1121326Sharti/*
2121326Sharti * Copyright (c) 1996-2003
3121326Sharti *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4121326Sharti * 	All rights reserved.
5121326Sharti *
6121326Sharti * Redistribution and use in source and binary forms, with or without
7121326Sharti * modification, are permitted provided that the following conditions
8121326Sharti * are met:
9121326Sharti * 1. Redistributions of source code must retain the above copyright
10121326Sharti *    notice, this list of conditions and the following disclaimer.
11121326Sharti * 2. Redistributions in binary form must reproduce the above copyright
12121326Sharti *    notice, this list of conditions and the following disclaimer in the
13121326Sharti *    documentation and/or other materials provided with the distribution.
14121326Sharti *
15121326Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16121326Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17121326Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18121326Sharti * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19121326Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20121326Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21121326Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22121326Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23121326Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24121326Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25121326Sharti * SUCH DAMAGE.
26121326Sharti *
27121326Sharti * Author: Hartmut Brandt <harti@freebsd.org>
28121326Sharti *
29131826Sharti * $Begemot: libunimsg/netnatm/saal/saal_sscop.c,v 1.11 2004/07/08 08:22:13 brandt Exp $
30121326Sharti *
31121326Sharti * Core SSCOP code (ITU-T Q.2110)
32121326Sharti */
33121326Sharti
34121326Sharti#include <netnatm/saal/sscop.h>
35121326Sharti#include <netnatm/saal/sscoppriv.h>
36121326Sharti
37121326Sharti#ifndef FAILURE
38121326Sharti#define FAILURE(S)
39121326Sharti#endif
40121326Sharti
41121326Sharti#define MKSTR(S)	#S
42121326Sharti
43121326Shartistatic const char *const sscop_sigs[] = {
44121326Sharti	MKSTR(SSCOP_ESTABLISH_request),
45121326Sharti	MKSTR(SSCOP_ESTABLISH_indication),
46121326Sharti	MKSTR(SSCOP_ESTABLISH_response),
47121326Sharti	MKSTR(SSCOP_ESTABLISH_confirm),
48121326Sharti	MKSTR(SSCOP_RELEASE_request),
49121326Sharti	MKSTR(SSCOP_RELEASE_indication),
50121326Sharti	MKSTR(SSCOP_RELEASE_confirm),
51121326Sharti	MKSTR(SSCOP_DATA_request),
52121326Sharti	MKSTR(SSCOP_DATA_indication),
53121326Sharti	MKSTR(SSCOP_UDATA_request),
54121326Sharti	MKSTR(SSCOP_UDATA_indication),
55121326Sharti	MKSTR(SSCOP_RECOVER_indication),
56121326Sharti	MKSTR(SSCOP_RECOVER_response),
57121326Sharti	MKSTR(SSCOP_RESYNC_request),
58121326Sharti	MKSTR(SSCOP_RESYNC_indication),
59121326Sharti	MKSTR(SSCOP_RESYNC_response),
60121326Sharti	MKSTR(SSCOP_RESYNC_confirm),
61121326Sharti	MKSTR(SSCOP_RETRIEVE_request),
62121326Sharti	MKSTR(SSCOP_RETRIEVE_indication),
63121326Sharti	MKSTR(SSCOP_RETRIEVE_COMPL_indication),
64121326Sharti};
65121326Sharti
66121326Shartistatic const char *const sscop_msigs[] = {
67121326Sharti	MKSTR(SSCOP_MDATA_request),
68121326Sharti	MKSTR(SSCOP_MDATA_indication),
69121326Sharti	MKSTR(SSCOP_MERROR_indication),
70121326Sharti};
71121326Sharti
72121326Shartistatic const char *const states[] = {
73121326Sharti	MKSTR(SSCOP_IDLE),
74121326Sharti	MKSTR(SSCOP_OUT_PEND),
75121326Sharti	MKSTR(SSCOP_IN_PEND),
76121326Sharti	MKSTR(SSCOP_OUT_DIS_PEND),
77121326Sharti	MKSTR(SSCOP_OUT_RESYNC_PEND),
78121326Sharti	MKSTR(SSCOP_IN_RESYNC_PEND),
79121326Sharti	MKSTR(SSCOP_OUT_REC_PEND),
80121326Sharti	MKSTR(SSCOP_REC_PEND),
81121326Sharti	MKSTR(SSCOP_IN_REC_PEND),
82121326Sharti	MKSTR(SSCOP_READY),
83121326Sharti};
84121326Sharti
85121326Sharti#ifdef SSCOP_DEBUG
86121326Shartistatic const char *const events[] = {
87121326Sharti	MKSTR(SIG_BGN),
88121326Sharti	MKSTR(SIG_BGAK),
89121326Sharti	MKSTR(SIG_END),
90121326Sharti	MKSTR(SIG_ENDAK),
91121326Sharti	MKSTR(SIG_RS),
92121326Sharti	MKSTR(SIG_RSAK),
93121326Sharti	MKSTR(SIG_BGREJ),
94121326Sharti	MKSTR(SIG_SD),
95121326Sharti	MKSTR(SIG_ER),
96121326Sharti	MKSTR(SIG_POLL),
97121326Sharti	MKSTR(SIG_STAT),
98121326Sharti	MKSTR(SIG_USTAT),
99121326Sharti	MKSTR(SIG_UD),
100121326Sharti	MKSTR(SIG_MD),
101121326Sharti	MKSTR(SIG_ERAK),
102121326Sharti
103121326Sharti	MKSTR(SIG_T_CC),
104121326Sharti	MKSTR(SIG_T_POLL),
105121326Sharti	MKSTR(SIG_T_KA),
106121326Sharti	MKSTR(SIG_T_NR),
107121326Sharti	MKSTR(SIG_T_IDLE),
108121326Sharti
109121326Sharti	MKSTR(SIG_PDU_Q),
110121326Sharti	MKSTR(SIG_USER_DATA),
111121326Sharti	MKSTR(SIG_ESTAB_REQ),
112121326Sharti	MKSTR(SIG_ESTAB_RESP),
113121326Sharti	MKSTR(SIG_RELEASE_REQ),
114121326Sharti	MKSTR(SIG_RECOVER),
115121326Sharti	MKSTR(SIG_SYNC_REQ),
116121326Sharti	MKSTR(SIG_SYNC_RESP),
117121326Sharti	MKSTR(SIG_UDATA),
118121326Sharti	MKSTR(SIG_MDATA),
119121326Sharti	MKSTR(SIG_UPDU_Q),
120121326Sharti	MKSTR(SIG_MPDU_Q),
121121326Sharti	MKSTR(SIG_RETRIEVE),
122121326Sharti};
123121326Sharti
124121326Shartistatic const char *const pdus[] = {
125121326Sharti	"illegale PDU type 0",		/* no PDU type 0 */
126121326Sharti	MKSTR(PDU_BGN),
127121326Sharti	MKSTR(PDU_BGAK),
128121326Sharti	MKSTR(PDU_END),
129121326Sharti	MKSTR(PDU_ENDAK),
130121326Sharti	MKSTR(PDU_RS),
131121326Sharti	MKSTR(PDU_RSAK),
132121326Sharti	MKSTR(PDU_BGREJ),
133121326Sharti	MKSTR(PDU_SD),
134121326Sharti	MKSTR(PDU_ER),
135121326Sharti	MKSTR(PDU_POLL),
136121326Sharti	MKSTR(PDU_STAT),
137121326Sharti	MKSTR(PDU_USTAT),
138121326Sharti	MKSTR(PDU_UD),
139121326Sharti	MKSTR(PDU_MD),
140121326Sharti	MKSTR(PDU_ERAK),
141121326Sharti};
142121326Sharti#endif
143121326Sharti
144121326ShartiMEMINIT();
145121326Sharti
146121326Shartistatic void sscop_signal(struct sscop *, u_int, struct sscop_msg *);
147121326Shartistatic void sscop_save_signal(struct sscop *, u_int, struct sscop_msg *);
148121326Shartistatic void handle_sigs(struct sscop *);
149121326Shartistatic void sscop_set_state(struct sscop *, u_int);
150121326Sharti
151121326Sharti/************************************************************/
152121326Sharti
153121326Sharti
154121326Sharti/************************************************************/
155121326Sharti/*
156121326Sharti * Queue macros
157121326Sharti */
158121326Sharti#define SSCOP_MSG_FREE(MSG)						\
159121326Sharti    do {								\
160121326Sharti	if(MSG) {							\
161121326Sharti		MBUF_FREE((MSG)->m);					\
162121326Sharti		MSG_FREE((MSG));					\
163121326Sharti	}								\
164121326Sharti    } while(0)
165121326Sharti
166121326Sharti
167121326Sharti#define QFIND(Q,RN)							\
168121326Sharti    ({									\
169121326Sharti	struct sscop_msg *_msg = NULL, *_m;				\
170121326Sharti	MSGQ_FOREACH(_m, (Q)) {						\
171121326Sharti		if(_m->seqno == (RN)) {					\
172121326Sharti			_msg = _m;					\
173121326Sharti			break;						\
174121326Sharti		}							\
175121326Sharti	}								\
176121326Sharti	_msg;								\
177121326Sharti    })
178121326Sharti
179121326Sharti#define QINSERT(Q,M)							\
180121326Sharti    do {								\
181121326Sharti	struct sscop_msg *_msg = NULL, *_m;				\
182121326Sharti	MSGQ_FOREACH(_m, (Q)) {						\
183121326Sharti		if (_m->seqno > (M)->seqno) {				\
184121326Sharti			_msg = _m;					\
185121326Sharti			break;						\
186121326Sharti		}							\
187121326Sharti	}								\
188121326Sharti	if (_msg != NULL)							\
189121326Sharti		MSGQ_INSERT_BEFORE(_msg, (M));				\
190121326Sharti	else								\
191121326Sharti		MSGQ_APPEND((Q), (M));					\
192121326Sharti    } while (0)
193121326Sharti
194121326Sharti
195121326Sharti/*
196121326Sharti * Send an error indication to the management plane.
197121326Sharti */
198121326Sharti#define MAAL_ERROR(S,E,C) 						\
199121326Sharti    do {								\
200121326Sharti	VERBOSE(S, SSCOP_DBG_USIG, ((S), (S)->aarg,			\
201121326Sharti	    "MAA-Signal %s in state %s", 				\
202121326Sharti	    sscop_msigs[SSCOP_MERROR_indication], states[(S)->state]));	\
203121326Sharti	(S)->funcs->send_manage((S), (S)->aarg,				\
204121326Sharti	    SSCOP_MERROR_indication, NULL, (E), (C));			\
205121326Sharti    } while(0)
206121326Sharti
207121326Sharti#define MAAL_DATA(S,M) 							\
208121326Sharti    do {								\
209121326Sharti	VERBOSE(S, SSCOP_DBG_USIG, ((S), (S)->aarg,			\
210121326Sharti	    "MAA-Signal %s in state %s",				\
211121326Sharti	    sscop_msigs[SSCOP_MDATA_indication], states[(S)->state]));	\
212121326Sharti	(S)->funcs->send_manage((S), (S)->aarg,				\
213121326Sharti	    SSCOP_MDATA_indication, (M), 0, 0);				\
214121326Sharti    } while(0)
215121326Sharti
216121326Sharti#define AAL_DATA(S,D,M,N)						\
217121326Sharti    do {								\
218121326Sharti	VERBOSE(S, SSCOP_DBG_USIG, ((S), (S)->aarg,			\
219121326Sharti	    "AA-Signal %s in state %s",					\
220121326Sharti	    sscop_sigs[D], states[(S)->state]));			\
221121326Sharti	(S)->funcs->send_upper((S), (S)->aarg, (D), (M), (N));		\
222121326Sharti    } while(0)
223121326Sharti
224121326Sharti#define AAL_SIG(S,D)							\
225121326Sharti    do {								\
226121326Sharti	VERBOSE(S, SSCOP_DBG_USIG, ((S), (S)->aarg,			\
227121326Sharti	    "AA-Signal %s in state %s",					\
228121326Sharti	    sscop_sigs[D], states[(S)->state]));			\
229121326Sharti	(S)->funcs->send_upper((S), (S)->aarg, (D), NULL, 0);		\
230121326Sharti    } while(0)
231121326Sharti
232121326Sharti#ifdef SSCOP_DEBUG
233121326Sharti#define AAL_SEND(S,M) do {						\
234121326Sharti	if (ISVERBOSE(S, SSCOP_DBG_PDU))				\
235121326Sharti		sscop_dump_pdu(S, "tx", (M));				\
236121326Sharti	(S)->funcs->send_lower((S), (S)->aarg, (M));			\
237121326Sharti    } while(0)
238121326Sharti#else
239121326Sharti#define AAL_SEND(S,M) (S)->funcs->send_lower((S), (S)->aarg, (M))
240121326Sharti#endif
241121326Sharti
242121326Sharti
243121326Sharti/*
244121326Sharti * Free a save user-to-user data buffer and set the pointer to zero
245121326Sharti * to signal, that it is free.
246121326Sharti */
247121326Sharti#define FREE_UU(F)							\
248121326Sharti	do {								\
249121326Sharti		if(sscop->F) {						\
250121326Sharti			MBUF_FREE(sscop->F);				\
251121326Sharti			sscop->F = NULL;				\
252121326Sharti		}							\
253121326Sharti	} while(0)
254121326Sharti
255121326Sharti#define SET_UU(F,U)							\
256121326Sharti	do {								\
257121326Sharti		FREE_UU(F);						\
258121326Sharti		sscop->F = U->m;					\
259121326Sharti		U->m = NULL;						\
260121326Sharti		SSCOP_MSG_FREE(U);					\
261121326Sharti	} while(0)
262121326Sharti
263121326Sharti#define AAL_UU_SIGNAL(S, SIG, M, PL, SN)				\
264121326Sharti	do {								\
265121326Sharti		if(MBUF_LEN((M)->m) > 0) { 				\
266121326Sharti			MBUF_UNPAD((M)->m,(PL));			\
267121326Sharti			AAL_DATA((S), (SIG), (M)->m, (SN)); 		\
268121326Sharti			(M)->m = NULL;					\
269121326Sharti		} else {						\
270121326Sharti			AAL_DATA((S), (SIG), NULL, (SN));		\
271121326Sharti		}							\
272121326Sharti		SSCOP_MSG_FREE((M));					\
273121326Sharti	} while(0)
274121326Sharti
275121326Sharti
276121326Sharti
277121326ShartiTIMER_FUNC(cc, CC)
278121326ShartiTIMER_FUNC(nr, NR)
279121326ShartiTIMER_FUNC(ka, KA)
280121326ShartiTIMER_FUNC(poll, POLL)
281121326ShartiTIMER_FUNC(idle, IDLE)
282121326Sharti
283121326Sharti/************************************************************/
284121326Sharti/*
285121326Sharti * INSTANCE AND TYPE HANDLING.
286121326Sharti */
287121326Sharti#ifdef SSCOP_DEBUG
288121326Shartistatic void
289121326Shartisscop_dump_pdu(struct sscop *sscop, const char *dir,
290121326Sharti    const struct SSCOP_MBUF_T *m)
291121326Sharti{
292121326Sharti	u_int32_t v1, v2, v3, v4;
293121326Sharti	u_int size = MBUF_LEN(m);
294121326Sharti	u_int n, i;
295121326Sharti
296121326Sharti	if (size < 8)
297121326Sharti		return;
298121326Sharti
299121326Sharti	v1 = MBUF_TRAIL32(m, -1);
300121326Sharti	v2 = MBUF_TRAIL32(m, -2);
301121326Sharti
302121326Sharti	switch ((v1 >> 24) & 0xf) {
303121326Sharti
304121326Sharti	  case 0:
305121326Sharti		return;
306121326Sharti
307121326Sharti	  case PDU_BGN:
308121326Sharti		sscop->funcs->verbose(sscop, sscop->aarg,
309121326Sharti		    "%s BGN n(mr)=%u n(sq)=%u pl=%u",
310121326Sharti		    dir, v1 & 0xffffff, v2 & 0xff, (v1 >> 30) & 0x3);
311121326Sharti		return;
312121326Sharti
313121326Sharti	  case PDU_BGAK:
314121326Sharti		sscop->funcs->verbose(sscop, sscop->aarg,
315121326Sharti		    "%s BGAK n(mr)=%u pl=%u",
316121326Sharti		    dir, v1 & 0xffffff, (v1 >> 30) & 0x3);
317121326Sharti		return;
318121326Sharti
319121326Sharti	  case PDU_END:
320121326Sharti		sscop->funcs->verbose(sscop, sscop->aarg,
321121326Sharti		    "%s END r=%u s=%u pl=%u",
322121326Sharti		    dir, (v1 >> 29) & 1, (v1 >> 28) & 1, (v1 >> 30) & 0x3);
323121326Sharti		return;
324121326Sharti
325121326Sharti	  case PDU_ENDAK:
326121326Sharti		sscop->funcs->verbose(sscop, sscop->aarg, "%s ENDAK", dir);
327121326Sharti		return;
328121326Sharti
329121326Sharti	  case PDU_RS:
330121326Sharti		sscop->funcs->verbose(sscop, sscop->aarg,
331121326Sharti		    "%s RS n(mr)=%u n(sq)=%u pl=%u",
332121326Sharti		    dir, v1 & 0xffffff, v2 & 0xff, (v1 >> 30) & 0x3);
333121326Sharti		return;
334121326Sharti
335121326Sharti	  case PDU_RSAK:
336121326Sharti		sscop->funcs->verbose(sscop, sscop->aarg, "%s RSAK n(mr)=%u",
337121326Sharti		    dir, v1 & 0xffffff);
338121326Sharti		return;
339121326Sharti
340121326Sharti	  case PDU_BGREJ:
341121326Sharti		sscop->funcs->verbose(sscop, sscop->aarg, "%s BGREJ pl=%u",
342121326Sharti		    dir, (v1 >> 30) & 0x3);
343121326Sharti		return;
344121326Sharti
345121326Sharti	  case PDU_SD:
346121326Sharti		sscop->funcs->verbose(sscop, sscop->aarg, "%s SD n(s)=%u pl=%u",
347121326Sharti		    dir, v1 & 0xffffff, (v1 >> 30) & 0x3);
348121326Sharti		return;
349121326Sharti
350121326Sharti	  case PDU_ER:
351121326Sharti		sscop->funcs->verbose(sscop, sscop->aarg, "%s ER n(mr)=%u n(sq)=%u",
352121326Sharti		    dir, v1 & 0xffffff, v2 & 0xff);
353121326Sharti		return;
354121326Sharti
355121326Sharti	  case PDU_POLL:
356121326Sharti		sscop->funcs->verbose(sscop, sscop->aarg, "%s POLL n(s)=%u n(ps)=%u",
357121326Sharti		    dir, v1 & 0xffffff, v2 & 0xffffff);
358121326Sharti		return;
359121326Sharti
360121326Sharti	  case PDU_STAT:
361121326Sharti		if (size < 12)
362121326Sharti			return;
363121326Sharti		v3 = MBUF_TRAIL32(m, -3);
364121326Sharti		sscop->funcs->verbose(sscop, sscop->aarg,
365121326Sharti		    "%s STAT n(r)=%u n(mr)=%u n(ps)=%u",
366121326Sharti		    dir, v1 & 0xffffff, v2 & 0xffffff, v3 & 0xffffff);
367121326Sharti		n = (size - 12) / 4;
368121326Sharti		for (i = 0; i < (size - 12) / 4; i++, n--) {
369121326Sharti			v4 = MBUF_TRAIL32(m, -4 - (int)i);
370121326Sharti			sscop->funcs->verbose(sscop, sscop->aarg,
371121326Sharti			    "   LE(%u)=%u", n, v4 & 0xffffff);
372121326Sharti		}
373121326Sharti		return;
374121326Sharti
375121326Sharti	  case PDU_USTAT:
376121326Sharti		if (size < 16)
377121326Sharti			return;
378121326Sharti		sscop->funcs->verbose(sscop, sscop->aarg,
379121326Sharti		    "%s STAT n(r)=%u n(mr)=%u LE1=%u LE2=%u",
380121326Sharti		    dir, v1 & 0xffffff, v2 & 0xffffff,
381121326Sharti		    MBUF_TRAIL32(m, -4) & 0xffffff,
382121326Sharti		    MBUF_TRAIL32(m, -3) & 0xffffff);
383121326Sharti		return;
384121326Sharti
385121326Sharti	  case PDU_UD:
386121326Sharti		sscop->funcs->verbose(sscop, sscop->aarg,
387121326Sharti		    "%s UD pl=%u", dir, (v1 >> 30) & 0x3);
388121326Sharti		return;
389121326Sharti
390121326Sharti	  case PDU_MD:
391121326Sharti		sscop->funcs->verbose(sscop, sscop->aarg,
392121326Sharti		    "%s MD pl=%u", dir, (v1 >> 30) & 0x3);
393121326Sharti		return;
394121326Sharti
395121326Sharti	  case PDU_ERAK:
396121326Sharti		sscop->funcs->verbose(sscop, sscop->aarg,
397121326Sharti		    "%s ERAK n(mr)=%u", dir, v1 & 0xffffff);
398121326Sharti		return;
399121326Sharti	}
400121326Sharti}
401121326Sharti#endif
402121326Sharti
403121326Sharti
404121326Sharti/*
405121326Sharti * Initialize state of variables
406121326Sharti */
407121326Shartistatic void
408121326Shartisscop_init(struct sscop *sscop)
409121326Sharti{
410121326Sharti	sscop->state = SSCOP_IDLE;
411121326Sharti
412121326Sharti	sscop->vt_sq = 0;
413121326Sharti	sscop->vr_sq = 0;
414121326Sharti	sscop->clear_buffers = 1;
415121326Sharti
416121326Sharti	sscop->ll_busy = 0;
417121326Sharti
418121326Sharti	sscop->rxq = 0;
419121326Sharti}
420121326Sharti
421121326Shartistatic void
422121326Shartisscop_clear(struct sscop *sscop)
423121326Sharti{
424121326Sharti	TIMER_STOP(sscop, cc);
425121326Sharti	TIMER_STOP(sscop, ka);
426121326Sharti	TIMER_STOP(sscop, nr);
427121326Sharti	TIMER_STOP(sscop, idle);
428121326Sharti	TIMER_STOP(sscop, poll);
429121326Sharti
430121326Sharti	FREE_UU(uu_bgn);
431121326Sharti	FREE_UU(uu_bgak);
432121326Sharti	FREE_UU(uu_bgrej);
433121326Sharti	FREE_UU(uu_end);
434121326Sharti	FREE_UU(uu_rs);
435121326Sharti
436121326Sharti	MSGQ_CLEAR(&sscop->xq);
437121326Sharti	MSGQ_CLEAR(&sscop->uxq);
438121326Sharti	MSGQ_CLEAR(&sscop->mxq);
439121326Sharti	MSGQ_CLEAR(&sscop->xbuf);
440121326Sharti	MSGQ_CLEAR(&sscop->rbuf);
441121326Sharti
442121326Sharti	SIGQ_CLEAR(&sscop->sigs);
443121326Sharti	SIGQ_CLEAR(&sscop->saved_sigs);
444121326Sharti}
445121326Sharti
446121326Sharti
447121326Sharti/*
448121326Sharti * Allocate instance memory, initialize the state of all variables.
449121326Sharti */
450121326Shartistruct sscop *
451121326Shartisscop_create(void *a, const struct sscop_funcs *funcs)
452121326Sharti{
453121326Sharti	struct sscop *sscop;
454121326Sharti
455121326Sharti	MEMZALLOC(sscop, struct sscop *, sizeof(struct sscop));
456121326Sharti	if (sscop == NULL)
457121326Sharti		return (NULL);
458121326Sharti
459121326Sharti	if (a == NULL)
460121326Sharti		sscop->aarg = sscop;
461121326Sharti	else
462121326Sharti		sscop->aarg = a;
463121326Sharti	sscop->funcs = funcs;
464121326Sharti
465121326Sharti	sscop->maxk = MAXK;
466121326Sharti	sscop->maxj = MAXJ;
467121326Sharti	sscop->maxcc = MAXCC;
468121326Sharti	sscop->maxpd = MAXPD;
469121326Sharti	sscop->maxstat = MAXSTAT;
470121326Sharti	sscop->timercc = TIMERCC;
471121326Sharti	sscop->timerka = TIMERKA;
472121326Sharti	sscop->timernr = TIMERNR;
473121326Sharti	sscop->timerpoll = TIMERPOLL;
474121326Sharti	sscop->timeridle = TIMERIDLE;
475121326Sharti	sscop->robustness = 0;
476121326Sharti	sscop->poll_after_rex = 0;
477121326Sharti	sscop->mr = MAXMR;
478121326Sharti
479121326Sharti	TIMER_INIT(sscop, cc);
480121326Sharti	TIMER_INIT(sscop, nr);
481121326Sharti	TIMER_INIT(sscop, ka);
482121326Sharti	TIMER_INIT(sscop, poll);
483121326Sharti	TIMER_INIT(sscop, idle);
484121326Sharti
485121326Sharti	MSGQ_INIT(&sscop->xq);
486121326Sharti	MSGQ_INIT(&sscop->uxq);
487121326Sharti	MSGQ_INIT(&sscop->mxq);
488121326Sharti	MSGQ_INIT(&sscop->rbuf);
489121326Sharti	MSGQ_INIT(&sscop->xbuf);
490121326Sharti
491121326Sharti	SIGQ_INIT(&sscop->sigs);
492121326Sharti	SIGQ_INIT(&sscop->saved_sigs);
493121326Sharti
494121326Sharti	sscop_init(sscop);
495121326Sharti
496121326Sharti	return (sscop);
497121326Sharti}
498121326Sharti
499121326Sharti/*
500121326Sharti * Free all resources in a sscop instance
501121326Sharti */
502121326Shartivoid
503121326Shartisscop_destroy(struct sscop *sscop)
504121326Sharti{
505121326Sharti	sscop_reset(sscop);
506121326Sharti
507121326Sharti	MEMFREE(sscop);
508121326Sharti}
509121326Sharti
510121326Sharti/*
511121326Sharti * Reset the SSCOP instance.
512121326Sharti */
513121326Shartivoid
514121326Shartisscop_reset(struct sscop *sscop)
515121326Sharti{
516121326Sharti	sscop_clear(sscop);
517121326Sharti	sscop_init(sscop);
518121326Sharti}
519121326Sharti
520121326Shartivoid
521121326Shartisscop_getparam(const struct sscop *sscop, struct sscop_param *p)
522121326Sharti{
523121326Sharti	p->timer_cc = sscop->timercc;
524121326Sharti	p->timer_poll = sscop->timerpoll;
525121326Sharti	p->timer_keep_alive = sscop->timerka;
526121326Sharti	p->timer_no_response = sscop->timernr;
527121326Sharti	p->timer_idle = sscop->timeridle;
528121326Sharti	p->maxk = sscop->maxk;
529121326Sharti	p->maxj = sscop->maxj;
530121326Sharti	p->maxcc = sscop->maxcc;
531121326Sharti	p->maxpd = sscop->maxpd;
532121326Sharti	p->maxstat = sscop->maxstat;
533121326Sharti	p->mr = sscop->mr;
534121326Sharti	p->flags = 0;
535121326Sharti	if(sscop->robustness)
536121326Sharti		p->flags |= SSCOP_ROBUST;
537121326Sharti	if(sscop->poll_after_rex)
538121326Sharti		p->flags |= SSCOP_POLLREX;
539121326Sharti}
540121326Sharti
541121326Shartiint
542121326Shartisscop_setparam(struct sscop *sscop, struct sscop_param *p, u_int *pmask)
543121326Sharti{
544121326Sharti	u_int mask = *pmask;
545121326Sharti
546121326Sharti	/* can change only in idle state */
547121326Sharti	if (sscop->state != SSCOP_IDLE)
548121326Sharti		return (EISCONN);
549121326Sharti
550121326Sharti	*pmask = 0;
551121326Sharti
552121326Sharti	/*
553121326Sharti	 * first check all parameters
554121326Sharti	 */
555121326Sharti	if ((mask & SSCOP_SET_TCC) && p->timer_cc == 0)
556121326Sharti		*pmask |= SSCOP_SET_TCC;
557121326Sharti	if ((mask & SSCOP_SET_TPOLL) && p->timer_poll == 0)
558121326Sharti		*pmask |= SSCOP_SET_TPOLL;
559121326Sharti	if ((mask & SSCOP_SET_TKA) && p->timer_keep_alive == 0)
560121326Sharti		*pmask |= SSCOP_SET_TKA;
561121326Sharti	if ((mask & SSCOP_SET_TNR) && p->timer_no_response == 0)
562121326Sharti		*pmask |= SSCOP_SET_TNR;
563121326Sharti	if ((mask & SSCOP_SET_TIDLE) && p->timer_idle == 0)
564121326Sharti		*pmask |= SSCOP_SET_TIDLE;
565121326Sharti	if ((mask & SSCOP_SET_MAXK) && p->maxk > MAXMAXK)
566121326Sharti		*pmask |= SSCOP_SET_MAXK;
567121326Sharti	if ((mask & SSCOP_SET_MAXJ) && p->maxj > MAXMAXJ)
568121326Sharti		*pmask |= SSCOP_SET_MAXJ;
569121326Sharti	if ((mask & SSCOP_SET_MAXCC) && p->maxcc > 255)
570121326Sharti		*pmask |= SSCOP_SET_MAXCC;
571121326Sharti	if ((mask & SSCOP_SET_MAXPD) && p->maxpd >= (1 << 24))
572121326Sharti		*pmask |= SSCOP_SET_MAXPD;
573121326Sharti	if ((mask & SSCOP_SET_MAXSTAT) &&
574121326Sharti	    ((p->maxstat & 1) == 0 || p->maxstat == 1 || p->maxstat == 2 ||
575121326Sharti	    p->maxstat * 4 > MAXMAXK - 8))
576121326Sharti		*pmask |= SSCOP_SET_MAXSTAT;
577121326Sharti	if ((mask & SSCOP_SET_MR) && p->mr >= (1 << 24) - 1)
578121326Sharti		*pmask |= SSCOP_SET_MR;
579121326Sharti
580121326Sharti	if (*pmask)
581121326Sharti		return (EINVAL);
582121326Sharti
583121326Sharti
584121326Sharti	/*
585121326Sharti	 * now set it
586121326Sharti	 */
587121326Sharti	if (mask & SSCOP_SET_TCC)
588121326Sharti		sscop->timercc = p->timer_cc;
589121326Sharti
590121326Sharti	if (mask & SSCOP_SET_TPOLL)
591121326Sharti		sscop->timerpoll = p->timer_poll;
592121326Sharti
593121326Sharti	if (mask & SSCOP_SET_TKA)
594121326Sharti		sscop->timerka = p->timer_keep_alive;
595121326Sharti
596121326Sharti	if (mask & SSCOP_SET_TNR)
597121326Sharti		sscop->timernr = p->timer_no_response;
598121326Sharti
599121326Sharti	if (mask & SSCOP_SET_TIDLE)
600121326Sharti		sscop->timeridle = p->timer_idle;
601121326Sharti
602121326Sharti	if (mask & SSCOP_SET_MAXK)
603121326Sharti		sscop->maxk = p->maxk;
604121326Sharti	if (mask & SSCOP_SET_MAXJ)
605121326Sharti		sscop->maxj = p->maxj;
606121326Sharti
607121326Sharti	if (mask & SSCOP_SET_MAXCC)
608121326Sharti		sscop->maxcc = p->maxcc;
609121326Sharti	if (mask & SSCOP_SET_MAXPD)
610121326Sharti		sscop->maxpd = p->maxpd;
611121326Sharti	if (mask & SSCOP_SET_MAXSTAT)
612121326Sharti		sscop->maxstat = p->maxstat;
613121326Sharti
614121326Sharti	if (mask & SSCOP_SET_MR)
615121326Sharti		sscop->mr = p->mr;
616121326Sharti
617121326Sharti	if (mask & SSCOP_SET_ROBUST)
618121326Sharti		sscop->robustness = ((p->flags & SSCOP_ROBUST) != 0);
619121326Sharti
620121326Sharti	if (mask & SSCOP_SET_POLLREX)
621121326Sharti		sscop->poll_after_rex = ((p->flags & SSCOP_POLLREX) != 0);
622121326Sharti
623121326Sharti	return (0);
624121326Sharti}
625121326Sharti
626121326Shartienum sscop_state
627121326Shartisscop_getstate(const struct sscop *sscop)
628121326Sharti{
629121326Sharti	return (sscop->state);
630121326Sharti}
631121326Sharti
632121326Sharti
633121326Sharti/************************************************************/
634121326Sharti/*
635121326Sharti * EXTERNAL INPUT SIGNAL MAPPING
636121326Sharti */
637121326Sharti
638121326Sharti/*
639121326Sharti * Map AA signal to SSCOP internal signal
640121326Sharti */
641121326Shartiint
642121326Shartisscop_aasig(struct sscop *sscop, enum sscop_aasig sig,
643121326Sharti    struct SSCOP_MBUF_T *m, u_int arg)
644121326Sharti{
645121326Sharti	struct sscop_msg *msg;
646121326Sharti
647121326Sharti	if (sig >= sizeof(sscop_sigs)/sizeof(sscop_sigs[0])) {
648121326Sharti		VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg,
649121326Sharti		    "AA-Signal %u - bad signal", sig));
650121326Sharti		MBUF_FREE(m);
651121326Sharti		return (EINVAL);
652121326Sharti	}
653121326Sharti	VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg,
654121326Sharti	    "AA-Signal %s in state %s with%s message",
655121326Sharti	    sscop_sigs[sig], states[sscop->state], m ? "" : "out"));
656121326Sharti
657121326Sharti	MSG_ALLOC(msg);
658121326Sharti	if (msg == NULL) {
659121326Sharti		FAILURE("sscop: cannot allocate aasig");
660121326Sharti		MBUF_FREE(m);
661121326Sharti		return (ENOMEM);
662121326Sharti	}
663121326Sharti
664121326Sharti	switch(sig) {
665121326Sharti
666121326Sharti	  case SSCOP_ESTABLISH_request:
667121326Sharti		msg->m = m;
668121326Sharti		msg->rexmit = arg;
669121326Sharti		sscop_signal(sscop, SIG_ESTAB_REQ, msg);
670121326Sharti		break;
671121326Sharti
672121326Sharti	  case SSCOP_ESTABLISH_response:
673121326Sharti		msg->m = m;
674121326Sharti		msg->rexmit = arg;
675121326Sharti		sscop_signal(sscop, SIG_ESTAB_RESP, msg);
676121326Sharti		break;
677121326Sharti
678121326Sharti	  case SSCOP_RELEASE_request:
679121326Sharti		msg->m = m;
680121326Sharti		sscop_signal(sscop, SIG_RELEASE_REQ, msg);
681121326Sharti		break;
682121326Sharti
683121326Sharti	  case SSCOP_DATA_request:
684121326Sharti		msg->m = m;
685121326Sharti		sscop_signal(sscop, SIG_USER_DATA, msg);
686121326Sharti		break;
687121326Sharti
688121326Sharti	  case SSCOP_UDATA_request:
689121326Sharti		msg->m = m;
690121326Sharti		sscop_signal(sscop, SIG_UDATA, msg);
691121326Sharti		break;
692121326Sharti
693121326Sharti	  case SSCOP_RECOVER_response:
694121326Sharti		MBUF_FREE(m);
695121326Sharti		MSG_FREE(msg);
696121326Sharti		sscop_signal(sscop, SIG_RECOVER, NULL);
697121326Sharti		break;
698121326Sharti
699121326Sharti	  case SSCOP_RESYNC_request:
700121326Sharti		msg->m = m;
701121326Sharti		sscop_signal(sscop, SIG_SYNC_REQ, msg);
702121326Sharti		break;
703121326Sharti
704121326Sharti	  case SSCOP_RESYNC_response:
705121326Sharti		MBUF_FREE(m);
706121326Sharti		MSG_FREE(msg);
707121326Sharti		sscop_signal(sscop, SIG_SYNC_RESP, NULL);
708121326Sharti		break;
709121326Sharti
710121326Sharti	  case SSCOP_RETRIEVE_request:
711121326Sharti		MBUF_FREE(m);
712121326Sharti		msg->rexmit = arg;
713121326Sharti		sscop_signal(sscop, SIG_RETRIEVE, msg);
714121326Sharti		break;
715121326Sharti
716121326Sharti	  case SSCOP_ESTABLISH_indication:
717121326Sharti	  case SSCOP_ESTABLISH_confirm:
718121326Sharti	  case SSCOP_RELEASE_indication:
719121326Sharti	  case SSCOP_RELEASE_confirm:
720121326Sharti	  case SSCOP_DATA_indication:
721121326Sharti	  case SSCOP_UDATA_indication:
722121326Sharti	  case SSCOP_RECOVER_indication:
723121326Sharti	  case SSCOP_RESYNC_indication:
724121326Sharti	  case SSCOP_RESYNC_confirm:
725121326Sharti	  case SSCOP_RETRIEVE_indication:
726121326Sharti	  case SSCOP_RETRIEVE_COMPL_indication:
727121326Sharti		MBUF_FREE(m);
728121326Sharti		MSG_FREE(msg);
729121326Sharti		return EINVAL;
730121326Sharti	}
731121326Sharti
732121326Sharti	return 0;
733121326Sharti}
734121326Sharti
735121326Sharti/*
736121326Sharti * Signal from layer management.
737121326Sharti */
738121326Shartiint
739121326Shartisscop_maasig(struct sscop *sscop, enum sscop_maasig sig, struct SSCOP_MBUF_T *m)
740121326Sharti{
741121326Sharti	struct sscop_msg *msg;
742121326Sharti
743121326Sharti	if (sig >= sizeof(sscop_msigs)/sizeof(sscop_msigs[0])) {
744121326Sharti		VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg,
745121326Sharti		    "MAA-Signal %u - bad signal", sig));
746121326Sharti		MBUF_FREE(m);
747121326Sharti		return (EINVAL);
748121326Sharti	}
749121326Sharti	VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg,
750121326Sharti	    "MAA-Signal %s in state %s with%s message",
751121326Sharti	    sscop_msigs[sig], states[sscop->state], m ? "" : "out"));
752121326Sharti
753121326Sharti	MSG_ALLOC(msg);
754121326Sharti	if (msg == NULL) {
755121326Sharti		FAILURE("sscop: cannot allocate maasig");
756121326Sharti		MBUF_FREE(m);
757121326Sharti		return (ENOMEM);
758121326Sharti	}
759121326Sharti
760121326Sharti	switch (sig) {
761121326Sharti
762121326Sharti	  case SSCOP_MDATA_request:
763121326Sharti		msg->m = m;
764121326Sharti		sscop_signal(sscop, SIG_MDATA, msg);
765121326Sharti		break;
766121326Sharti
767121326Sharti	  case SSCOP_MDATA_indication:
768121326Sharti	  case SSCOP_MERROR_indication:
769121326Sharti		MBUF_FREE(m);
770121326Sharti		MSG_FREE(msg);
771121326Sharti		return (EINVAL);
772121326Sharti	}
773121326Sharti	return (0);
774121326Sharti}
775121326Sharti
776121326Sharti/*
777121326Sharti * Map PDU to SSCOP signal.
778121326Sharti */
779121326Shartivoid
780121326Shartisscop_input(struct sscop *sscop, struct SSCOP_MBUF_T *m)
781121326Sharti{
782121326Sharti	struct sscop_msg *msg;
783121326Sharti	union pdu pdu;
784121326Sharti	u_int size;
785121326Sharti
786121326Sharti	MSG_ALLOC(msg);
787121326Sharti	if(msg == NULL) {
788121326Sharti		FAILURE("sscop: cannot allocate in pdu msg");
789121326Sharti		MBUF_FREE(m);
790121326Sharti		return;
791121326Sharti	}
792121326Sharti
793121326Sharti	msg->m = m;
794121326Sharti	msg->rexmit = 0;
795121326Sharti
796121326Sharti	size = MBUF_LEN(m);
797121326Sharti
798121326Sharti	if(size % 4 != 0 || size < 4)
799121326Sharti		goto err;
800121326Sharti
801121326Sharti	pdu.sscop_null = MBUF_TRAIL32(m, -1);
802121326Sharti
803121326Sharti	VERBOSE(sscop, SSCOP_DBG_PDU, (sscop, sscop->aarg,
804121326Sharti	    "got %s, size=%u", pdus[pdu.sscop_type], size));
805121326Sharti
806121326Sharti#ifdef SSCOP_DEBUG
807121326Sharti#define ENSURE(C,F)	if(!(C)) { VERBOSE(sscop, SSCOP_DBG_PDU, F); goto err; }
808121326Sharti#else
809121326Sharti#define ENSURE(C,F)	if(!(C)) goto err
810121326Sharti#endif
811121326Sharti
812121326Sharti#ifdef SSCOP_DEBUG
813121326Sharti	if (ISVERBOSE(sscop, SSCOP_DBG_PDU))
814121326Sharti		sscop_dump_pdu(sscop, "rx", m);
815121326Sharti#endif
816121326Sharti
817121326Sharti	switch(pdu.sscop_type) {
818121326Sharti
819121326Sharti          default:
820121326Sharti		ENSURE(0, (sscop, sscop->aarg,
821121326Sharti		    "Bad PDU type %u", pdu.sscop_type));
822121326Sharti		break;
823121326Sharti
824121326Sharti	  case PDU_BGN:
825121326Sharti		ENSURE(size >= 8U, (sscop, sscop->aarg,
826121326Sharti			"PDU_BGN size=%u", size));
827121326Sharti		ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg,
828121326Sharti			"PDU_BGN size=%u pl=%u", size, pdu.sscop_pl));
829121326Sharti		ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg,
830121326Sharti			"PDU_BGN size=%u", size));
831121326Sharti		sscop_signal(sscop, SIG_BGN, msg);
832121326Sharti		break;
833121326Sharti
834121326Sharti	  case PDU_BGAK:
835121326Sharti		ENSURE(size >= 8U, (sscop, sscop->aarg,
836121326Sharti			"PDU_BGAK size=%u", size));
837121326Sharti		ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg,
838121326Sharti			"PDU_BGAK size=%u pl=%u", size, pdu.sscop_pl));
839121326Sharti		ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg,
840121326Sharti			"PDU_BGAK size=%u", size));
841121326Sharti		sscop_signal(sscop, SIG_BGAK, msg);
842121326Sharti		break;
843121326Sharti
844121326Sharti	  case PDU_END:
845121326Sharti		ENSURE(size >= 8U, (sscop, sscop->aarg,
846121326Sharti			"PDU_END size=%u", size));
847121326Sharti		ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg,
848121326Sharti			"PDU_END size=%u pl=%u", size, pdu.sscop_pl));
849121326Sharti		ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg,
850121326Sharti			"PDU_END size=%u", size));
851121326Sharti		sscop_signal(sscop, SIG_END, msg);
852121326Sharti		break;
853121326Sharti
854121326Sharti	  case PDU_ENDAK:
855121326Sharti		ENSURE(size == 8U, (sscop, sscop->aarg,
856121326Sharti			"PDU_ENDAK size=%u", size));
857121326Sharti		sscop_signal(sscop, SIG_ENDAK, msg);
858121326Sharti		break;
859121326Sharti
860121326Sharti	  case PDU_BGREJ:
861121326Sharti		ENSURE(size >= 8U, (sscop, sscop->aarg,
862121326Sharti			"PDU_BGREJ size=%u", size));
863121326Sharti		ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg,
864121326Sharti			"PDU_BGREJ size=%u pl=%u", size, pdu.sscop_pl));
865121326Sharti		ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg,
866121326Sharti			"PDU_BGREJ size=%u", size));
867121326Sharti		sscop_signal(sscop, SIG_BGREJ, msg);
868121326Sharti		break;
869121326Sharti
870121326Sharti	  case PDU_SD:
871121326Sharti		ENSURE(size >= 4U + pdu.sscop_pl, (sscop, sscop->aarg,
872121326Sharti			"PDU_SD size=%u pl=%u", size, pdu.sscop_pl));
873121326Sharti		ENSURE(size <= 4U + sscop->maxk, (sscop, sscop->aarg,
874121326Sharti			"PDU_SD size=%u", size));
875121326Sharti		sscop_signal(sscop, SIG_SD, msg);
876121326Sharti		break;
877121326Sharti
878121326Sharti	  case PDU_UD:
879121326Sharti		ENSURE(size >= 4U + pdu.sscop_pl, (sscop, sscop->aarg,
880121326Sharti			"PDU_UD size=%u pl=%u", size, pdu.sscop_pl));
881121326Sharti		ENSURE(size <= 4U + sscop->maxk, (sscop, sscop->aarg,
882121326Sharti			"PDU_UD size=%u", size));
883121326Sharti		sscop_signal(sscop, SIG_UD, msg);
884121326Sharti		break;
885121326Sharti
886121326Sharti	  case PDU_MD:
887121326Sharti		ENSURE(size >= 4U + pdu.sscop_pl, (sscop, sscop->aarg,
888121326Sharti			"PDU_MD size=%u pl=%u", size, pdu.sscop_pl));
889121326Sharti		ENSURE(size <= 4U + sscop->maxk, (sscop, sscop->aarg,
890121326Sharti			"PDU_MD size=%u", size));
891121326Sharti		sscop_signal(sscop, SIG_MD, msg);
892121326Sharti		break;
893121326Sharti
894121326Sharti	  case PDU_POLL:
895121326Sharti		ENSURE(size == 8U, (sscop, sscop->aarg,
896121326Sharti			"PDU_POLL size=%u", size));
897121326Sharti		sscop_signal(sscop, SIG_POLL, msg);
898121326Sharti		break;
899121326Sharti
900121326Sharti	  case PDU_STAT:
901121326Sharti		ENSURE(size >= 12U, (sscop, sscop->aarg,
902121326Sharti			"PDU_STAT size=%u", size));
903121326Sharti		ENSURE(size <= 12U + 4 * sscop->maxstat, (sscop, sscop->aarg,
904121326Sharti			"PDU_STAT size=%u", size));
905121326Sharti		sscop_signal(sscop, SIG_STAT, msg);
906121326Sharti		break;
907121326Sharti
908121326Sharti	  case PDU_RS:
909121326Sharti		ENSURE(size >= 8U, (sscop, sscop->aarg,
910121326Sharti			"PDU_RS size=%u", size));
911121326Sharti		ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg,
912121326Sharti			"PDU_RS size=%u pl=%u", size, pdu.sscop_pl));
913121326Sharti		ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg,
914121326Sharti			"PDU_RS size=%u", size));
915121326Sharti		sscop_signal(sscop, SIG_RS, msg);
916121326Sharti		break;
917121326Sharti
918121326Sharti	  case PDU_RSAK:
919121326Sharti		ENSURE(size == 8U, (sscop, sscop->aarg,
920121326Sharti			"PDU_RSAK size=%u", size));
921121326Sharti		sscop_signal(sscop, SIG_RSAK, msg);
922121326Sharti		break;
923121326Sharti
924121326Sharti	  case PDU_ER:
925121326Sharti		ENSURE(size == 8U, (sscop, sscop->aarg,
926121326Sharti			"PDU_ER size=%u", size));
927121326Sharti		sscop_signal(sscop, SIG_ER, msg);
928121326Sharti		break;
929121326Sharti
930121326Sharti	  case PDU_ERAK:
931121326Sharti		ENSURE(size == 8U, (sscop, sscop->aarg,
932121326Sharti			"PDU_ERAK size=%u", size));
933121326Sharti		sscop_signal(sscop, SIG_ERAK, msg);
934121326Sharti		break;
935121326Sharti
936121326Sharti	  case PDU_USTAT:
937121326Sharti		ENSURE(size == 16U, (sscop, sscop->aarg,
938121326Sharti			"PDU_ERAK size=%u", size));
939121326Sharti		sscop_signal(sscop, SIG_USTAT, msg);
940121326Sharti		break;
941121326Sharti	}
942121326Sharti#undef ENSURE
943121326Sharti	return;
944121326Sharti
945121326Sharti  err:
946121326Sharti	MAAL_ERROR(sscop, 'U', 0);
947121326Sharti	SSCOP_MSG_FREE(msg);
948121326Sharti}
949121326Sharti
950121326Sharti/************************************************************/
951121326Sharti/*
952121326Sharti * UTILITIES
953121326Sharti */
954121326Sharti
955121326Sharti/*
956121326Sharti * Move the receiver window by N packets
957121326Sharti */
958121326Shartiu_int
959121326Shartisscop_window(struct sscop *sscop, u_int n)
960121326Sharti{
961121326Sharti	sscop->vr_mr += n;
962121326Sharti	return (SEQNO_DIFF(sscop->vr_mr, sscop->vr_r));
963121326Sharti}
964121326Sharti
965121326Sharti/*
966121326Sharti * Lower layer busy handling
967121326Sharti */
968121326Shartiu_int
969121326Shartisscop_setbusy(struct sscop *sscop, int busy)
970121326Sharti{
971121326Sharti	u_int old = sscop->ll_busy;
972121326Sharti
973121326Sharti	if (busy > 0)
974121326Sharti		sscop->ll_busy = 1;
975121326Sharti	else if (busy == 0) {
976121326Sharti		sscop->ll_busy = 0;
977121326Sharti		if(old)
978121326Sharti			handle_sigs(sscop);
979121326Sharti	}
980121326Sharti
981121326Sharti	return (old);
982121326Sharti}
983121326Sharti
984121326Sharticonst char *
985121326Shartisscop_signame(enum sscop_aasig sig)
986121326Sharti{
987121326Sharti	static char str[40];
988121326Sharti
989121326Sharti	if (sig >= sizeof(sscop_sigs)/sizeof(sscop_sigs[0])) {
990121326Sharti		sprintf(str, "BAD SSCOP_AASIG %u", sig);
991121326Sharti		return (str);
992121326Sharti	} else {
993121326Sharti		return (sscop_sigs[sig]);
994121326Sharti	}
995121326Sharti}
996121326Sharti
997121326Sharticonst char *
998121326Shartisscop_msigname(enum sscop_maasig sig)
999121326Sharti{
1000121326Sharti	static char str[40];
1001121326Sharti
1002121326Sharti	if (sig >= sizeof(sscop_msigs)/sizeof(sscop_msigs[0])) {
1003121326Sharti		sprintf(str, "BAD SSCOP_MAASIG %u", sig);
1004121326Sharti		return (str);
1005121326Sharti	} else {
1006121326Sharti		return (sscop_msigs[sig]);
1007121326Sharti	}
1008121326Sharti}
1009121326Sharti
1010121326Sharticonst char *
1011121326Shartisscop_statename(enum sscop_state s)
1012121326Sharti{
1013121326Sharti	static char str[40];
1014121326Sharti
1015121326Sharti	if (s >= sizeof(states)/sizeof(states[0])) {
1016121326Sharti		sprintf(str, "BAD SSCOP_STATE %u", s);
1017121326Sharti		return (str);
1018121326Sharti	} else {
1019121326Sharti		return (states[s]);
1020121326Sharti	}
1021121326Sharti}
1022121326Sharti
1023121326Sharti
1024121326Sharti/************************************************************/
1025121326Sharti/*
1026121326Sharti * MACROS
1027121326Sharti */
1028121326Sharti
1029121326Sharti/*
1030121326Sharti * p 75: release buffers
1031121326Sharti */
1032121326Shartistatic void
1033121326Shartim_release_buffers(struct sscop *sscop)
1034121326Sharti{
1035121326Sharti	MSGQ_CLEAR(&sscop->xq);
1036121326Sharti	MSGQ_CLEAR(&sscop->xbuf);
1037121326Sharti	sscop->rxq = 0;
1038121326Sharti	MSGQ_CLEAR(&sscop->rbuf);
1039121326Sharti}
1040121326Sharti
1041121326Sharti/*
1042121326Sharti * P 75: Prepare retrival
1043121326Sharti */
1044121326Shartistatic void
1045121326Shartim_prepare_retrieval(struct sscop *sscop)
1046121326Sharti{
1047121326Sharti	struct sscop_msg *msg;
1048121326Sharti
1049121326Sharti	if (sscop->clear_buffers) {
1050121326Sharti		MSGQ_CLEAR(&sscop->xq);
1051121326Sharti		MSGQ_CLEAR(&sscop->xbuf);
1052121326Sharti	}
1053121326Sharti	MSGQ_FOREACH(msg, &sscop->xbuf)
1054121326Sharti		msg->rexmit = 0;
1055121326Sharti	sscop->rxq = 0;
1056121326Sharti
1057121326Sharti	MSGQ_CLEAR(&sscop->rbuf);
1058121326Sharti}
1059121326Sharti
1060121326Sharti/*
1061121326Sharti * P 75: Prepare retrival
1062121326Sharti */
1063121326Shartistatic void
1064121326Shartim_prepare_recovery(struct sscop *sscop)
1065121326Sharti{
1066121326Sharti	struct sscop_msg *msg;
1067121326Sharti
1068121326Sharti	if(sscop->clear_buffers) {
1069121326Sharti		MSGQ_CLEAR(&sscop->xq);
1070121326Sharti		MSGQ_CLEAR(&sscop->xbuf);
1071121326Sharti	}
1072121326Sharti	MSGQ_FOREACH(msg, &sscop->xbuf)
1073121326Sharti		msg->rexmit = 0;
1074121326Sharti	sscop->rxq = 0;
1075121326Sharti}
1076121326Sharti
1077121326Sharti
1078121326Sharti/*
1079121326Sharti * P 75: Clear transmitter
1080121326Sharti */
1081121326Shartistatic void
1082121326Shartim_clear_transmitter(struct sscop *sscop)
1083121326Sharti{
1084121326Sharti	if(!sscop->clear_buffers) {
1085121326Sharti		MSGQ_CLEAR(&sscop->xq);
1086121326Sharti		MSGQ_CLEAR(&sscop->xbuf);
1087121326Sharti	}
1088121326Sharti}
1089121326Sharti
1090121326Sharti
1091121326Sharti/*
1092121326Sharti * p 75: Deliver data
1093121326Sharti * Freeing the message is the responibility of the handler function.
1094121326Sharti */
1095121326Shartistatic void
1096121326Shartim_deliver_data(struct sscop *sscop)
1097121326Sharti{
1098121326Sharti	struct sscop_msg *msg;
1099121326Sharti	u_int sn;
1100121326Sharti
1101121326Sharti	if ((msg = MSGQ_GET(&sscop->rbuf)) == NULL)
1102121326Sharti		return;
1103121326Sharti
1104121326Sharti	if (sscop->clear_buffers) {
1105121326Sharti		MSGQ_CLEAR(&sscop->rbuf);
1106121326Sharti		return;
1107121326Sharti	}
1108121326Sharti
1109121326Sharti	sn = msg->seqno + 1;
1110121326Sharti	AAL_DATA(sscop, SSCOP_DATA_indication, msg->m, msg->seqno);
1111121326Sharti	MSG_FREE(msg);
1112121326Sharti
1113121326Sharti	while ((msg = MSGQ_GET(&sscop->rbuf)) != NULL) {
1114121326Sharti		ASSERT(msg->seqno == sn);
1115121326Sharti		if (++sn == SSCOP_MAXSEQNO)
1116121326Sharti			sn = 0;
1117121326Sharti		AAL_DATA(sscop, SSCOP_DATA_indication, msg->m, msg->seqno);
1118121326Sharti		MSG_FREE(msg);
1119121326Sharti	}
1120121326Sharti}
1121121326Sharti
1122121326Sharti/*
1123121326Sharti * P 75: Initialize state variables
1124121326Sharti */
1125121326Shartistatic void
1126121326Shartim_initialize_state(struct sscop *sscop)
1127121326Sharti{
1128121326Sharti	sscop->vt_s = 0;
1129121326Sharti	sscop->vt_ps = 0;
1130121326Sharti	sscop->vt_a = 0;
1131121326Sharti
1132121326Sharti	sscop->vt_pa = 1;
1133121326Sharti	sscop->vt_pd = 0;
1134121326Sharti	sscop->credit = 1;
1135121326Sharti
1136121326Sharti	sscop->vr_r = 0;
1137121326Sharti	sscop->vr_h = 0;
1138121326Sharti}
1139121326Sharti
1140121326Sharti/*
1141121326Sharti * p 76: Data retrieval
1142121326Sharti */
1143121326Shartistatic void
1144121326Shartim_data_retrieval(struct sscop *sscop, u_int rn)
1145121326Sharti{
1146121326Sharti	struct sscop_msg *s;
1147121326Sharti
1148121326Sharti	if (rn != SSCOP_RETRIEVE_UNKNOWN) {
1149121326Sharti		if(rn >= SSCOP_RETRIEVE_TOTAL)
1150121326Sharti			rn = sscop->vt_a;
1151121326Sharti		else
1152121326Sharti			rn++;
1153121326Sharti		while(rn >= sscop->vt_a && rn < sscop->vt_s) {
1154121326Sharti			if(rn == SSCOP_MAXSEQNO) rn = 0;
1155121326Sharti			if((s = QFIND(&sscop->xbuf, rn)) != NULL) {
1156121326Sharti				MSGQ_REMOVE(&sscop->xbuf, s);
1157121326Sharti				AAL_DATA(sscop, SSCOP_RETRIEVE_indication,
1158121326Sharti					s->m, 0);
1159121326Sharti				MSG_FREE(s);
1160121326Sharti			}
1161121326Sharti			rn++;
1162121326Sharti		}
1163121326Sharti	}
1164121326Sharti
1165121326Sharti	while((s = MSGQ_GET(&sscop->xq)) != NULL) {
1166121326Sharti		AAL_DATA(sscop, SSCOP_RETRIEVE_indication, s->m, 0);
1167121326Sharti		MSG_FREE(s);
1168121326Sharti	}
1169121326Sharti	AAL_SIG(sscop, SSCOP_RETRIEVE_COMPL_indication);
1170121326Sharti}
1171121326Sharti
1172121326Sharti/*
1173121326Sharti * P 76: Detect retransmission. PDU type must already be stripped.
1174121326Sharti */
1175121326Shartistatic int
1176121326Shartim_detect_retransmission(struct sscop *sscop, struct sscop_msg *msg)
1177121326Sharti{
1178121326Sharti	union bgn bgn;
1179121326Sharti
1180121326Sharti	bgn.sscop_null = MBUF_TRAIL32(msg->m, -1);
1181121326Sharti
1182121326Sharti	if (sscop->vr_sq == bgn.sscop_bgns)
1183121326Sharti		return (1);
1184121326Sharti
1185121326Sharti	sscop->vr_sq = bgn.sscop_bgns;
1186121326Sharti	return (0);
1187121326Sharti}
1188121326Sharti
1189121326Sharti/*
1190121326Sharti * P 76: Set POLL timer
1191121326Sharti */
1192121326Shartistatic void
1193121326Shartim_set_poll_timer(struct sscop *sscop)
1194121326Sharti{
1195121326Sharti	if(MSGQ_EMPTY(&sscop->xq) && sscop->vt_s == sscop->vt_a)
1196121326Sharti		TIMER_RESTART(sscop, ka);
1197121326Sharti	else
1198121326Sharti		TIMER_RESTART(sscop, poll);
1199121326Sharti}
1200121326Sharti
1201121326Sharti/*
1202121326Sharti * P 77: Reset data transfer timers
1203121326Sharti */
1204121326Shartistatic void
1205121326Shartim_reset_data_xfer_timers(struct sscop *sscop)
1206121326Sharti{
1207121326Sharti	TIMER_STOP(sscop, ka);
1208121326Sharti	TIMER_STOP(sscop, nr);
1209121326Sharti	TIMER_STOP(sscop, idle);
1210121326Sharti	TIMER_STOP(sscop, poll);
1211121326Sharti}
1212121326Sharti
1213121326Sharti/*
1214121326Sharti * P 77: Set data transfer timers
1215121326Sharti */
1216121326Shartistatic void
1217121326Shartim_set_data_xfer_timers(struct sscop *sscop)
1218121326Sharti{
1219121326Sharti	TIMER_RESTART(sscop, poll);
1220121326Sharti	TIMER_RESTART(sscop, nr);
1221121326Sharti}
1222121326Sharti
1223121326Sharti/*
1224121326Sharti * P 77: Initialize VR(MR)
1225121326Sharti */
1226121326Shartistatic void
1227121326Shartim_initialize_mr(struct sscop *sscop)
1228121326Sharti{
1229121326Sharti	sscop->vr_mr = sscop->mr;
1230121326Sharti}
1231121326Sharti
1232121326Sharti/************************************************************/
1233121326Sharti/*
1234121326Sharti * CONDITIONS
1235121326Sharti */
1236121326Shartistatic int
1237121326Shartic_ready_pduq(struct sscop *sscop)
1238121326Sharti{
1239121326Sharti	if (!sscop->ll_busy &&
1240121326Sharti	    (sscop->rxq != 0 ||
1241121326Sharti	    sscop->vt_s < sscop->vt_ms ||
1242121326Sharti	    TIMER_ISACT(sscop, idle)))
1243121326Sharti		return (1);
1244121326Sharti	return (0);
1245121326Sharti}
1246121326Sharti
1247121326Sharti/************************************************************/
1248121326Sharti/*
1249121326Sharti * SEND PDUS
1250121326Sharti */
1251121326Sharti
1252121326Sharti/*
1253121326Sharti * Send BG PDU.
1254121326Sharti */
1255121326Shartistatic void
1256121326Shartisend_bgn(struct sscop *sscop, struct SSCOP_MBUF_T *uu)
1257121326Sharti{
1258121326Sharti	union pdu pdu;
1259121326Sharti	union bgn bgn;
1260121326Sharti	struct SSCOP_MBUF_T *m;
1261121326Sharti
1262121326Sharti	pdu.sscop_null = 0;
1263121326Sharti	pdu.sscop_type = PDU_BGN;
1264121326Sharti	pdu.sscop_ns = sscop->vr_mr;
1265121326Sharti
1266121326Sharti	bgn.sscop_null = 0;
1267121326Sharti	bgn.sscop_bgns = sscop->vt_sq;
1268121326Sharti
1269121326Sharti	if(uu) {
1270121326Sharti		if ((m = MBUF_DUP(uu)) == NULL) {
1271121326Sharti			FAILURE("sscop: cannot allocate BGN");
1272121326Sharti			return;
1273121326Sharti		}
1274121326Sharti		pdu.sscop_pl += MBUF_PAD4(m);
1275121326Sharti	} else {
1276121326Sharti		if ((m = MBUF_ALLOC(8)) == NULL) {
1277121326Sharti			FAILURE("sscop: cannot allocate BGN");
1278121326Sharti			return;
1279121326Sharti		}
1280121326Sharti	}
1281121326Sharti
1282121326Sharti	MBUF_APPEND32(m, bgn.sscop_null);
1283121326Sharti	MBUF_APPEND32(m, pdu.sscop_null);
1284121326Sharti
1285121326Sharti	AAL_SEND(sscop, m);
1286121326Sharti}
1287121326Sharti
1288121326Sharti/*
1289121326Sharti * Send BGREJ PDU.
1290121326Sharti */
1291121326Shartistatic void
1292121326Shartisend_bgrej(struct sscop *sscop, struct SSCOP_MBUF_T *uu)
1293121326Sharti{
1294121326Sharti	union pdu pdu;
1295121326Sharti	union bgn bgn;
1296121326Sharti	struct SSCOP_MBUF_T *m;
1297121326Sharti
1298121326Sharti	pdu.sscop_null = 0;
1299121326Sharti	pdu.sscop_type = PDU_BGREJ;
1300121326Sharti	bgn.sscop_null = 0;
1301121326Sharti
1302121326Sharti	if(uu) {
1303121326Sharti		if((m = MBUF_DUP(uu)) == NULL) {
1304121326Sharti			FAILURE("sscop: cannot allocate BGREJ");
1305121326Sharti			return;
1306121326Sharti		}
1307121326Sharti		pdu.sscop_pl += MBUF_PAD4(m);
1308121326Sharti	} else {
1309121326Sharti		if((m = MBUF_ALLOC(8)) == NULL) {
1310121326Sharti			FAILURE("sscop: cannot allocate BGREJ");
1311121326Sharti			return;
1312121326Sharti		}
1313121326Sharti	}
1314121326Sharti
1315121326Sharti	MBUF_APPEND32(m, bgn.sscop_null);
1316121326Sharti	MBUF_APPEND32(m, pdu.sscop_null);
1317121326Sharti
1318121326Sharti	AAL_SEND(sscop, m);
1319121326Sharti}
1320121326Sharti
1321121326Sharti/*
1322121326Sharti * Send BGAK PDU.
1323121326Sharti */
1324121326Shartistatic void
1325121326Shartisend_bgak(struct sscop *sscop, struct SSCOP_MBUF_T *uu)
1326121326Sharti{
1327121326Sharti	union pdu pdu;
1328121326Sharti	union bgn bgn;
1329121326Sharti	struct SSCOP_MBUF_T *m;
1330121326Sharti
1331121326Sharti	pdu.sscop_null = 0;
1332121326Sharti	pdu.sscop_type = PDU_BGAK;
1333121326Sharti	pdu.sscop_ns = sscop->vr_mr;
1334121326Sharti	bgn.sscop_null = 0;
1335121326Sharti
1336121326Sharti	if(uu) {
1337121326Sharti		if((m = MBUF_DUP(uu)) == NULL) {
1338121326Sharti			FAILURE("sscop: cannot allocate BGAK");
1339121326Sharti			return;
1340121326Sharti		}
1341121326Sharti		pdu.sscop_pl += MBUF_PAD4(m);
1342121326Sharti	} else {
1343121326Sharti		if((m = MBUF_ALLOC(8)) == NULL) {
1344121326Sharti			FAILURE("sscop: cannot allocate BGAK");
1345121326Sharti			return;
1346121326Sharti		}
1347121326Sharti	}
1348121326Sharti
1349121326Sharti	MBUF_APPEND32(m, bgn.sscop_null);
1350121326Sharti	MBUF_APPEND32(m, pdu.sscop_null);
1351121326Sharti
1352121326Sharti	AAL_SEND(sscop, m);
1353121326Sharti}
1354121326Sharti
1355121326Sharti/*
1356121326Sharti * Send SD PDU. The function makes a duplicate of the message.
1357121326Sharti */
1358121326Shartistatic void
1359121326Shartisend_sd(struct sscop *sscop, struct SSCOP_MBUF_T *m, u_int seqno)
1360121326Sharti{
1361121326Sharti	union pdu pdu;
1362121326Sharti
1363121326Sharti	if((m = MBUF_DUP(m)) == NULL) {
1364121326Sharti		FAILURE("sscop: cannot allocate SD");
1365121326Sharti		return;
1366121326Sharti	}
1367121326Sharti
1368121326Sharti	pdu.sscop_null = 0;
1369121326Sharti	pdu.sscop_pl = 0;
1370121326Sharti	pdu.sscop_type = PDU_SD;
1371121326Sharti	pdu.sscop_ns = seqno;
1372121326Sharti
1373121326Sharti	pdu.sscop_pl += MBUF_PAD4(m);
1374121326Sharti
1375121326Sharti	MBUF_APPEND32(m, pdu.sscop_null);
1376121326Sharti
1377121326Sharti	AAL_SEND(sscop, m);
1378121326Sharti}
1379121326Sharti
1380121326Sharti/*
1381121326Sharti * Send a UD PDU. The caller must free the sscop msg part.
1382121326Sharti */
1383121326Shartistatic void
1384121326Shartisend_ud(struct sscop *sscop, struct SSCOP_MBUF_T *m)
1385121326Sharti{
1386121326Sharti	union pdu pdu;
1387121326Sharti
1388121326Sharti	pdu.sscop_null = 0;
1389121326Sharti	pdu.sscop_type = PDU_UD;
1390121326Sharti
1391121326Sharti	pdu.sscop_pl += MBUF_PAD4(m);
1392121326Sharti
1393121326Sharti	MBUF_APPEND32(m, pdu.sscop_null);
1394121326Sharti
1395121326Sharti	AAL_SEND(sscop, m);
1396121326Sharti}
1397121326Sharti
1398121326Sharti/*
1399121326Sharti * Send a MD PDU. The caller must free the sscop msg part.
1400121326Sharti */
1401121326Shartistatic void
1402121326Shartisend_md(struct sscop *sscop, struct SSCOP_MBUF_T *m)
1403121326Sharti{
1404121326Sharti	union pdu pdu;
1405121326Sharti
1406121326Sharti	pdu.sscop_null = 0;
1407121326Sharti	pdu.sscop_type = PDU_MD;
1408121326Sharti
1409121326Sharti	pdu.sscop_pl += MBUF_PAD4(m);
1410121326Sharti
1411121326Sharti	MBUF_APPEND32(m, pdu.sscop_null);
1412121326Sharti
1413121326Sharti	AAL_SEND(sscop, m);
1414121326Sharti}
1415121326Sharti
1416121326Sharti/*
1417121326Sharti * Send END PDU.
1418121326Sharti */
1419121326Shartistatic void
1420121326Shartisend_end(struct sscop *sscop, int src, struct SSCOP_MBUF_T *uu)
1421121326Sharti{
1422121326Sharti	union pdu pdu;
1423121326Sharti	struct SSCOP_MBUF_T *m;
1424121326Sharti
1425121326Sharti	sscop->last_end_src = src;
1426121326Sharti
1427121326Sharti	pdu.sscop_null = 0;
1428121326Sharti	pdu.sscop_s = src;
1429121326Sharti	pdu.sscop_type = PDU_END;
1430121326Sharti
1431121326Sharti	if(uu) {
1432121326Sharti		if((m = MBUF_DUP(uu)) == NULL) {
1433121326Sharti			FAILURE("sscop: cannot allocate END");
1434121326Sharti			return;
1435121326Sharti		}
1436121326Sharti		pdu.sscop_pl += MBUF_PAD4(m);
1437121326Sharti	} else {
1438121326Sharti		if((m = MBUF_ALLOC(8)) == NULL) {
1439121326Sharti			FAILURE("sscop: cannot allocate END");
1440121326Sharti			return;
1441121326Sharti		}
1442121326Sharti	}
1443121326Sharti
1444121326Sharti	MBUF_APPEND32(m, 0);
1445121326Sharti	MBUF_APPEND32(m, pdu.sscop_null);
1446121326Sharti
1447121326Sharti	AAL_SEND(sscop, m);
1448121326Sharti}
1449121326Sharti
1450121326Sharti/*
1451121326Sharti * Send USTAT PDU. List must be terminated by -1.
1452121326Sharti */
1453121326Shartistatic void
1454121326Shartisend_ustat(struct sscop *sscop, ...)
1455121326Sharti{
1456121326Sharti	va_list ap;
1457121326Sharti	int f;
1458121326Sharti	u_int n;
1459121326Sharti	union pdu pdu;
1460121326Sharti	union seqno seqno;
1461121326Sharti	struct SSCOP_MBUF_T *m;
1462121326Sharti
1463121326Sharti	va_start(ap, sscop);
1464121326Sharti	n = 0;
1465121326Sharti	while((f = va_arg(ap, int)) >= 0)
1466121326Sharti		n++;
1467121326Sharti	va_end(ap);
1468121326Sharti
1469121326Sharti	if((m = MBUF_ALLOC(n * 4 + 8)) == NULL) {
1470121326Sharti		FAILURE("sscop: cannot allocate USTAT");
1471121326Sharti		return;
1472121326Sharti	}
1473121326Sharti
1474121326Sharti	va_start(ap, sscop);
1475121326Sharti	while((f = va_arg(ap, int)) >= 0) {
1476121326Sharti		seqno.sscop_null = 0;
1477121326Sharti		seqno.sscop_n = f;
1478121326Sharti		MBUF_APPEND32(m, seqno.sscop_null);
1479121326Sharti	}
1480121326Sharti	va_end(ap);
1481121326Sharti
1482121326Sharti	seqno.sscop_null = 0;
1483121326Sharti	seqno.sscop_n = sscop->vr_mr;
1484121326Sharti	MBUF_APPEND32(m, seqno.sscop_null);
1485121326Sharti
1486121326Sharti	pdu.sscop_null = 0;
1487121326Sharti	pdu.sscop_type = PDU_USTAT;
1488121326Sharti	pdu.sscop_ns = sscop->vr_r;
1489121326Sharti	MBUF_APPEND32(m, pdu.sscop_null);
1490121326Sharti
1491121326Sharti	AAL_SEND(sscop, m);
1492121326Sharti}
1493121326Sharti
1494121326Sharti/*
1495121326Sharti * Send ER PDU.
1496121326Sharti */
1497121326Shartistatic void
1498121326Shartisend_er(struct sscop *sscop)
1499121326Sharti{
1500121326Sharti	union pdu pdu;
1501121326Sharti	union bgn bgn;
1502121326Sharti	struct SSCOP_MBUF_T *m;
1503121326Sharti
1504121326Sharti	pdu.sscop_null = 0;
1505121326Sharti	pdu.sscop_type = PDU_ER;
1506121326Sharti	pdu.sscop_ns = sscop->vr_mr;
1507121326Sharti
1508121326Sharti	bgn.sscop_null = 0;
1509121326Sharti	bgn.sscop_bgns = sscop->vt_sq;
1510121326Sharti
1511121326Sharti	if((m = MBUF_ALLOC(8)) == NULL) {
1512121326Sharti		FAILURE("sscop: cannot allocate ER");
1513121326Sharti		return;
1514121326Sharti	}
1515121326Sharti	MBUF_APPEND32(m, bgn.sscop_null);
1516121326Sharti	MBUF_APPEND32(m, pdu.sscop_null);
1517121326Sharti
1518121326Sharti	AAL_SEND(sscop, m);
1519121326Sharti}
1520121326Sharti
1521121326Sharti/*
1522121326Sharti * Send POLL PDU.
1523121326Sharti */
1524121326Shartistatic void
1525121326Shartisend_poll(struct sscop *sscop)
1526121326Sharti{
1527121326Sharti	union pdu pdu;
1528121326Sharti	union seqno seqno;
1529121326Sharti	struct SSCOP_MBUF_T *m;
1530121326Sharti
1531121326Sharti	seqno.sscop_null = 0;
1532121326Sharti	seqno.sscop_n = sscop->vt_ps;
1533121326Sharti
1534121326Sharti	pdu.sscop_null = 0;
1535121326Sharti	pdu.sscop_ns = sscop->vt_s;
1536121326Sharti	pdu.sscop_type = PDU_POLL;
1537121326Sharti
1538121326Sharti	if((m = MBUF_ALLOC(8)) == NULL) {
1539121326Sharti		FAILURE("sscop: cannot allocate POLL");
1540121326Sharti		return;
1541121326Sharti	}
1542121326Sharti	MBUF_APPEND32(m, seqno.sscop_null);
1543121326Sharti	MBUF_APPEND32(m, pdu.sscop_null);
1544121326Sharti
1545121326Sharti	AAL_SEND(sscop, m);
1546121326Sharti}
1547121326Sharti
1548121326Sharti/*
1549121326Sharti * Send STAT PDU. List is already in buffer.
1550121326Sharti */
1551121326Shartistatic void
1552121326Shartisend_stat(struct sscop *sscop, u_int nps, struct SSCOP_MBUF_T *m)
1553121326Sharti{
1554121326Sharti	union pdu pdu;
1555121326Sharti	union seqno seqno;
1556121326Sharti
1557121326Sharti	seqno.sscop_null = 0;
1558121326Sharti	seqno.sscop_n = nps;
1559121326Sharti	MBUF_APPEND32(m, seqno.sscop_null);
1560121326Sharti
1561121326Sharti	seqno.sscop_null = 0;
1562121326Sharti	seqno.sscop_n = sscop->vr_mr;
1563121326Sharti	MBUF_APPEND32(m, seqno.sscop_null);
1564121326Sharti
1565121326Sharti	pdu.sscop_null = 0;
1566121326Sharti	pdu.sscop_type = PDU_STAT;
1567121326Sharti	pdu.sscop_ns = sscop->vr_r;
1568121326Sharti	MBUF_APPEND32(m, pdu.sscop_null);
1569121326Sharti
1570121326Sharti	AAL_SEND(sscop, m);
1571121326Sharti}
1572121326Sharti
1573121326Sharti/*
1574121326Sharti * Send ENDAK PDU.
1575121326Sharti */
1576121326Shartistatic void
1577121326Shartisend_endak(struct sscop *sscop)
1578121326Sharti{
1579121326Sharti	union pdu pdu;
1580121326Sharti	union seqno seqno;
1581121326Sharti	struct SSCOP_MBUF_T *m;
1582121326Sharti
1583121326Sharti	seqno.sscop_null = 0;
1584121326Sharti	pdu.sscop_null = 0;
1585121326Sharti	pdu.sscop_type = PDU_ENDAK;
1586121326Sharti
1587121326Sharti	if((m = MBUF_ALLOC(8)) == NULL) {
1588121326Sharti		FAILURE("sscop: cannot allocate ENDAK");
1589121326Sharti		return;
1590121326Sharti	}
1591121326Sharti	MBUF_APPEND32(m, seqno.sscop_null);
1592121326Sharti	MBUF_APPEND32(m, pdu.sscop_null);
1593121326Sharti
1594121326Sharti	AAL_SEND(sscop, m);
1595121326Sharti}
1596121326Sharti
1597121326Sharti/*
1598121326Sharti * Send ERAK PDU.
1599121326Sharti */
1600121326Shartistatic void
1601121326Shartisend_erak(struct sscop *sscop)
1602121326Sharti{
1603121326Sharti	union pdu pdu;
1604121326Sharti	union seqno seqno;
1605121326Sharti	struct SSCOP_MBUF_T *m;
1606121326Sharti
1607121326Sharti	seqno.sscop_null = 0;
1608121326Sharti	pdu.sscop_null = 0;
1609121326Sharti	pdu.sscop_type = PDU_ERAK;
1610121326Sharti	pdu.sscop_ns = sscop->vr_mr;
1611121326Sharti
1612121326Sharti	if((m = MBUF_ALLOC(8)) == NULL) {
1613121326Sharti		FAILURE("sscop: cannot allocate ERAK");
1614121326Sharti		return;
1615121326Sharti	}
1616121326Sharti	MBUF_APPEND32(m, seqno.sscop_null);
1617121326Sharti	MBUF_APPEND32(m, pdu.sscop_null);
1618121326Sharti
1619121326Sharti	AAL_SEND(sscop, m);
1620121326Sharti}
1621121326Sharti
1622121326Sharti/*
1623121326Sharti * Send RS PDU
1624121326Sharti */
1625121326Shartistatic void
1626121326Shartisend_rs(struct sscop *sscop, int resend, struct SSCOP_MBUF_T *uu)
1627121326Sharti{
1628121326Sharti	union pdu pdu;
1629121326Sharti	union bgn bgn;
1630121326Sharti	struct SSCOP_MBUF_T *m;
1631121326Sharti
1632121326Sharti	pdu.sscop_null = 0;
1633121326Sharti	pdu.sscop_type = PDU_RS;
1634121326Sharti	pdu.sscop_ns = resend ? sscop->rs_mr : sscop->vr_mr;
1635121326Sharti
1636121326Sharti	bgn.sscop_null = 0;
1637121326Sharti	bgn.sscop_bgns = resend ? sscop->rs_sq : sscop->vt_sq;
1638121326Sharti
1639121326Sharti	sscop->rs_mr = pdu.sscop_ns;
1640121326Sharti	sscop->rs_sq = bgn.sscop_bgns;
1641121326Sharti
1642121326Sharti	if(uu) {
1643121326Sharti		if((m = MBUF_DUP(uu)) == NULL) {
1644121326Sharti			FAILURE("sscop: cannot allocate RS");
1645121326Sharti			return;
1646121326Sharti		}
1647121326Sharti		pdu.sscop_pl += MBUF_PAD4(m);
1648121326Sharti	} else {
1649121326Sharti		if((m = MBUF_ALLOC(8)) == NULL) {
1650121326Sharti			FAILURE("sscop: cannot allocate RS");
1651121326Sharti			return;
1652121326Sharti		}
1653121326Sharti	}
1654121326Sharti
1655121326Sharti	MBUF_APPEND32(m, bgn.sscop_null);
1656121326Sharti	MBUF_APPEND32(m, pdu.sscop_null);
1657121326Sharti
1658121326Sharti	AAL_SEND(sscop, m);
1659121326Sharti}
1660121326Sharti
1661121326Sharti/*
1662121326Sharti * Send RSAK pdu
1663121326Sharti */
1664121326Shartistatic void
1665121326Shartisend_rsak(struct sscop *sscop)
1666121326Sharti{
1667121326Sharti	union pdu pdu;
1668121326Sharti	union seqno seqno;
1669121326Sharti	struct SSCOP_MBUF_T *m;
1670121326Sharti
1671121326Sharti	seqno.sscop_null = 0;
1672121326Sharti	pdu.sscop_null = 0;
1673121326Sharti	pdu.sscop_type = PDU_RSAK;
1674121326Sharti	pdu.sscop_ns = sscop->vr_mr;
1675121326Sharti
1676121326Sharti	if((m = MBUF_ALLOC(8)) == NULL) {
1677121326Sharti		FAILURE("sscop: cannot allocate RSAK");
1678121326Sharti		return;
1679121326Sharti	}
1680121326Sharti
1681121326Sharti	MBUF_APPEND32(m, seqno.sscop_null);
1682121326Sharti	MBUF_APPEND32(m, pdu.sscop_null);
1683121326Sharti
1684121326Sharti	AAL_SEND(sscop, m);
1685121326Sharti}
1686121326Sharti
1687121326Sharti/************************************************************/
1688121326Sharti/*
1689121326Sharti * P 31; IDLE && AA-ESTABLISH-request
1690121326Sharti *	arg is UU data (opt).
1691121326Sharti */
1692121326Shartistatic void
1693121326Shartisscop_idle_establish_req(struct sscop *sscop, struct sscop_msg *uu)
1694121326Sharti{
1695121326Sharti	u_int br = uu->rexmit;
1696121326Sharti
1697121326Sharti	SET_UU(uu_bgn, uu);
1698121326Sharti
1699121326Sharti	m_clear_transmitter(sscop);
1700121326Sharti
1701121326Sharti	sscop->clear_buffers = br;
1702121326Sharti
1703121326Sharti	sscop->vt_cc = 1;
1704121326Sharti	sscop->vt_sq++;
1705121326Sharti
1706121326Sharti	m_initialize_mr(sscop);
1707121326Sharti
1708121326Sharti	send_bgn(sscop, sscop->uu_bgn);
1709121326Sharti
1710121326Sharti	TIMER_RESTART(sscop, cc);
1711121326Sharti
1712121326Sharti	sscop_set_state(sscop, SSCOP_OUT_PEND);
1713121326Sharti}
1714121326Sharti
1715121326Sharti/*
1716121326Sharti * P 31: IDLE && BGN PDU
1717121326Sharti *	arg is the received PDU (freed).
1718121326Sharti */
1719121326Shartistatic void
1720121326Shartisscop_idle_bgn(struct sscop *sscop, struct sscop_msg *msg)
1721121326Sharti{
1722121326Sharti	union pdu pdu;
1723121326Sharti	union bgn bgn;
1724121326Sharti
1725121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
1726121326Sharti
1727121326Sharti	if(sscop->robustness) {
1728121326Sharti		bgn.sscop_null = MBUF_STRIP32(msg->m);
1729121326Sharti		sscop->vr_sq = bgn.sscop_bgns;
1730121326Sharti	} else {
1731121326Sharti		if(m_detect_retransmission(sscop, msg)) {
1732121326Sharti			send_bgrej(sscop, sscop->uu_bgrej);
1733121326Sharti			SSCOP_MSG_FREE(msg);
1734121326Sharti			return;
1735121326Sharti		}
1736121326Sharti		(void)MBUF_STRIP32(msg->m);
1737121326Sharti	}
1738121326Sharti
1739121326Sharti	sscop->vt_ms = pdu.sscop_ns;
1740121326Sharti	sscop_set_state(sscop, SSCOP_IN_PEND);
1741121326Sharti
1742121326Sharti	AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0);
1743121326Sharti}
1744121326Sharti
1745121326Sharti/*
1746121326Sharti * p 31: IDLE && ENDAK PDU
1747121326Sharti * p 34: OUT_PEND && ENDAK PDU
1748121326Sharti * p 34: OUT_PEND && SD PDU
1749121326Sharti * p 34: OUT_PEND && ERAK PDU
1750121326Sharti * p 34: OUT_PEND && END PDU
1751121326Sharti * p 34: OUT_PEND && STAT PDU
1752121326Sharti * p 34: OUT_PEND && USTAT PDU
1753121326Sharti * p 34: OUT_PEND && POLL PDU
1754121326Sharti * p 36: OUT_PEND && RS PDU
1755121326Sharti * p 36: OUT_PEND && RSAK PDU
1756121326Sharti * p 40: OUTGOING_DISCONNECT_PENDING && SD PDU
1757121326Sharti * p 40: OUTGOING_DISCONNECT_PENDING && BGAK PDU
1758121326Sharti * p 40: OUTGOING_DISCONNECT_PENDING && POLL PDU
1759121326Sharti * p 40: OUTGOING_DISCONNECT_PENDING && STAT PDU
1760121326Sharti * p 40: OUTGOING_DISCONNECT_PENDING && USTAT PDU
1761121326Sharti * p 41: OUTGOING_DISCONNECT_PENDING && ERAK PDU
1762121326Sharti * p 42: OUTGOING_DISCONNECT_PENDING && ER PDU
1763121326Sharti * p 42: OUTGOING_DISCONNECT_PENDING && RS PDU
1764121326Sharti * p 42: OUTGOING_DISCONNECT_PENDING && RSAK PDU
1765121326Sharti * p 43: OUTGOING_RESYNC && ER PDU
1766121326Sharti * p 43: OUTGOING_RESYNC && POLL PDU
1767121326Sharti * p 44: OUTGOING_RESYNC && STAT PDU
1768121326Sharti * p 44: OUTGOING_RESYNC && USTAT PDU
1769121326Sharti * p 45: OUTGOING_RESYNC && BGAK PDU
1770121326Sharti * p 45: OUTGOING_RESYNC && SD PDU
1771121326Sharti * p 45: OUTGOING_RESYNC && ERAK PDU
1772121326Sharti * P 60: READY && BGAK PDU
1773121326Sharti * P 60: READY && ERAK PDU
1774121326Sharti *	arg is pdu (freed).
1775121326Sharti */
1776121326Shartistatic void
1777121326Shartisscop_ignore_pdu(struct sscop *sscop __unused, struct sscop_msg *msg)
1778121326Sharti{
1779121326Sharti	SSCOP_MSG_FREE(msg);
1780121326Sharti}
1781121326Sharti
1782121326Sharti/*
1783121326Sharti * p 31: IDLE && END PDU
1784121326Sharti *	arg is pdu (freed).
1785121326Sharti */
1786121326Shartistatic void
1787121326Shartisscop_idle_end(struct sscop *sscop, struct sscop_msg *msg)
1788121326Sharti{
1789121326Sharti	SSCOP_MSG_FREE(msg);
1790121326Sharti	send_endak(sscop);
1791121326Sharti}
1792121326Sharti
1793121326Sharti/*
1794121326Sharti * p 31: IDLE && ER PDU
1795121326Sharti *	arg is pdu (freed).
1796121326Sharti */
1797121326Shartistatic void
1798121326Shartisscop_idle_er(struct sscop *sscop, struct sscop_msg *msg)
1799121326Sharti{
1800121326Sharti	SSCOP_MSG_FREE(msg);
1801121326Sharti	MAAL_ERROR(sscop, 'L', 0);
1802121326Sharti	FREE_UU(uu_end);
1803121326Sharti	send_end(sscop, 1, NULL);
1804121326Sharti}
1805121326Sharti
1806121326Sharti/*
1807121326Sharti * p 31: IDLE && BGREJ PDU
1808121326Sharti *	arg is pdu (freed).
1809121326Sharti */
1810121326Shartistatic void
1811121326Shartisscop_idle_bgrej(struct sscop *sscop, struct sscop_msg *msg)
1812121326Sharti{
1813121326Sharti	SSCOP_MSG_FREE(msg);
1814121326Sharti	MAAL_ERROR(sscop, 'D', 0);
1815121326Sharti	FREE_UU(uu_end);
1816121326Sharti}
1817121326Sharti
1818121326Sharti/*
1819121326Sharti * p 32: IDLE && POLL PDU
1820121326Sharti *	arg is pdu (freed).
1821121326Sharti */
1822121326Shartistatic void
1823121326Shartisscop_idle_poll(struct sscop *sscop, struct sscop_msg *msg)
1824121326Sharti{
1825121326Sharti	SSCOP_MSG_FREE(msg);
1826121326Sharti	MAAL_ERROR(sscop, 'G', 0);
1827121326Sharti	FREE_UU(uu_end);
1828121326Sharti	send_end(sscop, 1, NULL);
1829121326Sharti}
1830121326Sharti
1831121326Sharti/*
1832121326Sharti * p 32: IDLE && SD PDU
1833121326Sharti *	arg is pdu (freed).
1834121326Sharti */
1835121326Shartistatic void
1836121326Shartisscop_idle_sd(struct sscop *sscop, struct sscop_msg *msg)
1837121326Sharti{
1838121326Sharti	SSCOP_MSG_FREE(msg);
1839121326Sharti	MAAL_ERROR(sscop, 'A', 0);
1840121326Sharti	FREE_UU(uu_end);
1841121326Sharti	send_end(sscop, 1, NULL);
1842121326Sharti}
1843121326Sharti
1844121326Sharti/*
1845121326Sharti * p 32: IDLE && BGAK PDU
1846121326Sharti *	arg is pdu (freed).
1847121326Sharti */
1848121326Shartistatic void
1849121326Shartisscop_idle_bgak(struct sscop *sscop, struct sscop_msg *msg)
1850121326Sharti{
1851121326Sharti	SSCOP_MSG_FREE(msg);
1852121326Sharti	MAAL_ERROR(sscop, 'C', 0);
1853121326Sharti	FREE_UU(uu_end);
1854121326Sharti	send_end(sscop, 1, NULL);
1855121326Sharti}
1856121326Sharti
1857121326Sharti/*
1858121326Sharti * p 32: IDLE && ERAK PDU
1859121326Sharti *	arg is pdu (freed).
1860121326Sharti */
1861121326Shartistatic void
1862121326Shartisscop_idle_erak(struct sscop *sscop, struct sscop_msg *msg)
1863121326Sharti{
1864121326Sharti	SSCOP_MSG_FREE(msg);
1865121326Sharti	MAAL_ERROR(sscop, 'M', 0);
1866121326Sharti	FREE_UU(uu_end);
1867121326Sharti	send_end(sscop, 1, NULL);
1868121326Sharti}
1869121326Sharti
1870121326Sharti/*
1871121326Sharti * p 32: IDLE && STAT PDU
1872121326Sharti *	arg is pdu (freed).
1873121326Sharti */
1874121326Shartistatic void
1875121326Shartisscop_idle_stat(struct sscop *sscop, struct sscop_msg *msg)
1876121326Sharti{
1877121326Sharti	SSCOP_MSG_FREE(msg);
1878121326Sharti	MAAL_ERROR(sscop, 'H', 0);
1879121326Sharti	FREE_UU(uu_end);
1880121326Sharti	send_end(sscop, 1, NULL);
1881121326Sharti}
1882121326Sharti
1883121326Sharti/*
1884121326Sharti * p 32: IDLE && USTAT PDU
1885121326Sharti *	arg is pdu (freed).
1886121326Sharti */
1887121326Shartistatic void
1888121326Shartisscop_idle_ustat(struct sscop *sscop, struct sscop_msg *msg)
1889121326Sharti{
1890121326Sharti	SSCOP_MSG_FREE(msg);
1891121326Sharti	MAAL_ERROR(sscop, 'I', 0);
1892121326Sharti	FREE_UU(uu_end);
1893121326Sharti	send_end(sscop, 1, NULL);
1894121326Sharti}
1895121326Sharti
1896121326Sharti/*
1897121326Sharti * p 33: IDLE & RS PDU
1898121326Sharti *	arg is pdu (freed).
1899121326Sharti */
1900121326Shartistatic void
1901121326Shartisscop_idle_rs(struct sscop *sscop, struct sscop_msg *msg)
1902121326Sharti{
1903121326Sharti	SSCOP_MSG_FREE(msg);
1904121326Sharti	MAAL_ERROR(sscop, 'J', 0);
1905121326Sharti	FREE_UU(uu_end);
1906121326Sharti	send_end(sscop, 1, NULL);
1907121326Sharti}
1908121326Sharti
1909121326Sharti/*
1910121326Sharti * p 33: IDLE & RSAK PDU
1911121326Sharti *	arg is pdu (freed).
1912121326Sharti */
1913121326Shartistatic void
1914121326Shartisscop_idle_rsak(struct sscop *sscop, struct sscop_msg *msg)
1915121326Sharti{
1916121326Sharti	SSCOP_MSG_FREE(msg);
1917121326Sharti	MAAL_ERROR(sscop, 'K', 0);
1918121326Sharti	FREE_UU(uu_end);
1919121326Sharti	send_end(sscop, 1, NULL);
1920121326Sharti}
1921121326Sharti
1922121326Sharti/*
1923121326Sharti * p 33: IDLE && PDU_Q
1924121326Sharti * p XX: OUTPEND && PDU_Q
1925121326Sharti * p 39: IN_PEND && PDU_Q
1926121326Sharti * p 45: OUT_RESYNC_PEND && PDU_Q
1927121326Sharti * p 48: IN_RESYNC_PEND && PDU_Q
1928121326Sharti *	no arg
1929121326Sharti */
1930121326Shartistatic void
1931121326Shartisscop_flush_pduq(struct sscop *sscop __unused, struct sscop_msg *unused __unused)
1932121326Sharti{
1933121326Sharti#if 0
1934121326Sharti	MSGQ_CLEAR(&sscop->xq);
1935121326Sharti#endif
1936121326Sharti}
1937121326Sharti
1938121326Sharti/*
1939121326Sharti * p 34: OUT_PEND && BGAK PDU
1940121326Sharti *	arg is pdu (freed).
1941121326Sharti */
1942121326Shartistatic void
1943121326Shartisscop_outpend_bgak(struct sscop *sscop, struct sscop_msg *msg)
1944121326Sharti{
1945121326Sharti	union pdu pdu;
1946121326Sharti
1947121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
1948121326Sharti	(void)MBUF_STRIP32(msg->m);
1949121326Sharti
1950121326Sharti	TIMER_STOP(sscop, cc);
1951121326Sharti	sscop->vt_ms = pdu.sscop_ns;
1952121326Sharti
1953121326Sharti	AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_confirm, msg, pdu.sscop_pl, 0);
1954121326Sharti
1955121326Sharti	m_initialize_state(sscop);
1956121326Sharti	m_set_data_xfer_timers(sscop);
1957121326Sharti
1958121326Sharti	sscop_set_state(sscop, SSCOP_READY);
1959121326Sharti}
1960121326Sharti
1961121326Sharti/*
1962121326Sharti * P 34: OUT_PEND && BGREJ PDU
1963121326Sharti */
1964121326Shartistatic void
1965121326Shartisscop_outpend_bgrej(struct sscop *sscop, struct sscop_msg *msg)
1966121326Sharti{
1967121326Sharti	union pdu pdu;
1968121326Sharti
1969121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
1970121326Sharti	(void)MBUF_STRIP32(msg->m);
1971121326Sharti
1972121326Sharti	TIMER_STOP(sscop, cc);
1973121326Sharti
1974121326Sharti	AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication, msg, pdu.sscop_pl, 0);
1975121326Sharti
1976121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
1977121326Sharti}
1978121326Sharti
1979121326Sharti/*
1980121326Sharti * P 35: OUT_PEND && TIMER_CC expiry
1981121326Sharti *	no arg
1982121326Sharti */
1983121326Shartistatic void
1984121326Shartisscop_outpend_tcc(struct sscop *sscop, struct sscop_msg *unused __unused)
1985121326Sharti{
1986121326Sharti	if(sscop->vt_cc >= sscop->maxcc) {
1987121326Sharti		MAAL_ERROR(sscop, 'O', 0);
1988121326Sharti		FREE_UU(uu_end);
1989121326Sharti		send_end(sscop, 1, NULL);
1990121326Sharti
1991121326Sharti		AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
1992121326Sharti
1993121326Sharti		sscop_set_state(sscop, SSCOP_IDLE);
1994121326Sharti	} else {
1995121326Sharti		sscop->vt_cc++;
1996121326Sharti		send_bgn(sscop, sscop->uu_bgn);
1997121326Sharti		TIMER_RESTART(sscop, cc);
1998121326Sharti	}
1999121326Sharti}
2000121326Sharti
2001121326Sharti/*
2002121326Sharti * P 35: OUT_PEND && RELEASE_REQ
2003121326Sharti *	arg is UU
2004121326Sharti */
2005121326Shartistatic void
2006121326Shartisscop_outpend_release_req(struct sscop *sscop, struct sscop_msg *uu)
2007121326Sharti{
2008121326Sharti	SET_UU(uu_end, uu);
2009121326Sharti
2010121326Sharti	TIMER_STOP(sscop, cc);
2011121326Sharti	sscop->vt_cc = 1;
2012121326Sharti	send_end(sscop, 0, sscop->uu_end);
2013121326Sharti	TIMER_RESTART(sscop, cc);
2014121326Sharti
2015121326Sharti	sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
2016121326Sharti}
2017121326Sharti
2018121326Sharti/*
2019121326Sharti * P 36: OUT_PEND && BGN PDU
2020121326Sharti *	arg is the received PDU (freed).
2021121326Sharti */
2022121326Shartistatic void
2023121326Shartisscop_outpend_bgn(struct sscop *sscop, struct sscop_msg *msg)
2024121326Sharti{
2025121326Sharti	union pdu pdu;
2026121326Sharti
2027121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
2028121326Sharti
2029121326Sharti	if(m_detect_retransmission(sscop, msg)) {
2030121326Sharti		SSCOP_MSG_FREE(msg);
2031121326Sharti		return;
2032121326Sharti	}
2033121326Sharti	(void)MBUF_STRIP32(msg->m);
2034121326Sharti
2035121326Sharti	TIMER_STOP(sscop, cc);
2036121326Sharti
2037121326Sharti	sscop->vt_ms = pdu.sscop_ns;
2038121326Sharti
2039121326Sharti	m_initialize_mr(sscop);
2040121326Sharti
2041121326Sharti	send_bgak(sscop, sscop->uu_bgak);
2042121326Sharti
2043121326Sharti	AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_confirm, msg, pdu.sscop_pl, 0);
2044121326Sharti
2045121326Sharti	m_initialize_state(sscop);
2046121326Sharti
2047121326Sharti	m_set_data_xfer_timers(sscop);
2048121326Sharti
2049121326Sharti	sscop_set_state(sscop, SSCOP_READY);
2050121326Sharti}
2051121326Sharti
2052121326Sharti/*
2053121326Sharti * p 37: IN_PEND && AA-ESTABLISH.response
2054121326Sharti *	arg is UU
2055121326Sharti */
2056121326Shartistatic void
2057121326Shartisscop_inpend_establish_resp(struct sscop *sscop, struct sscop_msg *uu)
2058121326Sharti{
2059121326Sharti	u_int br = uu->rexmit;
2060121326Sharti
2061121326Sharti	SET_UU(uu_bgak, uu);
2062121326Sharti
2063121326Sharti	m_clear_transmitter(sscop);
2064121326Sharti	sscop->clear_buffers = br;
2065121326Sharti	m_initialize_mr(sscop);
2066121326Sharti	send_bgak(sscop, sscop->uu_bgak);
2067121326Sharti	m_initialize_state(sscop);
2068121326Sharti	m_set_data_xfer_timers(sscop);
2069121326Sharti
2070121326Sharti	sscop_set_state(sscop, SSCOP_READY);
2071121326Sharti}
2072121326Sharti
2073121326Sharti/*
2074121326Sharti * p 37: IN_PEND && AA-RELEASE.request
2075121326Sharti *	arg is uu.
2076121326Sharti */
2077121326Shartistatic void
2078121326Shartisscop_inpend_release_req(struct sscop *sscop, struct sscop_msg *uu)
2079121326Sharti{
2080121326Sharti	SET_UU(uu_bgrej, uu);
2081121326Sharti
2082121326Sharti	send_bgrej(sscop, sscop->uu_bgrej);
2083121326Sharti
2084121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
2085121326Sharti}
2086121326Sharti
2087121326Sharti/*
2088121326Sharti * p 37: IN_PEND && BGN PDU
2089121326Sharti *	arg is pdu. (freed)
2090121326Sharti */
2091121326Shartistatic void
2092121326Shartisscop_inpend_bgn(struct sscop *sscop, struct sscop_msg *msg)
2093121326Sharti{
2094121326Sharti	union pdu pdu;
2095121326Sharti
2096121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
2097121326Sharti
2098121326Sharti	if(m_detect_retransmission(sscop, msg)) {
2099121326Sharti		SSCOP_MSG_FREE(msg);
2100121326Sharti		return;
2101121326Sharti	}
2102121326Sharti	(void)MBUF_STRIP32(msg->m);
2103121326Sharti
2104121326Sharti	sscop->vt_ms = pdu.sscop_ns;
2105121326Sharti
2106121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
2107121326Sharti	AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0);
2108121326Sharti}
2109121326Sharti
2110121326Sharti/*
2111121326Sharti * p 37: IN_PEND && ER PDU
2112121326Sharti *	arg is pdu (freed).
2113121326Sharti */
2114121326Shartistatic void
2115121326Shartisscop_inpend_er(struct sscop *sscop, struct sscop_msg *msg)
2116121326Sharti{
2117121326Sharti	MAAL_ERROR(sscop, 'L', 0);
2118121326Sharti	SSCOP_MSG_FREE(msg);
2119121326Sharti}
2120121326Sharti
2121121326Sharti/*
2122121326Sharti * p 37: IN_PEND && ENDAK PDU
2123121326Sharti *	arg is pdu (freed).
2124121326Sharti */
2125121326Shartistatic void
2126121326Shartisscop_inpend_endak(struct sscop *sscop, struct sscop_msg *msg)
2127121326Sharti{
2128121326Sharti	MAAL_ERROR(sscop, 'F', 0);
2129121326Sharti
2130121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2131121326Sharti
2132121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
2133121326Sharti
2134121326Sharti	SSCOP_MSG_FREE(msg);
2135121326Sharti}
2136121326Sharti
2137121326Sharti/*
2138121326Sharti * p 38: IN_PEND && BGAK PDU
2139121326Sharti *	arg is pdu (freed).
2140121326Sharti */
2141121326Shartistatic void
2142121326Shartisscop_inpend_bgak(struct sscop *sscop, struct sscop_msg *msg)
2143121326Sharti{
2144121326Sharti	MAAL_ERROR(sscop, 'C', 0);
2145121326Sharti
2146121326Sharti	SSCOP_MSG_FREE(msg);
2147121326Sharti}
2148121326Sharti
2149121326Sharti/*
2150121326Sharti * p 38: IN_PEND && BGREJ PDU
2151121326Sharti *	arg is pdu (freed).
2152121326Sharti */
2153121326Shartistatic void
2154121326Shartisscop_inpend_bgrej(struct sscop *sscop, struct sscop_msg *msg)
2155121326Sharti{
2156121326Sharti	MAAL_ERROR(sscop, 'D', 0);
2157121326Sharti
2158121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2159121326Sharti
2160121326Sharti	SSCOP_MSG_FREE(msg);
2161121326Sharti
2162121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
2163121326Sharti}
2164121326Sharti
2165121326Sharti/*
2166121326Sharti * p 38: IN_PEND && SD PDU
2167121326Sharti *	arg is pdu (freed).
2168121326Sharti */
2169121326Shartistatic void
2170121326Shartisscop_inpend_sd(struct sscop *sscop, struct sscop_msg *msg)
2171121326Sharti{
2172121326Sharti	MAAL_ERROR(sscop, 'A', 0);
2173121326Sharti
2174121326Sharti	SSCOP_MSG_FREE(msg);
2175121326Sharti
2176121326Sharti	FREE_UU(uu_end);
2177121326Sharti	send_end(sscop, 1, NULL);
2178121326Sharti
2179121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2180121326Sharti
2181121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
2182121326Sharti}
2183121326Sharti
2184121326Sharti/*
2185121326Sharti * p 38: IN_PEND && USTAT PDU
2186121326Sharti *	arg is pdu (freed).
2187121326Sharti */
2188121326Shartistatic void
2189121326Shartisscop_inpend_ustat(struct sscop *sscop, struct sscop_msg *msg)
2190121326Sharti{
2191121326Sharti	MAAL_ERROR(sscop, 'I', 0);
2192121326Sharti
2193121326Sharti	SSCOP_MSG_FREE(msg);
2194121326Sharti
2195121326Sharti	FREE_UU(uu_end);
2196121326Sharti	send_end(sscop, 1, NULL);
2197121326Sharti
2198121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2199121326Sharti
2200121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
2201121326Sharti}
2202121326Sharti
2203121326Sharti/*
2204121326Sharti * p 38: IN_PEND && STAT PDU
2205121326Sharti *	arg is pdu (freed).
2206121326Sharti */
2207121326Shartistatic void
2208121326Shartisscop_inpend_stat(struct sscop *sscop, struct sscop_msg *msg)
2209121326Sharti{
2210121326Sharti	MAAL_ERROR(sscop, 'H', 0);
2211121326Sharti
2212121326Sharti	SSCOP_MSG_FREE(msg);
2213121326Sharti
2214121326Sharti	FREE_UU(uu_end);
2215121326Sharti	send_end(sscop, 1, NULL);
2216121326Sharti
2217121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2218121326Sharti
2219121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
2220121326Sharti}
2221121326Sharti
2222121326Sharti/*
2223121326Sharti * p 38: IN_PEND && POLL PDU
2224121326Sharti *	arg is pdu (freed).
2225121326Sharti */
2226121326Shartistatic void
2227121326Shartisscop_inpend_poll(struct sscop *sscop, struct sscop_msg *msg)
2228121326Sharti{
2229121326Sharti	MAAL_ERROR(sscop, 'G', 0);
2230121326Sharti
2231121326Sharti	SSCOP_MSG_FREE(msg);
2232121326Sharti
2233121326Sharti	FREE_UU(uu_end);
2234121326Sharti	send_end(sscop, 1, NULL);
2235121326Sharti
2236121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2237121326Sharti
2238121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
2239121326Sharti}
2240121326Sharti
2241121326Sharti/*
2242121326Sharti * p 39: IN_PEND && ERAK PDU
2243121326Sharti *	arg is pdu (freed).
2244121326Sharti */
2245121326Shartistatic void
2246121326Shartisscop_inpend_erak(struct sscop *sscop, struct sscop_msg *msg)
2247121326Sharti{
2248121326Sharti	SSCOP_MSG_FREE(msg);
2249121326Sharti	MAAL_ERROR(sscop, 'M', 0);
2250121326Sharti}
2251121326Sharti
2252121326Sharti/*
2253121326Sharti * p 39: IN_PEND & RS PDU
2254121326Sharti *	arg is pdu (freed).
2255121326Sharti */
2256121326Shartistatic void
2257121326Shartisscop_inpend_rs(struct sscop *sscop, struct sscop_msg *msg)
2258121326Sharti{
2259121326Sharti	SSCOP_MSG_FREE(msg);
2260121326Sharti	MAAL_ERROR(sscop, 'J', 0);
2261121326Sharti}
2262121326Sharti
2263121326Sharti/*
2264121326Sharti * p 39: IN_PEND & RSAK PDU
2265121326Sharti *	arg is pdu (freed).
2266121326Sharti */
2267121326Shartistatic void
2268121326Shartisscop_inpend_rsak(struct sscop *sscop, struct sscop_msg *msg)
2269121326Sharti{
2270121326Sharti	SSCOP_MSG_FREE(msg);
2271121326Sharti	MAAL_ERROR(sscop, 'K', 0);
2272121326Sharti}
2273121326Sharti
2274121326Sharti/*
2275121326Sharti * p 39: IN_PEND && END PDU
2276121326Sharti *	arg is pdu (freed).
2277121326Sharti *	no uui
2278121326Sharti */
2279121326Shartistatic void
2280121326Shartisscop_inpend_end(struct sscop *sscop, struct sscop_msg *msg)
2281121326Sharti{
2282121326Sharti	union pdu pdu;
2283121326Sharti
2284121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
2285121326Sharti	(void)MBUF_STRIP32(msg->m);
2286121326Sharti
2287121326Sharti	send_endak(sscop);
2288121326Sharti
2289121326Sharti	AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication,
2290121326Sharti		msg, pdu.sscop_pl, (u_int)pdu.sscop_s);
2291121326Sharti
2292121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
2293121326Sharti}
2294121326Sharti
2295121326Sharti/*
2296121326Sharti * p 40: OUT_DIS_PEND && SSCOP_ESTABLISH_request
2297121326Sharti *	no arg.
2298121326Sharti *	no uui.
2299121326Sharti */
2300121326Shartistatic void
2301121326Shartisscop_outdis_establish_req(struct sscop *sscop, struct sscop_msg *uu)
2302121326Sharti{
2303121326Sharti	SET_UU(uu_bgn, uu);
2304121326Sharti
2305121326Sharti	TIMER_STOP(sscop, cc);
2306121326Sharti	m_clear_transmitter(sscop);
2307121326Sharti	sscop->clear_buffers = 1;
2308121326Sharti	sscop->vt_cc = 1;
2309121326Sharti	sscop->vt_sq++;
2310121326Sharti	m_initialize_mr(sscop);
2311121326Sharti	send_bgn(sscop, sscop->uu_bgn);
2312121326Sharti	TIMER_RESTART(sscop, cc);
2313121326Sharti
2314121326Sharti	sscop_set_state(sscop, SSCOP_OUT_PEND);
2315121326Sharti}
2316121326Sharti
2317121326Sharti/*
2318121326Sharti * p 41: OUT_DIS_PEND && END PDU
2319121326Sharti *	arg is pdu (freed).
2320121326Sharti */
2321121326Shartistatic void
2322121326Shartisscop_outdis_end(struct sscop *sscop, struct sscop_msg *msg)
2323121326Sharti{
2324121326Sharti	union pdu pdu;
2325121326Sharti
2326121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
2327121326Sharti	(void)MBUF_STRIP32(msg->m);
2328121326Sharti
2329121326Sharti	TIMER_STOP(sscop, cc);
2330121326Sharti	send_endak(sscop);
2331121326Sharti
2332121326Sharti	AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_confirm, msg, pdu.sscop_pl, 0);
2333121326Sharti
2334121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
2335121326Sharti}
2336121326Sharti
2337121326Sharti/*
2338121326Sharti * p 41: OUT_DIS_PEND && ENDAK PDU
2339121326Sharti * p 41: OUT_DIS_PEND && BGREJ PDU
2340121326Sharti *	arg is pdu (freed)
2341121326Sharti */
2342121326Shartistatic void
2343121326Shartisscop_outdis_endak(struct sscop *sscop, struct sscop_msg *msg)
2344121326Sharti{
2345121326Sharti	union pdu pdu;
2346121326Sharti
2347121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
2348121326Sharti	(void)MBUF_STRIP32(msg->m);
2349121326Sharti
2350121326Sharti	TIMER_STOP(sscop, cc);
2351121326Sharti
2352121326Sharti	AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_confirm, msg, pdu.sscop_pl, 0);
2353121326Sharti
2354121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
2355121326Sharti}
2356121326Sharti
2357121326Sharti/*
2358121326Sharti * p 41: OUT_DIS_PEND && TIMER CC expiry
2359121326Sharti *	no arg
2360121326Sharti */
2361121326Shartistatic void
2362121326Shartisscop_outdis_cc(struct sscop *sscop, struct sscop_msg *unused __unused)
2363121326Sharti{
2364121326Sharti	if(sscop->vt_cc >= sscop->maxcc) {
2365121326Sharti		MAAL_ERROR(sscop, 'O', 0);
2366121326Sharti		AAL_SIG(sscop, SSCOP_RELEASE_confirm);
2367121326Sharti		sscop_set_state(sscop, SSCOP_IDLE);
2368121326Sharti	} else {
2369121326Sharti		sscop->vt_cc++;
2370121326Sharti		send_end(sscop, sscop->last_end_src, sscop->uu_end);
2371121326Sharti		TIMER_RESTART(sscop, cc);
2372121326Sharti	}
2373121326Sharti}
2374121326Sharti
2375121326Sharti/*
2376121326Sharti * p 42: OUT_DIS_PEND && BGN PDU
2377121326Sharti *	arg is pdu (freed).
2378121326Sharti */
2379121326Shartistatic void
2380121326Shartisscop_outdis_bgn(struct sscop *sscop, struct sscop_msg *msg)
2381121326Sharti{
2382121326Sharti	union pdu pdu;
2383121326Sharti
2384121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
2385121326Sharti
2386121326Sharti	if(m_detect_retransmission(sscop, msg)) {
2387121326Sharti		FREE_UU(uu_bgak);
2388121326Sharti		send_bgak(sscop, NULL);
2389121326Sharti		send_end(sscop, sscop->last_end_src, sscop->uu_end);
2390121326Sharti		SSCOP_MSG_FREE(msg);
2391121326Sharti
2392121326Sharti	} else {
2393121326Sharti		(void)MBUF_STRIP32(msg->m);
2394121326Sharti
2395121326Sharti		TIMER_STOP(sscop, cc);
2396121326Sharti		sscop->vt_ms = pdu.sscop_ns;
2397121326Sharti		AAL_SIG(sscop, SSCOP_RELEASE_confirm);
2398121326Sharti		AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication,
2399121326Sharti			msg, pdu.sscop_pl, 0);
2400121326Sharti		sscop_set_state(sscop, SSCOP_IN_PEND);
2401121326Sharti	}
2402121326Sharti}
2403121326Sharti
2404121326Sharti/*
2405121326Sharti * p 43: OUT_RESYNC_PEND && BGN PDU
2406121326Sharti *	arg is pdu (freed).
2407121326Sharti */
2408121326Shartistatic void
2409121326Shartisscop_outsync_bgn(struct sscop *sscop, struct sscop_msg *msg)
2410121326Sharti{
2411121326Sharti	union pdu pdu;
2412121326Sharti
2413121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
2414121326Sharti
2415121326Sharti	if(m_detect_retransmission(sscop, msg)) {
2416121326Sharti		send_bgak(sscop, sscop->uu_bgak);
2417121326Sharti		send_rs(sscop, 1, sscop->uu_rs);
2418121326Sharti		SSCOP_MSG_FREE(msg);
2419121326Sharti	} else {
2420121326Sharti		(void)MBUF_STRIP32(msg->m);
2421121326Sharti
2422121326Sharti		TIMER_STOP(sscop, cc);
2423121326Sharti		sscop->vt_ms = pdu.sscop_ns;
2424121326Sharti		AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
2425121326Sharti		AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication,
2426121326Sharti			msg, pdu.sscop_pl, 0);
2427121326Sharti		sscop_set_state(sscop, SSCOP_IN_PEND);
2428121326Sharti	}
2429121326Sharti}
2430121326Sharti
2431121326Sharti/*
2432121326Sharti * p 43: OUT_RESYNC_PEND && ENDAK PDU
2433121326Sharti *	arg is pdu (freed).
2434121326Sharti */
2435121326Shartistatic void
2436121326Shartisscop_outsync_endak(struct sscop *sscop, struct sscop_msg *msg)
2437121326Sharti{
2438121326Sharti	SSCOP_MSG_FREE(msg);
2439121326Sharti	TIMER_STOP(sscop, cc);
2440121326Sharti	MAAL_ERROR(sscop, 'F', 0);
2441121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2442121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
2443121326Sharti}
2444121326Sharti
2445121326Sharti/*
2446121326Sharti * p 43: OUT_RESYNC_PEND && BGREJ PDU
2447121326Sharti *	arg is pdu (freed).
2448121326Sharti */
2449121326Shartistatic void
2450121326Shartisscop_outsync_bgrej(struct sscop *sscop, struct sscop_msg *msg)
2451121326Sharti{
2452121326Sharti	SSCOP_MSG_FREE(msg);
2453121326Sharti	TIMER_STOP(sscop, cc);
2454121326Sharti	MAAL_ERROR(sscop, 'D', 0);
2455121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2456121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
2457121326Sharti}
2458121326Sharti
2459121326Sharti/*
2460121326Sharti * p 43: OUT_RESYNC_PEND && END PDU
2461121326Sharti *	arg is pdu (freed).
2462121326Sharti *	no UU-data
2463121326Sharti */
2464121326Shartistatic void
2465121326Shartisscop_outsync_end(struct sscop *sscop, struct sscop_msg *msg)
2466121326Sharti{
2467121326Sharti	union pdu pdu;
2468121326Sharti
2469121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
2470121326Sharti	(void)MBUF_STRIP32(msg->m);
2471121326Sharti
2472121326Sharti	TIMER_STOP(sscop, cc);
2473121326Sharti	send_endak(sscop);
2474121326Sharti	AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication, msg, pdu.sscop_pl,
2475121326Sharti		(u_int)pdu.sscop_s);
2476121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
2477121326Sharti}
2478121326Sharti
2479121326Sharti/*
2480121326Sharti * p 44: OUT_RESYNC && TIMER CC expiry
2481121326Sharti */
2482121326Shartistatic void
2483121326Shartisscop_outsync_cc(struct sscop *sscop, struct sscop_msg *msg __unused)
2484121326Sharti{
2485121326Sharti	if(sscop->vt_cc == sscop->maxcc) {
2486121326Sharti		MAAL_ERROR(sscop, 'O', 0);
2487121326Sharti		FREE_UU(uu_end);
2488121326Sharti		send_end(sscop, 1, NULL);
2489121326Sharti		AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2490121326Sharti		sscop_set_state(sscop, SSCOP_IDLE);
2491121326Sharti	} else {
2492121326Sharti		sscop->vt_cc++;
2493121326Sharti		send_rs(sscop, 1, sscop->uu_rs);
2494121326Sharti		TIMER_RESTART(sscop, cc);
2495121326Sharti	}
2496121326Sharti}
2497121326Sharti
2498121326Sharti/*
2499121326Sharti * p 44: OUT_RESYNC && AA-RELEASE.request
2500121326Sharti *	arg is UU
2501121326Sharti */
2502121326Shartistatic void
2503121326Shartisscop_outsync_release_req(struct sscop *sscop, struct sscop_msg *uu)
2504121326Sharti{
2505121326Sharti	SET_UU(uu_end, uu);
2506121326Sharti
2507121326Sharti	TIMER_STOP(sscop, cc);
2508121326Sharti	sscop->vt_cc = 1;
2509121326Sharti	send_end(sscop, 0, sscop->uu_end);
2510121326Sharti	TIMER_RESTART(sscop, cc);
2511121326Sharti	sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
2512121326Sharti}
2513121326Sharti
2514121326Sharti/*
2515121326Sharti * p 45: OUT_RESYNC && RS PDU
2516121326Sharti *	arg is pdu (freed).
2517121326Sharti */
2518121326Shartistatic void
2519121326Shartisscop_outsync_rs(struct sscop *sscop, struct sscop_msg *msg)
2520121326Sharti{
2521121326Sharti	union pdu pdu;
2522121326Sharti
2523121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
2524121326Sharti
2525121326Sharti	if(m_detect_retransmission(sscop, msg)) {
2526121326Sharti		SSCOP_MSG_FREE(msg);
2527121326Sharti		return;
2528121326Sharti	}
2529121326Sharti	(void)MBUF_STRIP32(msg->m);
2530121326Sharti
2531121326Sharti	TIMER_STOP(sscop, cc);
2532121326Sharti	sscop->vt_ms = pdu.sscop_ns;
2533121326Sharti	m_initialize_mr(sscop);
2534121326Sharti	send_rsak(sscop);
2535121326Sharti	AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_confirm, msg, pdu.sscop_pl, 0);
2536121326Sharti	m_initialize_state(sscop);
2537121326Sharti	m_set_data_xfer_timers(sscop);
2538121326Sharti	sscop_set_state(sscop, SSCOP_READY);
2539121326Sharti}
2540121326Sharti
2541121326Sharti/*
2542121326Sharti * p 45: OUT_RESYNC && RSAK PDU
2543121326Sharti *	arg is pdu (freed).
2544121326Sharti */
2545121326Shartistatic void
2546121326Shartisscop_outsync_rsak(struct sscop *sscop, struct sscop_msg *msg)
2547121326Sharti{
2548121326Sharti	union pdu pdu;
2549121326Sharti
2550121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
2551121326Sharti
2552121326Sharti	SSCOP_MSG_FREE(msg);
2553121326Sharti
2554121326Sharti	TIMER_STOP(sscop, cc);
2555121326Sharti	sscop->vt_ms = pdu.sscop_ns;
2556121326Sharti	AAL_SIG(sscop, SSCOP_RESYNC_confirm);
2557121326Sharti	m_initialize_state(sscop);
2558121326Sharti	m_set_data_xfer_timers(sscop);
2559121326Sharti	sscop_set_state(sscop, SSCOP_READY);
2560121326Sharti}
2561121326Sharti
2562121326Sharti/*
2563121326Sharti * p 46: IN_RESYNC_PEND && AA-RESYNC.response
2564121326Sharti */
2565121326Shartistatic void
2566121326Shartisscop_insync_sync_resp(struct sscop *sscop, struct sscop_msg *noarg __unused)
2567121326Sharti{
2568121326Sharti	m_initialize_mr(sscop);
2569121326Sharti	send_rsak(sscop);
2570121326Sharti	m_clear_transmitter(sscop);
2571121326Sharti	m_initialize_state(sscop);
2572121326Sharti	m_set_data_xfer_timers(sscop);
2573121326Sharti	sscop_set_state(sscop, SSCOP_READY);
2574121326Sharti}
2575121326Sharti
2576121326Sharti/*
2577121326Sharti * p 46: IN_RESYNC_PEND && AA-RELEASE.request
2578121326Sharti *	arg is uu
2579121326Sharti */
2580121326Shartistatic void
2581121326Shartisscop_insync_release_req(struct sscop *sscop, struct sscop_msg *uu)
2582121326Sharti{
2583121326Sharti	SET_UU(uu_end, uu);
2584121326Sharti
2585121326Sharti	sscop->vt_cc = 1;
2586121326Sharti	send_end(sscop, 0, sscop->uu_end);
2587121326Sharti	TIMER_RESTART(sscop, cc);
2588121326Sharti	sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
2589121326Sharti}
2590121326Sharti
2591121326Sharti/*
2592121326Sharti * p 46: IN_RESYNC_PEND && ENDAK PDU
2593121326Sharti *	arg is pdu (freed).
2594121326Sharti */
2595121326Shartistatic void
2596121326Shartisscop_insync_endak(struct sscop *sscop, struct sscop_msg *msg)
2597121326Sharti{
2598121326Sharti	SSCOP_MSG_FREE(msg);
2599121326Sharti	MAAL_ERROR(sscop, 'F', 0);
2600121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2601121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
2602121326Sharti}
2603121326Sharti
2604121326Sharti/*
2605121326Sharti * p 46: IN_RESYNC_PEND && BGREJ PDU
2606121326Sharti *	arg is pdu (freed).
2607121326Sharti */
2608121326Shartistatic void
2609121326Shartisscop_insync_bgrej(struct sscop *sscop, struct sscop_msg *msg)
2610121326Sharti{
2611121326Sharti	SSCOP_MSG_FREE(msg);
2612121326Sharti	MAAL_ERROR(sscop, 'D', 0);
2613121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2614121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
2615121326Sharti}
2616121326Sharti
2617121326Sharti/*
2618121326Sharti * p 46: IN_RESYNC_PEND && END PDU
2619121326Sharti *	arg is pdu (freed).
2620121326Sharti */
2621121326Shartistatic void
2622121326Shartisscop_insync_end(struct sscop *sscop, struct sscop_msg *msg)
2623121326Sharti{
2624121326Sharti	union pdu pdu;
2625121326Sharti
2626121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
2627121326Sharti	(void)MBUF_STRIP32(msg->m);
2628121326Sharti
2629121326Sharti	send_endak(sscop);
2630121326Sharti	AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication,
2631121326Sharti		msg, pdu.sscop_pl, (u_int)pdu.sscop_s);
2632121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
2633121326Sharti}
2634121326Sharti
2635121326Sharti/*
2636121326Sharti * p 47: IN_RESYNC_PEND && ER PDU
2637121326Sharti *	arg is pdu (freed).
2638121326Sharti */
2639121326Shartistatic void
2640121326Shartisscop_insync_er(struct sscop *sscop, struct sscop_msg *msg)
2641121326Sharti{
2642121326Sharti	SSCOP_MSG_FREE(msg);
2643121326Sharti	MAAL_ERROR(sscop, 'L', 0);
2644121326Sharti}
2645121326Sharti
2646121326Sharti/*
2647121326Sharti * p 47: IN_RESYNC_PEND && BGN PDU
2648121326Sharti *	arg is pdu (freed).
2649121326Sharti */
2650121326Shartistatic void
2651121326Shartisscop_insync_bgn(struct sscop *sscop, struct sscop_msg *msg)
2652121326Sharti{
2653121326Sharti	union pdu pdu;
2654121326Sharti
2655121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
2656121326Sharti
2657121326Sharti	if(m_detect_retransmission(sscop, msg)) {
2658121326Sharti		MAAL_ERROR(sscop, 'B', 0);
2659121326Sharti		SSCOP_MSG_FREE(msg);
2660121326Sharti		return;
2661121326Sharti	}
2662121326Sharti	(void)MBUF_STRIP32(msg->m);
2663121326Sharti
2664121326Sharti	sscop->vt_ms = pdu.sscop_ns;
2665121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
2666121326Sharti	AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0);
2667121326Sharti
2668121326Sharti	sscop_set_state(sscop, SSCOP_IN_PEND);
2669121326Sharti}
2670121326Sharti
2671121326Sharti/*
2672121326Sharti * p 47: IN_RESYNC_PEND && SD PDU
2673121326Sharti *	arg is pdu (freed).
2674121326Sharti */
2675121326Shartistatic void
2676121326Shartisscop_insync_sd(struct sscop *sscop, struct sscop_msg *msg)
2677121326Sharti{
2678121326Sharti	SSCOP_MSG_FREE(msg);
2679121326Sharti	MAAL_ERROR(sscop, 'A', 0);
2680121326Sharti	FREE_UU(uu_end);
2681121326Sharti	send_end(sscop, 1, NULL);
2682121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2683121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
2684121326Sharti}
2685121326Sharti
2686121326Sharti/*
2687121326Sharti * p 47: IN_RESYNC_PEND && POLL PDU
2688121326Sharti *	arg is pdu (freed).
2689121326Sharti */
2690121326Shartistatic void
2691121326Shartisscop_insync_poll(struct sscop *sscop, struct sscop_msg *msg)
2692121326Sharti{
2693121326Sharti	SSCOP_MSG_FREE(msg);
2694121326Sharti	MAAL_ERROR(sscop, 'G', 0);
2695121326Sharti	FREE_UU(uu_end);
2696121326Sharti	send_end(sscop, 1, NULL);
2697121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2698121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
2699121326Sharti}
2700121326Sharti
2701121326Sharti/*
2702121326Sharti * p 47: IN_RESYNC_PEND && STAT PDU
2703121326Sharti *	arg is pdu (freed).
2704121326Sharti */
2705121326Shartistatic void
2706121326Shartisscop_insync_stat(struct sscop *sscop, struct sscop_msg *msg)
2707121326Sharti{
2708121326Sharti	SSCOP_MSG_FREE(msg);
2709121326Sharti	MAAL_ERROR(sscop, 'H', 0);
2710121326Sharti	FREE_UU(uu_end);
2711121326Sharti	send_end(sscop, 1, NULL);
2712121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2713121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
2714121326Sharti}
2715121326Sharti
2716121326Sharti/*
2717121326Sharti * p 47: IN_RESYNC_PEND && USTAT PDU
2718121326Sharti *	arg is pdu (freed).
2719121326Sharti */
2720121326Shartistatic void
2721121326Shartisscop_insync_ustat(struct sscop *sscop, struct sscop_msg *msg)
2722121326Sharti{
2723121326Sharti	SSCOP_MSG_FREE(msg);
2724121326Sharti	MAAL_ERROR(sscop, 'I', 0);
2725121326Sharti	FREE_UU(uu_end);
2726121326Sharti	send_end(sscop, 1, NULL);
2727121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2728121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
2729121326Sharti}
2730121326Sharti
2731121326Sharti/*
2732121326Sharti * p 48: IN_RESYNC_PEND && BGAK PDU
2733121326Sharti *	arg is pdu (freed).
2734121326Sharti */
2735121326Shartistatic void
2736121326Shartisscop_insync_bgak(struct sscop *sscop, struct sscop_msg *msg)
2737121326Sharti{
2738121326Sharti	MAAL_ERROR(sscop, 'C', 0);
2739121326Sharti	SSCOP_MSG_FREE(msg);
2740121326Sharti}
2741121326Sharti
2742121326Sharti/*
2743121326Sharti * p 48: IN_RESYNC_PEND && ERAK PDU
2744121326Sharti *	arg is pdu (freed).
2745121326Sharti */
2746121326Shartistatic void
2747121326Shartisscop_insync_erak(struct sscop *sscop, struct sscop_msg *msg)
2748121326Sharti{
2749121326Sharti	MAAL_ERROR(sscop, 'M', 0);
2750121326Sharti	SSCOP_MSG_FREE(msg);
2751121326Sharti}
2752121326Sharti
2753121326Sharti/*
2754121326Sharti * p 48: IN_RESYNC_PEND && RS PDU
2755121326Sharti *	arg is pdu (freed).
2756121326Sharti */
2757121326Shartistatic void
2758121326Shartisscop_insync_rs(struct sscop *sscop, struct sscop_msg *msg)
2759121326Sharti{
2760121326Sharti	union pdu pdu;
2761121326Sharti
2762121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
2763121326Sharti
2764121326Sharti	if(m_detect_retransmission(sscop, msg)) {
2765121326Sharti		SSCOP_MSG_FREE(msg);
2766121326Sharti		return;
2767121326Sharti	}
2768121326Sharti	SSCOP_MSG_FREE(msg);
2769121326Sharti	MAAL_ERROR(sscop, 'J', 0);
2770121326Sharti}
2771121326Sharti
2772121326Sharti/*
2773121326Sharti * p 48: IN_RESYNC_PEND && RSAK PDU
2774121326Sharti *	arg is pdu (freed).
2775121326Sharti */
2776121326Shartistatic void
2777121326Shartisscop_insync_rsak(struct sscop *sscop, struct sscop_msg *msg)
2778121326Sharti{
2779121326Sharti	MAAL_ERROR(sscop, 'K', 0);
2780121326Sharti	SSCOP_MSG_FREE(msg);
2781121326Sharti}
2782121326Sharti
2783121326Sharti
2784121326Sharti/*
2785121326Sharti * p 49: OUT_REC_PEND && AA-DATA.request
2786121326Sharti *	arg is message (queued).
2787121326Sharti */
2788121326Shartistatic void
2789121326Shartisscop_outrec_userdata(struct sscop *sscop, struct sscop_msg *msg)
2790121326Sharti{
2791121326Sharti	if(!sscop->clear_buffers) {
2792121326Sharti		MSGQ_APPEND(&sscop->xq, msg);
2793121326Sharti		sscop_signal(sscop, SIG_PDU_Q, msg);
2794121326Sharti	} else {
2795121326Sharti		SSCOP_MSG_FREE(msg);
2796121326Sharti	}
2797121326Sharti}
2798121326Sharti
2799121326Sharti/*
2800121326Sharti * p 49: OUT_REC_PEND && BGAK PDU
2801121326Sharti *	arg is pdu (freed)
2802121326Sharti */
2803121326Shartistatic void
2804121326Shartisscop_outrec_bgak(struct sscop *sscop, struct sscop_msg *msg)
2805121326Sharti{
2806121326Sharti	MAAL_ERROR(sscop, 'C', 0);
2807121326Sharti
2808121326Sharti	SSCOP_MSG_FREE(msg);
2809121326Sharti}
2810121326Sharti
2811121326Sharti/*
2812121326Sharti * p 49: OUT_REC_PEND && ERAK PDU
2813121326Sharti *	arg is pdu (freed)
2814121326Sharti */
2815121326Shartistatic void
2816121326Shartisscop_outrec_erak(struct sscop *sscop, struct sscop_msg *msg)
2817121326Sharti{
2818121326Sharti	union pdu pdu;
2819121326Sharti
2820121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
2821121326Sharti
2822121326Sharti	TIMER_STOP(sscop, cc);
2823121326Sharti	sscop->vt_ms = pdu.sscop_ns;
2824121326Sharti	m_deliver_data(sscop);
2825121326Sharti
2826121326Sharti	AAL_SIG(sscop, SSCOP_RECOVER_indication);
2827121326Sharti
2828121326Sharti	sscop_set_state(sscop, SSCOP_REC_PEND);
2829121326Sharti
2830121326Sharti	SSCOP_MSG_FREE(msg);
2831121326Sharti}
2832121326Sharti
2833121326Sharti/*
2834121326Sharti * p 49: OUT_REC_PEND && END PDU
2835121326Sharti *	arg is pdu (freed)
2836121326Sharti */
2837121326Shartistatic void
2838121326Shartisscop_outrec_end(struct sscop *sscop, struct sscop_msg *msg)
2839121326Sharti{
2840121326Sharti	union pdu pdu;
2841121326Sharti
2842121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
2843121326Sharti	(void)MBUF_STRIP32(msg->m);
2844121326Sharti
2845121326Sharti	TIMER_STOP(sscop, cc);
2846121326Sharti	send_endak(sscop);
2847121326Sharti	AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication,
2848121326Sharti		msg, pdu.sscop_pl, (u_int)pdu.sscop_s);
2849121326Sharti
2850121326Sharti	MSGQ_CLEAR(&sscop->rbuf);
2851121326Sharti
2852121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
2853121326Sharti}
2854121326Sharti
2855121326Sharti/*
2856121326Sharti * p 49: OUT_REC_PEND && ENDAK PDU
2857121326Sharti *	arg is pdu (freed)
2858121326Sharti */
2859121326Shartistatic void
2860121326Shartisscop_outrec_endak(struct sscop *sscop, struct sscop_msg *msg)
2861121326Sharti{
2862121326Sharti	MAAL_ERROR(sscop, 'F', 0);
2863121326Sharti	TIMER_STOP(sscop, cc);
2864121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2865121326Sharti	MSGQ_CLEAR(&sscop->rbuf);
2866121326Sharti
2867121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
2868121326Sharti
2869121326Sharti	SSCOP_MSG_FREE(msg);
2870121326Sharti}
2871121326Sharti
2872121326Sharti/*
2873121326Sharti * p 49: OUT_REC_PEND && BGREJ PDU
2874121326Sharti *	arg is pdu (freed)
2875121326Sharti */
2876121326Shartistatic void
2877121326Shartisscop_outrec_bgrej(struct sscop *sscop, struct sscop_msg *msg)
2878121326Sharti{
2879121326Sharti	MAAL_ERROR(sscop, 'D', 0);
2880121326Sharti	TIMER_STOP(sscop, cc);
2881121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2882121326Sharti	MSGQ_CLEAR(&sscop->rbuf);
2883121326Sharti
2884121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
2885121326Sharti
2886121326Sharti	SSCOP_MSG_FREE(msg);
2887121326Sharti}
2888121326Sharti
2889121326Sharti/*
2890121326Sharti * p 50: OUT_REC_PEND && TIMER CC expiry
2891121326Sharti *	no arg.
2892121326Sharti */
2893121326Shartistatic void
2894121326Shartisscop_outrec_cc(struct sscop *sscop, struct sscop_msg *unused __unused)
2895121326Sharti{
2896121326Sharti	if(sscop->vt_cc >= sscop->maxcc) {
2897121326Sharti		MAAL_ERROR(sscop, 'O', 0);
2898121326Sharti		FREE_UU(uu_end);
2899121326Sharti		send_end(sscop, 1, NULL);
2900121326Sharti		AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2901121326Sharti		MSGQ_CLEAR(&sscop->rbuf);
2902121326Sharti		sscop_set_state(sscop, SSCOP_IDLE);
2903121326Sharti	} else {
2904121326Sharti		sscop->vt_cc++;
2905121326Sharti		send_er(sscop);
2906121326Sharti		TIMER_RESTART(sscop, cc);
2907121326Sharti	}
2908121326Sharti}
2909121326Sharti
2910121326Sharti/*
2911121326Sharti * p 50: OUT_REC_PEND && SSCOP_RELEASE_request
2912121326Sharti *	arg is UU
2913121326Sharti */
2914121326Shartistatic void
2915121326Shartisscop_outrec_release_req(struct sscop *sscop, struct sscop_msg *uu)
2916121326Sharti{
2917121326Sharti	SET_UU(uu_end, uu);
2918121326Sharti
2919121326Sharti	TIMER_STOP(sscop, cc);
2920121326Sharti	sscop->vt_cc = 1;
2921121326Sharti	send_end(sscop, 0, sscop->uu_end);
2922121326Sharti	MSGQ_CLEAR(&sscop->rbuf);
2923121326Sharti	TIMER_RESTART(sscop, cc);
2924121326Sharti
2925121326Sharti	sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
2926121326Sharti}
2927121326Sharti
2928121326Sharti/*
2929121326Sharti * p 51: OUT_REC_PEND && AA-RESYNC.request
2930121326Sharti *	arg is uu
2931121326Sharti */
2932121326Shartistatic void
2933121326Shartisscop_outrec_sync_req(struct sscop *sscop, struct sscop_msg *uu)
2934121326Sharti{
2935121326Sharti	SET_UU(uu_rs, uu);
2936121326Sharti
2937121326Sharti	TIMER_STOP(sscop, cc);
2938121326Sharti	sscop->vt_cc = 1;
2939121326Sharti	sscop->vt_sq++;
2940121326Sharti	m_initialize_mr(sscop);
2941121326Sharti	send_rs(sscop, 0, sscop->uu_rs);
2942121326Sharti	m_clear_transmitter(sscop);
2943121326Sharti	MSGQ_CLEAR(&sscop->rbuf);
2944121326Sharti	TIMER_RESTART(sscop, cc);
2945121326Sharti}
2946121326Sharti
2947121326Sharti/*
2948121326Sharti * p 51: OUT_REC_PEND && BGN PDU
2949121326Sharti *	arg is pdu (freed).
2950121326Sharti *	no uui
2951121326Sharti */
2952121326Shartistatic void
2953121326Shartisscop_outrec_bgn(struct sscop *sscop, struct sscop_msg *msg)
2954121326Sharti{
2955121326Sharti	union pdu pdu;
2956121326Sharti
2957121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
2958121326Sharti
2959121326Sharti	if(m_detect_retransmission(sscop, msg)) {
2960121326Sharti		MAAL_ERROR(sscop, 'B', 0);
2961121326Sharti		SSCOP_MSG_FREE(msg);
2962121326Sharti	} else {
2963121326Sharti		(void)MBUF_STRIP32(msg->m);
2964121326Sharti
2965121326Sharti		TIMER_STOP(sscop, cc);
2966121326Sharti		sscop->vt_ms = pdu.sscop_ns;
2967121326Sharti		AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
2968121326Sharti		AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication,
2969121326Sharti			msg, pdu.sscop_pl, 0);
2970121326Sharti		MSGQ_CLEAR(&sscop->rbuf);
2971121326Sharti
2972121326Sharti		sscop_set_state(sscop, SSCOP_IN_PEND);
2973121326Sharti	}
2974121326Sharti}
2975121326Sharti
2976121326Sharti/*
2977121326Sharti * p 51: OUT_REC_PEND && ER PDU
2978121326Sharti *	arg is pdu (freed).
2979121326Sharti */
2980121326Shartistatic void
2981121326Shartisscop_outrec_er(struct sscop *sscop, struct sscop_msg *msg)
2982121326Sharti{
2983121326Sharti	union pdu pdu;
2984121326Sharti
2985121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
2986121326Sharti
2987121326Sharti	if(m_detect_retransmission(sscop, msg)) {
2988121326Sharti		MAAL_ERROR(sscop, 'L', 0);
2989121326Sharti	} else {
2990121326Sharti		TIMER_STOP(sscop, cc);
2991121326Sharti		sscop->vt_ms = pdu.sscop_ns;
2992121326Sharti		m_initialize_mr(sscop);
2993121326Sharti		send_erak(sscop);
2994121326Sharti		m_deliver_data(sscop);
2995121326Sharti
2996121326Sharti		AAL_SIG(sscop, SSCOP_RECOVER_indication);
2997121326Sharti
2998121326Sharti		sscop_set_state(sscop, SSCOP_REC_PEND);
2999121326Sharti	}
3000121326Sharti
3001121326Sharti	SSCOP_MSG_FREE(msg);
3002121326Sharti}
3003121326Sharti
3004121326Sharti/*
3005121326Sharti * p 52: OUT_REC_PEND && SD PDU queued
3006121326Sharti *	no arg.
3007121326Sharti */
3008121326Shartistatic void
3009121326Shartisscop_outrec_pduq(struct sscop *sscop, struct sscop_msg *msg)
3010121326Sharti{
3011121326Sharti	sscop_save_signal(sscop, SIG_PDU_Q, msg);
3012121326Sharti}
3013121326Sharti
3014121326Sharti/*
3015121326Sharti * p 52: OUT_REC_PEND && RSAK PDU
3016121326Sharti *	arg is pdu (freed).
3017121326Sharti */
3018121326Shartistatic void
3019121326Shartisscop_outrec_rsak(struct sscop *sscop, struct sscop_msg *msg)
3020121326Sharti{
3021121326Sharti	SSCOP_MSG_FREE(msg);
3022121326Sharti	MAAL_ERROR(sscop, 'K', 0);
3023121326Sharti}
3024121326Sharti
3025121326Sharti/*
3026121326Sharti * p 52: OUT_REC_PEND && RS PDU
3027121326Sharti *	arg is pdu (freed).
3028121326Sharti */
3029121326Shartistatic void
3030121326Shartisscop_outrec_rs(struct sscop *sscop, struct sscop_msg *msg)
3031121326Sharti{
3032121326Sharti	union pdu pdu;
3033121326Sharti
3034121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
3035121326Sharti
3036121326Sharti	if(m_detect_retransmission(sscop, msg)) {
3037121326Sharti		SSCOP_MSG_FREE(msg);
3038121326Sharti		MAAL_ERROR(sscop, 'J', 0);
3039121326Sharti		return;
3040121326Sharti	}
3041121326Sharti	(void)MBUF_STRIP32(msg->m);
3042121326Sharti
3043121326Sharti	TIMER_STOP(sscop, cc);
3044121326Sharti	sscop->vt_ms = pdu.sscop_ns;
3045121326Sharti	AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_indication, msg, pdu.sscop_pl, 0);
3046121326Sharti	MSGQ_CLEAR(&sscop->rbuf);
3047121326Sharti	sscop_set_state(sscop, SSCOP_IN_RESYNC_PEND);
3048121326Sharti}
3049121326Sharti
3050121326Sharti/*
3051121326Sharti * p 53: REC_PEND && BGAK PDU
3052121326Sharti *	arg is pdu (freed)
3053121326Sharti */
3054121326Shartistatic void
3055121326Shartisscop_rec_bgak(struct sscop *sscop, struct sscop_msg *msg)
3056121326Sharti{
3057121326Sharti	MAAL_ERROR(sscop, 'C', 0);
3058121326Sharti
3059121326Sharti	SSCOP_MSG_FREE(msg);
3060121326Sharti}
3061121326Sharti
3062121326Sharti/*
3063121326Sharti * p 53: REC_PEND && END PDU
3064121326Sharti *	arg is pdu (freed)
3065121326Sharti *	no uui
3066121326Sharti */
3067121326Shartistatic void
3068121326Shartisscop_rec_end(struct sscop *sscop, struct sscop_msg *msg)
3069121326Sharti{
3070121326Sharti	union pdu pdu;
3071121326Sharti
3072121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
3073121326Sharti	(void)MBUF_STRIP32(msg->m);
3074121326Sharti
3075121326Sharti	send_endak(sscop);
3076121326Sharti	AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication,
3077121326Sharti		msg, pdu.sscop_pl, (u_int)pdu.sscop_s);
3078121326Sharti
3079121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
3080121326Sharti}
3081121326Sharti
3082121326Sharti/*
3083121326Sharti * p 53: REC_PEND && ENDAK PDU
3084121326Sharti *	arg is pdu (freed)
3085121326Sharti */
3086121326Shartistatic void
3087121326Shartisscop_rec_endak(struct sscop *sscop, struct sscop_msg *msg)
3088121326Sharti{
3089121326Sharti	MAAL_ERROR(sscop, 'F', 0);
3090121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
3091121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
3092121326Sharti	SSCOP_MSG_FREE(msg);
3093121326Sharti}
3094121326Sharti
3095121326Sharti/*
3096121326Sharti * p 53: REC_PEND && BGREJ PDU
3097121326Sharti *	arg is pdu (freed)
3098121326Sharti */
3099121326Shartistatic void
3100121326Shartisscop_rec_bgrej(struct sscop *sscop, struct sscop_msg *msg)
3101121326Sharti{
3102121326Sharti	MAAL_ERROR(sscop, 'D', 0);
3103121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
3104121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
3105121326Sharti	SSCOP_MSG_FREE(msg);
3106121326Sharti}
3107121326Sharti
3108121326Sharti/*
3109121326Sharti * p 54: REC_PEND && RELEASE
3110121326Sharti *	arg is UU
3111121326Sharti */
3112121326Shartistatic void
3113121326Shartisscop_rec_release_req(struct sscop *sscop, struct sscop_msg *uu)
3114121326Sharti{
3115121326Sharti	SET_UU(uu_end, uu);
3116121326Sharti
3117121326Sharti	sscop->vt_cc = 1;
3118121326Sharti	send_end(sscop, 0, sscop->uu_end);
3119121326Sharti	TIMER_RESTART(sscop, cc);
3120121326Sharti
3121121326Sharti	sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
3122121326Sharti}
3123121326Sharti
3124121326Sharti/*
3125121326Sharti * p 54: REC_PEND && RSAK PDU
3126121326Sharti *	arg is pdu (freed).
3127121326Sharti */
3128121326Shartistatic void
3129121326Shartisscop_rec_rsak(struct sscop *sscop, struct sscop_msg *msg)
3130121326Sharti{
3131121326Sharti	MAAL_ERROR(sscop, 'K', 0);
3132121326Sharti	SSCOP_MSG_FREE(msg);
3133121326Sharti}
3134121326Sharti
3135121326Sharti
3136121326Sharti/*
3137121326Sharti * p 54: REC_PEND && RS PDU
3138121326Sharti *	arg is pdu (freed).
3139121326Sharti */
3140121326Shartistatic void
3141121326Shartisscop_rec_rs(struct sscop *sscop, struct sscop_msg *msg)
3142121326Sharti{
3143121326Sharti	union pdu pdu;
3144121326Sharti
3145121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
3146121326Sharti
3147121326Sharti	if(m_detect_retransmission(sscop, msg)) {
3148121326Sharti		SSCOP_MSG_FREE(msg);
3149121326Sharti		MAAL_ERROR(sscop, 'J', 0);
3150121326Sharti		return;
3151121326Sharti	}
3152121326Sharti	(void)MBUF_STRIP32(msg->m);
3153121326Sharti
3154121326Sharti	sscop->vt_ms = pdu.sscop_ns;
3155121326Sharti	AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_indication, msg, pdu.sscop_pl, 0);
3156121326Sharti
3157121326Sharti	sscop_set_state(sscop, SSCOP_IN_RESYNC_PEND);
3158121326Sharti}
3159121326Sharti
3160121326Sharti/*
3161121326Sharti * p 54: REC_PEND && RECOVER response
3162121326Sharti *	no arg
3163121326Sharti */
3164121326Shartistatic void
3165121326Shartisscop_rec_recover(struct sscop *sscop, struct sscop_msg *unused __unused)
3166121326Sharti{
3167121326Sharti	if(!sscop->clear_buffers) {
3168121326Sharti		MSGQ_CLEAR(&sscop->xbuf);
3169121326Sharti	}
3170121326Sharti	m_initialize_state(sscop);
3171121326Sharti	m_set_data_xfer_timers(sscop);
3172121326Sharti
3173121326Sharti	sscop_set_state(sscop, SSCOP_READY);
3174121326Sharti}
3175121326Sharti
3176121326Sharti/*
3177121326Sharti * p 54: REC_PEND && RESYNC request
3178121326Sharti *	arg is uu
3179121326Sharti */
3180121326Shartistatic void
3181121326Shartisscop_rec_sync_req(struct sscop *sscop, struct sscop_msg *uu)
3182121326Sharti{
3183121326Sharti	SET_UU(uu_rs, uu);
3184121326Sharti
3185121326Sharti	m_clear_transmitter(sscop);
3186121326Sharti	sscop->vt_cc = 1;
3187121326Sharti	sscop->vt_sq++;
3188121326Sharti	m_initialize_mr(sscop);
3189121326Sharti	send_rs(sscop, 0, sscop->uu_rs);
3190121326Sharti	TIMER_RESTART(sscop, cc);
3191121326Sharti
3192121326Sharti	sscop_set_state(sscop, SSCOP_OUT_RESYNC_PEND);
3193121326Sharti}
3194121326Sharti
3195121326Sharti/*
3196121326Sharti * p 55: REC_PEND && SD PDU queued
3197121326Sharti *	no arg
3198121326Sharti */
3199121326Shartistatic void
3200121326Shartisscop_rec_pduq(struct sscop *sscop, struct sscop_msg *msg)
3201121326Sharti{
3202121326Sharti	sscop_save_signal(sscop, SIG_PDU_Q, msg);
3203121326Sharti}
3204121326Sharti
3205121326Sharti/*
3206121326Sharti * p 55: REC_PEND && ER PDU
3207121326Sharti *	arg is pdu (freed).
3208121326Sharti */
3209121326Shartistatic void
3210121326Shartisscop_rec_er(struct sscop *sscop, struct sscop_msg *msg)
3211121326Sharti{
3212121326Sharti	union pdu pdu;
3213121326Sharti
3214121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
3215121326Sharti
3216121326Sharti	if(m_detect_retransmission(sscop, msg)) {
3217121326Sharti		send_erak(sscop);
3218121326Sharti	} else {
3219121326Sharti		MAAL_ERROR(sscop, 'L', 0);
3220121326Sharti	}
3221121326Sharti	SSCOP_MSG_FREE(msg);
3222121326Sharti}
3223121326Sharti
3224121326Sharti/*
3225121326Sharti * p 55: REC_PEND && BGN PDU
3226121326Sharti *	arg is pdu (freed)
3227121326Sharti *	no uui
3228121326Sharti */
3229121326Shartistatic void
3230121326Shartisscop_rec_bgn(struct sscop *sscop, struct sscop_msg *msg)
3231121326Sharti{
3232121326Sharti	union pdu pdu;
3233121326Sharti
3234121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
3235121326Sharti
3236121326Sharti	if(m_detect_retransmission(sscop, msg)) {
3237121326Sharti		MAAL_ERROR(sscop, 'B', 0);
3238121326Sharti		SSCOP_MSG_FREE(msg);
3239121326Sharti		return;
3240121326Sharti	}
3241121326Sharti	(void)MBUF_STRIP32(msg->m);
3242121326Sharti
3243121326Sharti	sscop->vt_ms = pdu.sscop_ns;
3244121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
3245121326Sharti	AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0);
3246121326Sharti
3247121326Sharti	sscop_set_state(sscop, SSCOP_IN_PEND);
3248121326Sharti}
3249121326Sharti
3250121326Sharti/*
3251121326Sharti * p 55: REC_PEND && STAT PDU
3252121326Sharti *	arg is pdu (freed)
3253121326Sharti */
3254121326Shartistatic void
3255121326Shartisscop_rec_stat(struct sscop *sscop, struct sscop_msg *msg)
3256121326Sharti{
3257121326Sharti	MAAL_ERROR(sscop, 'H', 0);
3258121326Sharti	FREE_UU(uu_end);
3259121326Sharti	send_end(sscop, 1, NULL);
3260121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
3261121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
3262121326Sharti	SSCOP_MSG_FREE(msg);
3263121326Sharti}
3264121326Sharti
3265121326Sharti/*
3266121326Sharti * p 55: REC_PEND && USTAT PDU
3267121326Sharti *	arg is pdu (freed)
3268121326Sharti */
3269121326Shartistatic void
3270121326Shartisscop_rec_ustat(struct sscop *sscop, struct sscop_msg *msg)
3271121326Sharti{
3272121326Sharti	MAAL_ERROR(sscop, 'I', 0);
3273121326Sharti	FREE_UU(uu_end);
3274121326Sharti	send_end(sscop, 1, NULL);
3275121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
3276121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
3277121326Sharti	SSCOP_MSG_FREE(msg);
3278121326Sharti}
3279121326Sharti
3280121326Sharti/*
3281121326Sharti * p 56: IN_REC_PEND && AA-RECOVER.response
3282121326Sharti *	no arg
3283121326Sharti */
3284121326Shartistatic void
3285121326Shartisscop_inrec_recover(struct sscop *sscop, struct sscop_msg *unused __unused)
3286121326Sharti{
3287121326Sharti	if(!sscop->clear_buffers) {
3288121326Sharti		MSGQ_CLEAR(&sscop->xbuf);
3289121326Sharti	}
3290121326Sharti	m_initialize_mr(sscop);
3291121326Sharti	send_erak(sscop);
3292121326Sharti	m_initialize_state(sscop);
3293121326Sharti	m_set_data_xfer_timers(sscop);
3294121326Sharti
3295121326Sharti	sscop_set_state(sscop, SSCOP_READY);
3296121326Sharti}
3297121326Sharti
3298121326Sharti/*
3299121326Sharti * p 56: IN_REC_PEND && SD PDU queued
3300121326Sharti *	no arg
3301121326Sharti */
3302121326Shartistatic void
3303121326Shartisscop_inrec_pduq(struct sscop *sscop, struct sscop_msg *msg)
3304121326Sharti{
3305121326Sharti	sscop_save_signal(sscop, SIG_PDU_Q, msg);
3306121326Sharti}
3307121326Sharti
3308121326Sharti/*
3309121326Sharti * p 56: IN_REC_PEND && AA-RELEASE.request
3310121326Sharti *	arg is UU
3311121326Sharti */
3312121326Shartistatic void
3313121326Shartisscop_inrec_release_req(struct sscop *sscop, struct sscop_msg *uu)
3314121326Sharti{
3315121326Sharti	SET_UU(uu_end, uu);
3316121326Sharti
3317121326Sharti	sscop->vt_cc = 1;
3318121326Sharti	send_end(sscop, 0, sscop->uu_end);
3319121326Sharti	TIMER_RESTART(sscop, cc);
3320121326Sharti
3321121326Sharti	sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
3322121326Sharti}
3323121326Sharti
3324121326Sharti/*
3325121326Sharti * p 56: IN_REC_PEND && END PDU
3326121326Sharti *	arg is pdu (freed).
3327121326Sharti *	no uui
3328121326Sharti */
3329121326Shartistatic void
3330121326Shartisscop_inrec_end(struct sscop *sscop, struct sscop_msg *msg)
3331121326Sharti{
3332121326Sharti	union pdu pdu;
3333121326Sharti
3334121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
3335121326Sharti	(void)MBUF_STRIP32(msg->m);
3336121326Sharti
3337121326Sharti	send_endak(sscop);
3338121326Sharti	AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication,
3339121326Sharti		msg, pdu.sscop_pl, (u_int)pdu.sscop_s);
3340121326Sharti
3341121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
3342121326Sharti}
3343121326Sharti
3344121326Sharti/*
3345121326Sharti * p 56: IN_REC_PEND && RESYNC_REQ
3346121326Sharti */
3347121326Shartistatic void
3348121326Shartisscop_inrec_sync_req(struct sscop *sscop, struct sscop_msg *uu)
3349121326Sharti{
3350121326Sharti	SET_UU(uu_rs, uu);
3351121326Sharti
3352121326Sharti	m_clear_transmitter(sscop);
3353121326Sharti	sscop->vt_cc = 1;
3354121326Sharti	sscop->vt_sq++;
3355121326Sharti	m_initialize_mr(sscop);
3356121326Sharti	send_rs(sscop, 0, sscop->uu_rs);
3357121326Sharti	TIMER_RESTART(sscop, cc);
3358121326Sharti
3359121326Sharti	sscop_set_state(sscop, SSCOP_OUT_RESYNC_PEND);
3360121326Sharti}
3361121326Sharti
3362121326Sharti
3363121326Sharti/*
3364121326Sharti * p 57: IN_REC_PEND && ENDAK PDU
3365121326Sharti *	arg is pdu (freed)
3366121326Sharti */
3367121326Shartistatic void
3368121326Shartisscop_inrec_endak(struct sscop *sscop, struct sscop_msg *msg)
3369121326Sharti{
3370121326Sharti	MAAL_ERROR(sscop, 'F', 0);
3371121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
3372121326Sharti	SSCOP_MSG_FREE(msg);
3373121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
3374121326Sharti}
3375121326Sharti
3376121326Sharti/*
3377121326Sharti * p 57: IN_REC_PEND && BGREJ PDU
3378121326Sharti *	arg is pdu (freed)
3379121326Sharti */
3380121326Shartistatic void
3381121326Shartisscop_inrec_bgrej(struct sscop *sscop, struct sscop_msg *msg)
3382121326Sharti{
3383121326Sharti	MAAL_ERROR(sscop, 'D', 0);
3384121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
3385121326Sharti	SSCOP_MSG_FREE(msg);
3386121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
3387121326Sharti}
3388121326Sharti
3389121326Sharti/*
3390121326Sharti * p 57: IN_REC_PEND && USTAT PDU
3391121326Sharti *	arg is pdu (freed)
3392121326Sharti */
3393121326Shartistatic void
3394121326Shartisscop_inrec_ustat(struct sscop *sscop, struct sscop_msg *msg)
3395121326Sharti{
3396121326Sharti	MAAL_ERROR(sscop, 'I', 0);
3397121326Sharti	FREE_UU(uu_end);
3398121326Sharti	send_end(sscop, 1, NULL);
3399121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
3400121326Sharti	SSCOP_MSG_FREE(msg);
3401121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
3402121326Sharti}
3403121326Sharti
3404121326Sharti/*
3405121326Sharti * p 57: IN_REC_PEND && STAT PDU
3406121326Sharti *	arg is pdu (freed)
3407121326Sharti */
3408121326Shartistatic void
3409121326Shartisscop_inrec_stat(struct sscop *sscop, struct sscop_msg *msg)
3410121326Sharti{
3411121326Sharti	MAAL_ERROR(sscop, 'H', 0);
3412121326Sharti	FREE_UU(uu_end);
3413121326Sharti	send_end(sscop, 1, NULL);
3414121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
3415121326Sharti	SSCOP_MSG_FREE(msg);
3416121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
3417121326Sharti}
3418121326Sharti
3419121326Sharti/*
3420121326Sharti * p 57: IN_REC_PEND && POLL PDU
3421121326Sharti *	arg is pdu (freed)
3422121326Sharti */
3423121326Shartistatic void
3424121326Shartisscop_inrec_poll(struct sscop *sscop, struct sscop_msg *msg)
3425121326Sharti{
3426121326Sharti	MAAL_ERROR(sscop, 'G', 0);
3427121326Sharti	FREE_UU(uu_end);
3428121326Sharti	send_end(sscop, 1, NULL);
3429121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
3430121326Sharti	SSCOP_MSG_FREE(msg);
3431121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
3432121326Sharti}
3433121326Sharti
3434121326Sharti/*
3435121326Sharti * p 57: IN_REC_PEND && SD PDU
3436121326Sharti *	arg is pdu (freed)
3437121326Sharti */
3438121326Shartistatic void
3439121326Shartisscop_inrec_sd(struct sscop *sscop, struct sscop_msg *msg)
3440121326Sharti{
3441121326Sharti	MAAL_ERROR(sscop, 'A', 0);
3442121326Sharti	FREE_UU(uu_end);
3443121326Sharti	send_end(sscop, 1, NULL);
3444121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
3445121326Sharti	SSCOP_MSG_FREE(msg);
3446121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
3447121326Sharti}
3448121326Sharti
3449121326Sharti/*
3450121326Sharti * p 58: IN_REC_PEND && RSAK PDU
3451121326Sharti *	arg is pdu (freed).
3452121326Sharti */
3453121326Shartistatic void
3454121326Shartisscop_inrec_rsak(struct sscop *sscop, struct sscop_msg *msg)
3455121326Sharti{
3456121326Sharti	SSCOP_MSG_FREE(msg);
3457121326Sharti	MAAL_ERROR(sscop, 'K', 0);
3458121326Sharti}
3459121326Sharti
3460121326Sharti/*
3461121326Sharti * p 58: IN_REC_PEND && RS PDU
3462121326Sharti *	arg is pdu (freed).
3463121326Sharti */
3464121326Shartistatic void
3465121326Shartisscop_inrec_rs(struct sscop *sscop, struct sscop_msg *msg)
3466121326Sharti{
3467121326Sharti	union pdu pdu;
3468121326Sharti
3469121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
3470121326Sharti
3471121326Sharti	if(m_detect_retransmission(sscop, msg)) {
3472121326Sharti		SSCOP_MSG_FREE(msg);
3473121326Sharti		MAAL_ERROR(sscop, 'J', 0);
3474121326Sharti		return;
3475121326Sharti	}
3476121326Sharti	(void)MBUF_STRIP32(msg->m);
3477121326Sharti
3478121326Sharti	sscop->vt_ms = pdu.sscop_ns;
3479121326Sharti	AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_indication, msg, pdu.sscop_pl, 0);
3480121326Sharti
3481121326Sharti	sscop_set_state(sscop, SSCOP_IN_RESYNC_PEND);
3482121326Sharti}
3483121326Sharti
3484121326Sharti/*
3485121326Sharti * p 59: IN_REC_PEND && ER PDU
3486121326Sharti *	arg is pdu (freed)
3487121326Sharti */
3488121326Shartistatic void
3489121326Shartisscop_inrec_er(struct sscop *sscop, struct sscop_msg *msg)
3490121326Sharti{
3491121326Sharti	union pdu pdu;
3492121326Sharti
3493121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
3494121326Sharti
3495121326Sharti	if(!m_detect_retransmission(sscop, msg)) {
3496121326Sharti		MAAL_ERROR(sscop, 'L', 0);
3497121326Sharti	}
3498121326Sharti
3499121326Sharti	SSCOP_MSG_FREE(msg);
3500121326Sharti}
3501121326Sharti
3502121326Sharti/*
3503121326Sharti * p 59: IN_REC_PEND && BGN PDU
3504121326Sharti *	arg is pdu (freed).
3505121326Sharti *	no uui
3506121326Sharti */
3507121326Shartistatic void
3508121326Shartisscop_inrec_bgn(struct sscop *sscop, struct sscop_msg *msg)
3509121326Sharti{
3510121326Sharti	union pdu pdu;
3511121326Sharti
3512121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
3513121326Sharti
3514121326Sharti	if(m_detect_retransmission(sscop, msg)) {
3515121326Sharti		MAAL_ERROR(sscop, 'B', 0);
3516121326Sharti		SSCOP_MSG_FREE(msg);
3517121326Sharti		return;
3518121326Sharti	}
3519121326Sharti	(void)MBUF_STRIP32(msg->m);
3520121326Sharti
3521121326Sharti	sscop->vt_ms = pdu.sscop_ns;
3522121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
3523121326Sharti	AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0);
3524121326Sharti
3525121326Sharti	sscop_set_state(sscop, SSCOP_IN_PEND);
3526121326Sharti}
3527121326Sharti
3528121326Sharti/*
3529121326Sharti * p 59: IN_REC_PEND && BGAK PDU
3530121326Sharti *	arg is pdu (freed)
3531121326Sharti *	no uui
3532121326Sharti */
3533121326Shartistatic void
3534121326Shartisscop_inrec_bgak(struct sscop *sscop, struct sscop_msg *msg)
3535121326Sharti{
3536121326Sharti	MAAL_ERROR(sscop, 'C', 0);
3537121326Sharti	SSCOP_MSG_FREE(msg);
3538121326Sharti}
3539121326Sharti
3540121326Sharti/*
3541121326Sharti * p 59: IN_REC_PEND && ERAK PDU
3542121326Sharti *	arg is pdu (freed)
3543121326Sharti *	no uui
3544121326Sharti */
3545121326Shartistatic void
3546121326Shartisscop_inrec_erak(struct sscop *sscop, struct sscop_msg *msg)
3547121326Sharti{
3548121326Sharti	MAAL_ERROR(sscop, 'M', 0);
3549121326Sharti	SSCOP_MSG_FREE(msg);
3550121326Sharti}
3551121326Sharti
3552121326Sharti/*
3553121326Sharti * p 60: READY && RESYNC request
3554121326Sharti *	arg is UU
3555121326Sharti */
3556121326Shartistatic void
3557121326Shartisscop_ready_sync_req(struct sscop *sscop, struct sscop_msg *uu)
3558121326Sharti{
3559121326Sharti	SET_UU(uu_rs, uu);
3560121326Sharti
3561121326Sharti	m_reset_data_xfer_timers(sscop);
3562121326Sharti	sscop->vt_cc = 1;
3563121326Sharti	sscop->vt_sq++;
3564121326Sharti	m_initialize_mr(sscop);
3565121326Sharti	send_rs(sscop, 0, sscop->uu_rs);
3566121326Sharti	m_release_buffers(sscop);
3567121326Sharti	TIMER_RESTART(sscop, cc);
3568121326Sharti
3569121326Sharti	sscop_set_state(sscop, SSCOP_OUT_RESYNC_PEND);
3570121326Sharti}
3571121326Sharti
3572121326Sharti
3573121326Sharti/*
3574121326Sharti * p 60: READY && AA-RELEASE.request
3575121326Sharti *	arg is uu.
3576121326Sharti */
3577121326Shartistatic void
3578121326Shartisscop_ready_release_req(struct sscop *sscop, struct sscop_msg *uu)
3579121326Sharti{
3580121326Sharti	SET_UU(uu_end, uu);
3581121326Sharti
3582121326Sharti	m_reset_data_xfer_timers(sscop);
3583121326Sharti	sscop->vt_cc = 1;
3584121326Sharti	send_end(sscop, 0, sscop->uu_end);
3585121326Sharti	m_prepare_retrieval(sscop);
3586121326Sharti	TIMER_RESTART(sscop, cc);
3587121326Sharti
3588121326Sharti	sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
3589121326Sharti}
3590121326Sharti
3591121326Sharti/*
3592121326Sharti * p 61: READY && ER PDU
3593121326Sharti *	arg is pdu (freed).
3594121326Sharti */
3595121326Shartistatic void
3596121326Shartisscop_ready_er(struct sscop *sscop, struct sscop_msg *msg)
3597121326Sharti{
3598121326Sharti	union pdu pdu;
3599121326Sharti
3600121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
3601121326Sharti
3602121326Sharti	if(m_detect_retransmission(sscop, msg)) {
3603121326Sharti		TIMER_RESTART(sscop, nr);
3604121326Sharti		send_erak(sscop);
3605121326Sharti	} else {
3606121326Sharti		m_reset_data_xfer_timers(sscop);
3607121326Sharti		sscop->vt_ms = pdu.sscop_ns;
3608121326Sharti		m_prepare_recovery(sscop);
3609121326Sharti		m_deliver_data(sscop);
3610121326Sharti
3611121326Sharti		AAL_SIG(sscop, SSCOP_RECOVER_indication);
3612121326Sharti
3613121326Sharti		sscop_set_state(sscop, SSCOP_IN_REC_PEND);
3614121326Sharti	}
3615121326Sharti
3616121326Sharti	SSCOP_MSG_FREE(msg);
3617121326Sharti}
3618121326Sharti
3619121326Sharti/*
3620121326Sharti * p 61: READY && BGN PDU
3621121326Sharti *	arg is pdu (freed)
3622121326Sharti */
3623121326Shartistatic void
3624121326Shartisscop_ready_bgn(struct sscop *sscop, struct sscop_msg *msg)
3625121326Sharti{
3626121326Sharti	union pdu pdu;
3627121326Sharti
3628121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
3629121326Sharti
3630121326Sharti	if(m_detect_retransmission(sscop, msg)) {
3631121326Sharti		TIMER_RESTART(sscop, nr);
3632121326Sharti		send_bgak(sscop, sscop->uu_bgak);
3633121326Sharti		SSCOP_MSG_FREE(msg);
3634121326Sharti		return;
3635121326Sharti	}
3636121326Sharti	(void)MBUF_STRIP32(msg->m);
3637121326Sharti
3638121326Sharti	m_reset_data_xfer_timers(sscop);
3639121326Sharti	sscop->vt_ms = pdu.sscop_ns;
3640121326Sharti
3641121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
3642121326Sharti	AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0);
3643121326Sharti
3644121326Sharti	m_prepare_retrieval(sscop);
3645121326Sharti
3646121326Sharti	sscop_set_state(sscop, SSCOP_IN_PEND);
3647121326Sharti}
3648121326Sharti
3649121326Sharti/*
3650121326Sharti * p 62: READY && ENDAK PDU
3651121326Sharti *	arg is pdu (freed)
3652121326Sharti */
3653121326Shartistatic void
3654121326Shartisscop_ready_endak(struct sscop *sscop, struct sscop_msg *msg)
3655121326Sharti{
3656121326Sharti	m_reset_data_xfer_timers(sscop);
3657121326Sharti	MAAL_ERROR(sscop, 'F', 0);
3658121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
3659121326Sharti	m_prepare_retrieval(sscop);
3660121326Sharti	SSCOP_MSG_FREE(msg);
3661121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
3662121326Sharti}
3663121326Sharti
3664121326Sharti/*
3665121326Sharti * p 62: READY && BGREJ PDU
3666121326Sharti *	arg is pdu (freed)
3667121326Sharti */
3668121326Shartistatic void
3669121326Shartisscop_ready_bgrej(struct sscop *sscop, struct sscop_msg *msg)
3670121326Sharti{
3671121326Sharti	m_reset_data_xfer_timers(sscop);
3672121326Sharti	MAAL_ERROR(sscop, 'D', 0);
3673121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
3674121326Sharti	m_prepare_retrieval(sscop);
3675121326Sharti	SSCOP_MSG_FREE(msg);
3676121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
3677121326Sharti}
3678121326Sharti
3679121326Sharti/*
3680121326Sharti * p 62: READY && RS PDU
3681121326Sharti *	arg is pdu (freed)
3682121326Sharti */
3683121326Shartistatic void
3684121326Shartisscop_ready_rs(struct sscop *sscop, struct sscop_msg *msg)
3685121326Sharti{
3686121326Sharti	union pdu pdu;
3687121326Sharti
3688121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
3689121326Sharti
3690121326Sharti	if(m_detect_retransmission(sscop, msg)) {
3691121326Sharti		SSCOP_MSG_FREE(msg);
3692121326Sharti		TIMER_RESTART(sscop, nr);
3693121326Sharti		send_rsak(sscop);
3694121326Sharti		return;
3695121326Sharti	}
3696121326Sharti	(void)MBUF_STRIP32(msg->m);
3697121326Sharti
3698121326Sharti	m_reset_data_xfer_timers(sscop);
3699121326Sharti	sscop->vt_ms = pdu.sscop_ns;
3700121326Sharti	AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_indication, msg, pdu.sscop_pl, 0);
3701121326Sharti	m_prepare_retrieval(sscop);
3702121326Sharti
3703121326Sharti	sscop_set_state(sscop, SSCOP_IN_RESYNC_PEND);
3704121326Sharti}
3705121326Sharti
3706121326Sharti/*
3707121326Sharti * p 62: READY && END PDU
3708121326Sharti *	arg is pdu (freed)
3709121326Sharti */
3710121326Shartistatic void
3711121326Shartisscop_ready_end(struct sscop *sscop, struct sscop_msg *msg)
3712121326Sharti{
3713121326Sharti	union pdu pdu;
3714121326Sharti
3715121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
3716121326Sharti	(void)MBUF_STRIP32(msg->m);
3717121326Sharti
3718121326Sharti	m_reset_data_xfer_timers(sscop);
3719121326Sharti	send_endak(sscop);
3720121326Sharti	AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication,
3721121326Sharti		msg, pdu.sscop_pl, (u_int)pdu.sscop_s);
3722121326Sharti	m_prepare_retrieval(sscop);
3723121326Sharti
3724121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
3725121326Sharti}
3726121326Sharti
3727121326Sharti/*
3728121326Sharti * p 63: READY && POLL expiry
3729121326Sharti */
3730121326Shartistatic void
3731121326Shartisscop_ready_tpoll(struct sscop *sscop, struct sscop_msg *unused __unused)
3732121326Sharti{
3733121326Sharti	sscop->vt_ps++;
3734121326Sharti	send_poll(sscop);
3735121326Sharti	sscop->vt_pd = 0;
3736121326Sharti	m_set_poll_timer(sscop);
3737121326Sharti}
3738121326Sharti
3739121326Sharti/*
3740121326Sharti * p 63: READY && KEEP_ALIVE expiry
3741121326Sharti */
3742121326Shartistatic void
3743121326Shartisscop_ready_tka(struct sscop *sscop, struct sscop_msg *unused __unused)
3744121326Sharti{
3745121326Sharti	sscop->vt_ps++;
3746121326Sharti	send_poll(sscop);
3747121326Sharti	sscop->vt_pd = 0;
3748121326Sharti	m_set_poll_timer(sscop);
3749121326Sharti}
3750121326Sharti
3751121326Sharti/*
3752121326Sharti * p 63: READY && IDLE expiry
3753121326Sharti */
3754121326Shartistatic void
3755121326Shartisscop_ready_tidle(struct sscop *sscop, struct sscop_msg *unused __unused)
3756121326Sharti{
3757121326Sharti	TIMER_RESTART(sscop, nr);
3758121326Sharti	sscop->vt_ps++;
3759121326Sharti	send_poll(sscop);
3760121326Sharti	sscop->vt_pd = 0;
3761121326Sharti	m_set_poll_timer(sscop);
3762121326Sharti}
3763121326Sharti
3764121326Sharti/*
3765121326Sharti * p 63: READY && NO_RESPONSE expiry
3766121326Sharti *	no arg
3767121326Sharti */
3768121326Shartistatic void
3769121326Shartisscop_ready_nr(struct sscop *sscop, struct sscop_msg *unused __unused)
3770121326Sharti{
3771121326Sharti	m_reset_data_xfer_timers(sscop);
3772121326Sharti	MAAL_ERROR(sscop, 'P', 0);
3773121326Sharti	FREE_UU(uu_end);
3774121326Sharti	send_end(sscop, 1, NULL);
3775121326Sharti	AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
3776121326Sharti	m_prepare_retrieval(sscop);
3777121326Sharti	sscop_set_state(sscop, SSCOP_IDLE);
3778121326Sharti}
3779121326Sharti
3780121326Sharti/*
3781121326Sharti * p 63: READY && AA-DATA.request
3782121326Sharti *	arg is message (queued).
3783121326Sharti */
3784121326Shartistatic void
3785121326Shartisscop_ready_userdata(struct sscop *sscop, struct sscop_msg *msg)
3786121326Sharti{
3787121326Sharti	MSGQ_APPEND(&sscop->xq, msg);
3788121326Sharti
3789121326Sharti	sscop_signal(sscop, SIG_PDU_Q, msg);
3790121326Sharti}
3791121326Sharti
3792121326Sharti/*
3793121326Sharti * p 64: READY && SD PDU queued up
3794121326Sharti *	arg is unused.
3795121326Sharti */
3796121326Shartistatic void
3797121326Shartisscop_ready_pduq(struct sscop *sscop, struct sscop_msg *unused __unused)
3798121326Sharti{
3799121326Sharti	struct sscop_msg *msg;
3800121326Sharti
3801121326Sharti	if(sscop->rxq != 0) {
3802121326Sharti		TAILQ_FOREACH(msg, &sscop->xbuf, link)
3803121326Sharti			if(msg->rexmit)
3804121326Sharti				break;
3805121326Sharti		ASSERT(msg != NULL);
3806121326Sharti		msg->rexmit = 0;
3807121326Sharti		sscop->rxq--;
3808121326Sharti		send_sd(sscop, msg->m, msg->seqno);
3809121326Sharti		msg->poll_seqno = sscop->vt_ps;
3810121326Sharti		if(sscop->poll_after_rex && sscop->rxq == 0)
3811121326Sharti			goto poll;			/* -> A */
3812121326Sharti		else
3813121326Sharti			goto maybe_poll;		/* -> B */
3814121326Sharti
3815121326Sharti	}
3816121326Sharti	if(MSGQ_EMPTY(&sscop->xq))
3817121326Sharti		return;
3818121326Sharti
3819121326Sharti	if(sscop->vt_s >= sscop->vt_ms) {
3820121326Sharti		/* Send windows closed */
3821121326Sharti		TIMER_STOP(sscop, idle);
3822121326Sharti		TIMER_RESTART(sscop, nr);
3823121326Sharti		goto poll;			/* -> A */
3824121326Sharti
3825121326Sharti	} else {
3826121326Sharti		msg = MSGQ_GET(&sscop->xq);
3827121326Sharti		msg->seqno = sscop->vt_s;
3828121326Sharti		send_sd(sscop, msg->m, msg->seqno);
3829121326Sharti		msg->poll_seqno = sscop->vt_ps;
3830121326Sharti		sscop->vt_s++;
3831121326Sharti		MSGQ_APPEND(&sscop->xbuf, msg);
3832121326Sharti		goto maybe_poll;		/* -> B */
3833121326Sharti	}
3834121326Sharti
3835121326Sharti	/*
3836121326Sharti	 * p 65: Poll handling
3837121326Sharti	 */
3838121326Sharti  maybe_poll:					/* label B */
3839121326Sharti	sscop->vt_pd++;
3840121326Sharti	if(TIMER_ISACT(sscop, poll)) {
3841121326Sharti		if(sscop->vt_pd < sscop->maxpd)
3842121326Sharti			return;
3843121326Sharti	} else {
3844121326Sharti		 if(TIMER_ISACT(sscop, idle)) {
3845121326Sharti			TIMER_STOP(sscop, idle);
3846121326Sharti			TIMER_RESTART(sscop, nr);
3847121326Sharti		} else {
3848121326Sharti			TIMER_STOP(sscop, ka);
3849121326Sharti		}
3850121326Sharti		if(sscop->vt_pd < sscop->maxpd) {
3851121326Sharti			TIMER_RESTART(sscop, poll);
3852121326Sharti			return;
3853121326Sharti		}
3854121326Sharti	}
3855121326Sharti  poll:						/* label A */
3856121326Sharti	sscop->vt_ps++;
3857121326Sharti	send_poll(sscop);
3858121326Sharti	sscop->vt_pd = 0;
3859121326Sharti	TIMER_RESTART(sscop, poll);
3860121326Sharti}
3861121326Sharti
3862121326Sharti/*
3863121326Sharti * p 67: common recovery start
3864121326Sharti */
3865121326Shartistatic void
3866121326Shartisscop_recover(struct sscop *sscop)
3867121326Sharti{
3868121326Sharti	sscop->vt_cc = 1;
3869121326Sharti	sscop->vt_sq++;
3870121326Sharti
3871121326Sharti	m_initialize_mr(sscop);
3872121326Sharti	send_er(sscop);
3873121326Sharti	m_prepare_recovery(sscop);
3874121326Sharti
3875121326Sharti	TIMER_RESTART(sscop, cc);
3876121326Sharti
3877121326Sharti	sscop_set_state(sscop, SSCOP_OUT_REC_PEND);
3878121326Sharti}
3879121326Sharti
3880121326Sharti/*
3881121326Sharti * p 66: READY && SD PDU
3882121326Sharti *	arg is received message.
3883121326Sharti */
3884121326Shartistatic void
3885121326Shartisscop_ready_sd(struct sscop *sscop, struct sscop_msg *msg)
3886121326Sharti{
3887121326Sharti	union pdu pdu;
3888121326Sharti	u_int sn;
3889121326Sharti
3890121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
3891121326Sharti	msg->seqno = pdu.sscop_ns;
3892121326Sharti
3893121326Sharti	/* Fix padding */
3894121326Sharti	MBUF_UNPAD(msg->m, pdu.sscop_pl);
3895121326Sharti
3896121326Sharti	if(msg->seqno >= sscop->vr_mr) {
3897121326Sharti		/* message outside window */
3898121326Sharti		if(sscop->vr_h < sscop->vr_mr) {
3899121326Sharti			send_ustat(sscop, sscop->vr_h, sscop->vr_mr, -1);
3900121326Sharti			sscop->vr_h = sscop->vr_mr;
3901121326Sharti		}
3902121326Sharti		SSCOP_MSG_FREE(msg);
3903121326Sharti		return;
3904121326Sharti	}
3905121326Sharti
3906121326Sharti	if(msg->seqno == sscop->vr_r) {
3907121326Sharti		if(msg->seqno == sscop->vr_h) {
3908121326Sharti			sscop->vr_r = msg->seqno + 1;
3909121326Sharti			sscop->vr_h = msg->seqno + 1;
3910121326Sharti
3911121326Sharti			AAL_DATA(sscop, SSCOP_DATA_indication,
3912121326Sharti				msg->m, msg->seqno);
3913121326Sharti			msg->m = NULL;
3914121326Sharti			SSCOP_MSG_FREE(msg);
3915121326Sharti
3916121326Sharti			return;
3917121326Sharti		}
3918121326Sharti		for(;;) {
3919121326Sharti			AAL_DATA(sscop, SSCOP_DATA_indication,
3920121326Sharti				msg->m, msg->seqno);
3921121326Sharti			msg->m = NULL;
3922121326Sharti			SSCOP_MSG_FREE(msg);
3923121326Sharti
3924121326Sharti			sscop->vr_r++;
3925121326Sharti			if((msg = MSGQ_PEEK(&sscop->rbuf)) == NULL)
3926121326Sharti				break;
3927121326Sharti			sn = msg->seqno;
3928121326Sharti			ASSERT(sn >= sscop->vr_r);
3929121326Sharti			if(sn != sscop->vr_r)
3930121326Sharti				break;
3931121326Sharti			msg = MSGQ_GET(&sscop->rbuf);
3932121326Sharti		}
3933121326Sharti		return;
3934121326Sharti	}
3935121326Sharti
3936121326Sharti	/* Messages were lost */
3937121326Sharti
3938121326Sharti	/* XXX Flow control */
3939121326Sharti	if(msg->seqno == sscop->vr_h) {
3940121326Sharti		QINSERT(&sscop->rbuf, msg);
3941121326Sharti		sscop->vr_h++;
3942121326Sharti		return;
3943121326Sharti	}
3944121326Sharti	if(sscop->vr_h < msg->seqno) {
3945121326Sharti		QINSERT(&sscop->rbuf, msg);
3946121326Sharti		send_ustat(sscop, sscop->vr_h, msg->seqno, -1);
3947121326Sharti		sscop->vr_h = msg->seqno + 1;
3948121326Sharti		return;
3949121326Sharti	}
3950121326Sharti
3951121326Sharti	if(QFIND(&sscop->rbuf, msg->seqno) == NULL) {
3952121326Sharti		QINSERT(&sscop->rbuf, msg);
3953121326Sharti		return;
3954121326Sharti	}
3955121326Sharti
3956121326Sharti	/* error: start recovery */
3957121326Sharti	SSCOP_MSG_FREE(msg);
3958121326Sharti	m_reset_data_xfer_timers(sscop);
3959121326Sharti	MAAL_ERROR(sscop, 'Q', 0);
3960121326Sharti	sscop_recover(sscop);
3961121326Sharti}
3962121326Sharti
3963121326Sharti/*
3964121326Sharti * p 67: READY && POLL PDU
3965121326Sharti */
3966121326Shartistatic void
3967121326Shartisscop_ready_poll(struct sscop *sscop, struct sscop_msg *msg)
3968121326Sharti{
3969121326Sharti	union pdu pdu;
3970121326Sharti	union seqno seqno;
3971121326Sharti	u_int sn, nps;
3972121326Sharti	struct SSCOP_MBUF_T *m;
3973121326Sharti
3974121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
3975121326Sharti	seqno.sscop_null = MBUF_STRIP32(msg->m);
3976121326Sharti
3977121326Sharti	if((u_int)pdu.sscop_ns < sscop->vr_h) {
3978121326Sharti		SSCOP_MSG_FREE(msg);
3979121326Sharti		m_reset_data_xfer_timers(sscop);
3980121326Sharti		MAAL_ERROR(sscop, 'Q', 0);
3981121326Sharti		sscop_recover(sscop);
3982121326Sharti		return;
3983121326Sharti	}
3984121326Sharti	nps = seqno.sscop_n;
3985121326Sharti
3986121326Sharti	if((u_int)pdu.sscop_ns > sscop->vr_mr)
3987121326Sharti		sscop->vr_h = sscop->vr_mr;
3988121326Sharti	else
3989121326Sharti		sscop->vr_h = pdu.sscop_ns;
3990121326Sharti
3991121326Sharti	SSCOP_MSG_FREE(msg);
3992121326Sharti
3993121326Sharti	/* build stat pdu */
3994121326Sharti	if((m = MBUF_ALLOC(sscop->maxstat * 4 + 12)) == NULL) {
3995121326Sharti		FAILURE("sscop: cannot allocate STAT");
3996121326Sharti		return;
3997121326Sharti	}
3998121326Sharti	sn = sscop->vr_r;
3999121326Sharti
4000121326Sharti	while(sn != sscop->vr_h) {
4001121326Sharti		/* loop through burst we already have */
4002121326Sharti		for(;;) {
4003121326Sharti			if(sn >= sscop->vr_h) {
4004121326Sharti				seqno.sscop_null = 0;
4005121326Sharti				seqno.sscop_n = sn;
4006121326Sharti				MBUF_APPEND32(m, seqno.sscop_null);
4007121326Sharti				goto out;
4008121326Sharti			}
4009121326Sharti			if(QFIND(&sscop->rbuf, sn) == NULL)
4010121326Sharti				break;
4011121326Sharti			sn++;
4012121326Sharti		}
4013121326Sharti
4014121326Sharti		/* start of a hole */
4015121326Sharti		seqno.sscop_null = 0;
4016121326Sharti		seqno.sscop_n = sn;
4017121326Sharti		MBUF_APPEND32(m, seqno.sscop_null);
4018121326Sharti		if(MBUF_LEN(m)/4 >= sscop->maxstat) {
4019121326Sharti			send_stat(sscop, nps, m);
4020121326Sharti			if((m = MBUF_ALLOC(sscop->maxstat * 4 + 12)) == NULL) {
4021121326Sharti				FAILURE("sscop: cannot allocate STAT");
4022121326Sharti				return;
4023121326Sharti			}
4024121326Sharti			seqno.sscop_null = 0;
4025121326Sharti			seqno.sscop_n = sn;
4026121326Sharti			MBUF_APPEND32(m, seqno.sscop_null);
4027121326Sharti		}
4028121326Sharti		do {
4029121326Sharti			sn++;
4030121326Sharti		} while(sn < sscop->vr_h && !QFIND(&sscop->rbuf, sn));
4031121326Sharti		seqno.sscop_null = 0;
4032121326Sharti		seqno.sscop_n = sn;
4033121326Sharti		MBUF_APPEND32(m, seqno.sscop_null);
4034121326Sharti	}
4035121326Sharti  out:
4036121326Sharti	send_stat(sscop, nps, m);
4037121326Sharti}
4038121326Sharti
4039121326Sharti/*
4040121326Sharti * p 69: READY && USTAT PDU
4041121326Sharti *	arg is msg (freed)
4042121326Sharti */
4043121326Shartistatic void
4044121326Shartisscop_ready_ustat(struct sscop *sscop, struct sscop_msg *msg)
4045121326Sharti{
4046121326Sharti	union pdu pdu;
4047121326Sharti	union seqno nmr, sq1, sq2;
4048121326Sharti	u_int cnt;
4049121326Sharti
4050121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
4051121326Sharti	nmr.sscop_null = MBUF_STRIP32(msg->m);
4052121326Sharti	sq2.sscop_null = MBUF_STRIP32(msg->m);
4053121326Sharti	sq1.sscop_null = MBUF_STRIP32(msg->m);
4054121326Sharti
4055121326Sharti	SSCOP_MSG_FREE(msg);
4056121326Sharti
4057121326Sharti	cnt = sq1.sscop_n - sq2.sscop_n;
4058121326Sharti
4059121326Sharti	if((u_int)pdu.sscop_ns < sscop->vt_a || (u_int)pdu.sscop_ns >= sscop->vt_s) {
4060121326Sharti		VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg,
4061121326Sharti		    "USTAT: N(R) outside VT(A)...VT(S)-1: N(R)=%u VT(A)=%u "
4062121326Sharti		    "VT(S)=%u", (u_int)pdu.sscop_ns, sscop->vt_a, sscop->vt_s));
4063121326Sharti		goto err_f;
4064121326Sharti	}
4065121326Sharti
4066121326Sharti	/* Acknowledge all messages between VT(A) and N(R)-1. N(R) is the new
4067121326Sharti	 * next in sequence-SD-number of the receiver and means, it has all
4068121326Sharti	 * messages below N(R). Remove all message below N(R) from the
4069121326Sharti	 * transmission buffer. It may already be removed because of an
4070121326Sharti	 * earlier selective ACK in a STAT message.
4071121326Sharti	 */
4072121326Sharti	while((msg = MSGQ_PEEK(&sscop->xbuf)) != NULL && msg->seqno < (u_int)pdu.sscop_ns) {
4073121326Sharti		ASSERT(msg->seqno >= sscop->vt_a);
4074121326Sharti		MSGQ_REMOVE(&sscop->xbuf, msg);
4075121326Sharti		SSCOP_MSG_FREE(msg);
4076121326Sharti	}
4077121326Sharti
4078121326Sharti	/* Update the in-sequence acknowledge and the send window */
4079121326Sharti	sscop->vt_a = pdu.sscop_ns;
4080121326Sharti	sscop->vt_ms = nmr.sscop_n;
4081121326Sharti
4082121326Sharti	/* check, that the range of requested re-transmissions is between
4083121326Sharti	 * the in-sequence-ack and the highest up-to-now transmitted SD
4084121326Sharti	 */
4085121326Sharti	if(sq1.sscop_n >= sq2.sscop_n
4086121326Sharti	    || (u_int)sq1.sscop_n < sscop->vt_a
4087121326Sharti	    || (u_int)sq2.sscop_n >= sscop->vt_s) {
4088121326Sharti		VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg,
4089121326Sharti		    "USTAT: seq1 or seq2 outside VT(A)...VT(S)-1 or seq1>=seq2:"
4090121326Sharti		    " seq1=%u seq2=%u VT(A)=%u VT(S)=%u",
4091121326Sharti		    sq1.sscop_n, sq2.sscop_n, sscop->vt_a, sscop->vt_s));
4092121326Sharti		goto err_f;
4093121326Sharti	}
4094121326Sharti
4095121326Sharti	/*
4096121326Sharti	 * Retransmit all messages from seq1 to seq2-1
4097121326Sharti	 */
4098121326Sharti	do {
4099121326Sharti		/*
4100121326Sharti		 * The message may not be in the transmit buffer if it was
4101121326Sharti		 * already acked by a STAT. This means, the receiver is
4102121326Sharti		 * confused.
4103121326Sharti		 */
4104121326Sharti		if((msg = QFIND(&sscop->xbuf, sq1.sscop_n)) == NULL) {
4105121326Sharti			VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg,
4106121326Sharti			    "USTAT: message %u not found in xmit buffer",
4107121326Sharti			    sq1.sscop_n));
4108121326Sharti			goto err_f;
4109121326Sharti		}
4110121326Sharti
4111121326Sharti		/*
4112121326Sharti		 * If it is not yet in the re-transmission queue, put it there
4113121326Sharti		 */
4114121326Sharti		if(!msg->rexmit) {
4115121326Sharti			msg->rexmit = 1;
4116121326Sharti			sscop->rxq++;
4117121326Sharti			sscop_signal(sscop, SIG_PDU_Q, msg);
4118121326Sharti		}
4119121326Sharti		sq1.sscop_n++;
4120121326Sharti	} while(sq1.sscop_n != sq2.sscop_n);
4121121326Sharti
4122121326Sharti	/*
4123121326Sharti	 * report the re-transmission to the management
4124121326Sharti	 */
4125121326Sharti	MAAL_ERROR(sscop, 'V', cnt);
4126121326Sharti	return;
4127121326Sharti
4128121326Sharti  err_f:
4129121326Sharti	m_reset_data_xfer_timers(sscop);
4130121326Sharti	MAAL_ERROR(sscop, 'T', 0);
4131121326Sharti	sscop_recover(sscop);
4132121326Sharti}
4133121326Sharti
4134121326Sharti/*
4135121326Sharti * p 70: READY && STAT PDU
4136121326Sharti *	arg is msg (freed).
4137121326Sharti */
4138121326Shartistatic void
4139121326Shartisscop_ready_stat(struct sscop *sscop, struct sscop_msg *msg)
4140121326Sharti{
4141121326Sharti	union pdu pdu;
4142121326Sharti	union seqno nps, nmr;
4143121326Sharti	u_int len, seq1, seq2, cnt;
4144121326Sharti	struct sscop_msg *m;
4145121326Sharti
4146121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
4147121326Sharti	nmr.sscop_null = MBUF_STRIP32(msg->m);
4148121326Sharti	nps.sscop_null = MBUF_STRIP32(msg->m);
4149121326Sharti
4150121326Sharti	len = MBUF_LEN(msg->m) / 4;
4151121326Sharti
4152121326Sharti	if((u_int)nps.sscop_n < sscop->vt_pa
4153121326Sharti	    || (u_int)nps.sscop_n > sscop->vt_ps) {
4154121326Sharti		SSCOP_MSG_FREE(msg);
4155121326Sharti		m_reset_data_xfer_timers(sscop);
4156121326Sharti		MAAL_ERROR(sscop, 'R', 0);
4157121326Sharti		sscop_recover(sscop);
4158121326Sharti		return;
4159121326Sharti	}
4160121326Sharti
4161121326Sharti	if((u_int)pdu.sscop_ns < sscop->vt_a
4162121326Sharti	    || (u_int)pdu.sscop_ns > sscop->vt_s) {
4163121326Sharti		/*
4164121326Sharti		 * The in-sequence acknowledge, i.e. the receivers's next
4165121326Sharti		 * expected in-sequence msg is outside the window between
4166121326Sharti		 * the transmitters in-sequence ack and highest seqno -
4167121326Sharti		 * the receiver seems to be confused.
4168121326Sharti		 */
4169121326Sharti		VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg,
4170121326Sharti		    "STAT: N(R) outside VT(A)...VT(S)-1: N(R)=%u VT(A)=%u "
4171121326Sharti		    "VT(S)=%u", (u_int)pdu.sscop_ns, sscop->vt_a, sscop->vt_s));
4172121326Sharti  err_H:
4173121326Sharti		SSCOP_MSG_FREE(msg);
4174121326Sharti		m_reset_data_xfer_timers(sscop);
4175121326Sharti		MAAL_ERROR(sscop, 'S', 0);
4176121326Sharti		sscop_recover(sscop);
4177121326Sharti		return;
4178121326Sharti	}
4179121326Sharti
4180121326Sharti	/* Acknowledge all messages between VT(A) and N(R)-1. N(R) is the new
4181121326Sharti	 * next in sequence-SD-number of the receiver and means, it has all
4182121326Sharti	 * messages below N(R). Remove all message below N(R) from the
4183121326Sharti	 * transmission buffer. It may already be removed because of an
4184121326Sharti	 * earlier selective ACK in a STAT message.
4185121326Sharti	 */
4186121326Sharti	while((m = MSGQ_PEEK(&sscop->xbuf)) != NULL
4187121326Sharti	    && m->seqno < (u_int)pdu.sscop_ns) {
4188121326Sharti		ASSERT(m->seqno >= sscop->vt_a);
4189121326Sharti		MSGQ_REMOVE(&sscop->xbuf, m);
4190121326Sharti		SSCOP_MSG_FREE(m);
4191121326Sharti	}
4192121326Sharti
4193121326Sharti	/*
4194121326Sharti	 * Update in-sequence ack, poll-ack and send window.
4195121326Sharti	 */
4196121326Sharti	sscop->vt_a = pdu.sscop_ns;
4197121326Sharti	sscop->vt_pa = nps.sscop_n;
4198121326Sharti	sscop->vt_ms = nmr.sscop_n;
4199121326Sharti
4200121326Sharti	cnt = 0;
4201121326Sharti	if(len > 1) {
4202121326Sharti		seq1 = MBUF_GET32(msg->m);
4203121326Sharti		len--;
4204121326Sharti		if(seq1 >= sscop->vt_s) {
4205121326Sharti			VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg,
4206121326Sharti			    "STAT: seq1 >= VT(S): seq1=%u VT(S)=%u",
4207121326Sharti			    seq1, sscop->vt_s));
4208121326Sharti			goto err_H;
4209121326Sharti		}
4210121326Sharti
4211121326Sharti		for(;;) {
4212121326Sharti			seq2 = MBUF_GET32(msg->m);
4213121326Sharti			len--;
4214121326Sharti			if(seq1 >= seq2 || seq2 > sscop->vt_s) {
4215121326Sharti				VERBERR(sscop, SSCOP_DBG_ERR, (sscop,
4216121326Sharti				    sscop->aarg, "STAT: seq1 >= seq2 or "
4217121326Sharti				    "seq2 > VT(S): seq1=%u seq2=%u VT(S)=%u",
4218121326Sharti				    seq1, seq2, sscop->vt_s));
4219121326Sharti				goto err_H;
4220121326Sharti			}
4221121326Sharti
4222121326Sharti			do {
4223121326Sharti				/*
4224121326Sharti				 * The receiver requests the re-transmission
4225121326Sharti				 * of some message, but has acknowledged it
4226121326Sharti				 * already in an earlier STAT (it isn't in the
4227121326Sharti				 * transmitt buffer anymore).
4228121326Sharti				 */
4229121326Sharti				if((m = QFIND(&sscop->xbuf, seq1)) == NULL) {
4230121326Sharti					VERBERR(sscop, SSCOP_DBG_ERR,
4231121326Sharti					    (sscop, sscop->aarg, "STAT: message"
4232121326Sharti					    " %u not found in xmit buffer",
4233121326Sharti					    seq1));
4234121326Sharti					goto err_H;
4235121326Sharti				}
4236121326Sharti				if(m->poll_seqno < (u_int)nps.sscop_n
4237121326Sharti				    && (u_int)nps.sscop_n <= sscop->vt_ps)
4238121326Sharti					if(!m->rexmit) {
4239121326Sharti						m->rexmit = 1;
4240121326Sharti						sscop->rxq++;
4241121326Sharti						cnt++;
4242121326Sharti						sscop_signal(sscop, SIG_PDU_Q, msg);
4243121326Sharti					}
4244121326Sharti			} while(++seq1 < seq2);
4245121326Sharti
4246121326Sharti			if(len == 0)
4247121326Sharti				break;
4248121326Sharti
4249121326Sharti			seq2 = MBUF_GET32(msg->m);
4250121326Sharti			len--;
4251121326Sharti
4252121326Sharti			if(seq1 >= seq2 || seq2 > sscop->vt_s) {
4253121326Sharti				VERBERR(sscop, SSCOP_DBG_ERR, (sscop,
4254121326Sharti				    sscop->aarg, "STAT: seq1 >= seq2 or "
4255121326Sharti				    "seq2 > VT(S): seq1=%u seq2=%u VT(S)=%u",
4256121326Sharti				    seq1, seq2, sscop->vt_s));
4257121326Sharti				goto err_H;
4258121326Sharti			}
4259121326Sharti
4260121326Sharti			/* OK now the sucessful transmitted messages. Note, that
4261121326Sharti			 * some messages may already be out of the buffer because
4262121326Sharti			 * of earlier STATS */
4263121326Sharti			do {
4264121326Sharti				if(sscop->clear_buffers) {
4265121326Sharti					if((m = QFIND(&sscop->xbuf, seq1)) != NULL) {
4266121326Sharti						MSGQ_REMOVE(&sscop->xbuf, m);
4267121326Sharti						SSCOP_MSG_FREE(m);
4268121326Sharti					}
4269121326Sharti				}
4270121326Sharti			} while(++seq1 != seq2);
4271121326Sharti
4272121326Sharti			if(len == 0)
4273121326Sharti				break;
4274121326Sharti		}
4275121326Sharti		MAAL_ERROR(sscop, 'V', cnt);
4276121326Sharti	}
4277121326Sharti	SSCOP_MSG_FREE(msg);
4278121326Sharti
4279121326Sharti	/* label L: */
4280121326Sharti	if(sscop->vt_s >= sscop->vt_ms) {
4281121326Sharti		/*
4282121326Sharti		 * The receiver has closed the window: report to management
4283121326Sharti		 */
4284121326Sharti		if(sscop->credit) {
4285121326Sharti			sscop->credit = 0;
4286121326Sharti			MAAL_ERROR(sscop, 'W', 0);
4287121326Sharti		}
4288121326Sharti	} else if(!sscop->credit) {
4289121326Sharti		/*
4290121326Sharti		 * The window was forcefully closed above, but
4291121326Sharti		 * now re-opened. Report to management.
4292121326Sharti		 */
4293121326Sharti		sscop->credit = 1;
4294121326Sharti		MAAL_ERROR(sscop, 'X', 0);
4295121326Sharti	}
4296121326Sharti
4297121326Sharti	if(TIMER_ISACT(sscop, poll)) {
4298121326Sharti		TIMER_RESTART(sscop, nr);
4299121326Sharti	} else if(!TIMER_ISACT(sscop, idle)) {
4300121326Sharti		TIMER_STOP(sscop, ka);
4301121326Sharti		TIMER_STOP(sscop, nr);
4302121326Sharti		TIMER_RESTART(sscop, idle);
4303121326Sharti	}
4304121326Sharti}
4305121326Sharti
4306121326Sharti/*
4307121326Sharti * P. 73: any state & UDATA_REQUEST
4308121326Sharti *	arg is pdu (queued)
4309121326Sharti */
4310121326Shartistatic void
4311121326Shartisscop_udata_req(struct sscop *sscop, struct sscop_msg *msg)
4312121326Sharti{
4313121326Sharti	MSGQ_APPEND(&sscop->uxq, msg);
4314121326Sharti	sscop_signal(sscop, SIG_UPDU_Q, msg);
4315121326Sharti}
4316121326Sharti
4317121326Sharti/*
4318121326Sharti * P. 73: any state & MDATA_REQUEST
4319121326Sharti *	arg is pdu (queued)
4320121326Sharti */
4321121326Shartistatic void
4322121326Shartisscop_mdata_req(struct sscop *sscop, struct sscop_msg *msg)
4323121326Sharti{
4324121326Sharti	MSGQ_APPEND(&sscop->mxq, msg);
4325121326Sharti	sscop_signal(sscop, SIG_MPDU_Q, msg);
4326121326Sharti}
4327121326Sharti
4328121326Sharti/*
4329121326Sharti * P. 74: any state & UDATA queued
4330121326Sharti *	no arg.
4331121326Sharti */
4332121326Shartistatic void
4333121326Shartisscop_upduq(struct sscop *sscop, struct sscop_msg *unused __unused)
4334121326Sharti{
4335121326Sharti	struct sscop_msg *msg;
4336121326Sharti
4337121326Sharti	if(sscop->ll_busy)
4338121326Sharti		return;
4339121326Sharti	while((msg = MSGQ_GET(&sscop->uxq)) != NULL) {
4340121326Sharti		send_ud(sscop, msg->m);
4341121326Sharti		msg->m = NULL;
4342121326Sharti		SSCOP_MSG_FREE(msg);
4343121326Sharti	}
4344121326Sharti}
4345121326Sharti
4346121326Sharti/*
4347121326Sharti * P. 74: any state & MDATA queued
4348121326Sharti *	no arg.
4349121326Sharti */
4350121326Shartistatic void
4351121326Shartisscop_mpduq(struct sscop *sscop, struct sscop_msg *unused __unused)
4352121326Sharti{
4353121326Sharti	struct sscop_msg *msg;
4354121326Sharti
4355121326Sharti	if(sscop->ll_busy)
4356121326Sharti		return;
4357121326Sharti	while((msg = MSGQ_GET(&sscop->mxq)) != NULL) {
4358121326Sharti		send_md(sscop, msg->m);
4359121326Sharti		msg->m = NULL;
4360121326Sharti		SSCOP_MSG_FREE(msg);
4361121326Sharti	}
4362121326Sharti}
4363121326Sharti
4364121326Sharti/*
4365121326Sharti * p 73: MD PDU
4366121326Sharti *	arg is PDU
4367121326Sharti */
4368121326Shartistatic void
4369121326Shartisscop_md(struct sscop *sscop, struct sscop_msg *msg)
4370121326Sharti{
4371121326Sharti	union pdu pdu;
4372121326Sharti
4373121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
4374121326Sharti
4375121326Sharti	MBUF_UNPAD(msg->m, pdu.sscop_pl);
4376121326Sharti
4377121326Sharti	MAAL_DATA(sscop, msg->m);
4378121326Sharti	msg->m = NULL;
4379121326Sharti	SSCOP_MSG_FREE(msg);
4380121326Sharti}
4381121326Sharti
4382121326Sharti/*
4383121326Sharti * p 73: UD PDU
4384121326Sharti *	arg is PDU
4385121326Sharti */
4386121326Shartistatic void
4387121326Shartisscop_ud(struct sscop *sscop, struct sscop_msg *msg)
4388121326Sharti{
4389121326Sharti	union pdu pdu;
4390121326Sharti
4391121326Sharti	pdu.sscop_null = MBUF_STRIP32(msg->m);
4392121326Sharti
4393121326Sharti	MBUF_UNPAD(msg->m, pdu.sscop_pl);
4394121326Sharti
4395121326Sharti	AAL_DATA(sscop, SSCOP_UDATA_indication, msg->m, 0);
4396121326Sharti	msg->m = NULL;
4397121326Sharti	SSCOP_MSG_FREE(msg);
4398121326Sharti}
4399121326Sharti
4400121326Sharti
4401121326Sharti/*
4402121326Sharti * p 33: IDLE & RETRIEVE
4403121326Sharti * p 39: IN_PEND & RETRIEVE
4404121326Sharti * p 42: OUT_DIS_PEND & RETRIEVE
4405121326Sharti * p 48: IN_RESYNC_PEND & RETRIEVE
4406121326Sharti * p 53: REC_PEND & RETRIEVE
4407121326Sharti * p 58: IN_REC_PEND & RETRIEVE
4408121326Sharti */
4409121326Shartistatic void
4410121326Shartisscop_retrieve(struct sscop *sscop, struct sscop_msg *msg)
4411121326Sharti{
4412121326Sharti	m_data_retrieval(sscop, msg->rexmit);
4413121326Sharti	SSCOP_MSG_FREE(msg);
4414121326Sharti}
4415121326Sharti
4416121326Sharti/************************************************************/
4417121326Sharti/*
4418121326Sharti * GENERAL EVENT HANDLING
4419121326Sharti */
4420121326Sharti
4421121326Sharti/*
4422121326Sharti * State/event matrix.
4423121326Sharti *
4424121326Sharti * Entries marked with Z are not specified in Q.2110, but are added for
4425121326Sharti * the sake of stability.
4426121326Sharti */
4427121326Shartistatic struct {
4428121326Sharti	void	(*func)(struct sscop *, struct sscop_msg *);
4429121326Sharti	int	(*cond)(struct sscop *);
4430121326Sharti} state_matrix[SSCOP_NSTATES][SIG_NUM] = {
4431121326Sharti	/* SSCOP_IDLE */ {
4432121326Sharti		/* SIG_BGN */		{ sscop_idle_bgn, NULL },
4433121326Sharti		/* SIG_BGAK */		{ sscop_idle_bgak, NULL },
4434121326Sharti		/* SIG_END */		{ sscop_idle_end, NULL },
4435121326Sharti		/* SIG_ENDAK */		{ sscop_ignore_pdu, NULL },
4436121326Sharti		/* SIG_RS */		{ sscop_idle_rs, NULL },
4437121326Sharti		/* SIG_RSAK */		{ sscop_idle_rsak, NULL },
4438121326Sharti		/* SIG_BGREJ */		{ sscop_idle_bgrej, NULL },
4439121326Sharti		/* SIG_SD */		{ sscop_idle_sd, NULL },
4440121326Sharti		/* SIG_ER */		{ sscop_idle_er, NULL },
4441121326Sharti		/* SIG_POLL */		{ sscop_idle_poll, NULL },
4442121326Sharti		/* SIG_STAT */		{ sscop_idle_stat, NULL },
4443121326Sharti		/* SIG_USTAT */		{ sscop_idle_ustat, NULL },
4444121326Sharti		/* SIG_UD */		{ sscop_ud, NULL },
4445121326Sharti		/* SIG_MD */		{ sscop_md, NULL },
4446121326Sharti		/* SIG_ERAK */		{ sscop_idle_erak, NULL },
4447121326Sharti		/* SIG_T_CC */		{ NULL, NULL },
4448121326Sharti		/* SIG_T_POLL */	{ NULL, NULL },
4449121326Sharti		/* SIG_T_KA */		{ NULL, NULL },
4450121326Sharti		/* SIG_T_NR */		{ NULL, NULL },
4451121326Sharti		/* SIG_T_IDLE */	{ NULL, NULL },
4452121326Sharti		/* SIG_PDU_Q */		{ sscop_flush_pduq, NULL },
4453121326Sharti		/* SIG_USER_DATA */	{ NULL, NULL },
4454121326Sharti		/* SIG_ESTAB_REQ */	{ sscop_idle_establish_req, NULL },
4455121326Sharti		/* SIG_ESTAB_RESP */	{ NULL, NULL },
4456121326Sharti		/* SIG_RELEASE_REQ */	{ NULL, NULL },
4457121326Sharti		/* SIG_RECOVER */	{ NULL, NULL },
4458121326Sharti		/* SIG_SYNC_REQ */	{ NULL, NULL },
4459121326Sharti		/* SIG_SYNC_RESP */	{ NULL, NULL },
4460121326Sharti		/* SIG_UDATA */		{ sscop_udata_req, NULL },
4461121326Sharti		/* SIG_MDATA */		{ sscop_mdata_req, NULL },
4462121326Sharti		/* SIG_UPDU_Q */	{ sscop_upduq, NULL },
4463121326Sharti		/* SIG_MPDU_Q */	{ sscop_mpduq, NULL },
4464121326Sharti		/* SIG_RETRIEVE */	{ sscop_retrieve, NULL },
4465121326Sharti	},
4466121326Sharti	/* SSCOP_OUT_PEND */ {
4467121326Sharti		/* SIG_BGN */		{ sscop_outpend_bgn, NULL },
4468121326Sharti		/* SIG_BGAK */		{ sscop_outpend_bgak, NULL },
4469121326Sharti		/* SIG_END */		{ sscop_ignore_pdu, NULL },
4470121326Sharti		/* SIG_ENDAK */		{ sscop_ignore_pdu, NULL },
4471121326Sharti		/* SIG_RS */		{ sscop_ignore_pdu, NULL },
4472121326Sharti		/* SIG_RSAK */		{ sscop_ignore_pdu, NULL },
4473121326Sharti		/* SIG_BGREJ */		{ sscop_outpend_bgrej, NULL },
4474121326Sharti		/* SIG_SD */		{ sscop_ignore_pdu, NULL },
4475121326Sharti		/* SIG_ER */		{ sscop_ignore_pdu, NULL },
4476121326Sharti		/* SIG_POLL */		{ sscop_ignore_pdu, NULL },
4477121326Sharti		/* SIG_STAT */		{ sscop_ignore_pdu, NULL },
4478121326Sharti		/* SIG_USTAT */		{ sscop_ignore_pdu, NULL },
4479121326Sharti		/* SIG_UD */		{ sscop_ud, NULL },
4480121326Sharti		/* SIG_MD */		{ sscop_md, NULL },
4481121326Sharti		/* SIG_ERAK */		{ sscop_ignore_pdu, NULL },
4482121326Sharti		/* SIG_T_CC */		{ sscop_outpend_tcc, NULL },
4483121326Sharti		/* SIG_T_POLL */	{ NULL, NULL },
4484121326Sharti		/* SIG_T_KA */		{ NULL, NULL },
4485121326Sharti		/* SIG_T_NR */		{ NULL, NULL },
4486121326Sharti		/* SIG_T_IDLE */	{ NULL, NULL },
4487121326Sharti		/* SIG_PDU_Q */		{ sscop_flush_pduq, NULL },
4488121326Sharti		/* SIG_USER_DATA */	{ NULL, NULL },
4489121326Sharti		/* SIG_ESTAB_REQ */	{ NULL, NULL },
4490121326Sharti		/* SIG_ESTAB_RESP */	{ NULL, NULL },
4491121326Sharti		/* SIG_RELEASE_REQ */	{ sscop_outpend_release_req, NULL },
4492121326Sharti		/* SIG_RECOVER */	{ NULL, NULL },
4493121326Sharti		/* SIG_SYNC_REQ */	{ NULL, NULL },
4494121326Sharti		/* SIG_SYNC_RESP */	{ NULL, NULL },
4495121326Sharti		/* SIG_UDATA */		{ sscop_udata_req, NULL },
4496121326Sharti		/* SIG_MDATA */		{ sscop_mdata_req, NULL },
4497121326Sharti		/* SIG_UPDU_Q */	{ sscop_upduq, NULL },
4498121326Sharti		/* SIG_MPDU_Q */	{ sscop_mpduq, NULL },
4499121326Sharti		/* SIG_RETRIEVE */	{ NULL, NULL },
4500121326Sharti	},
4501121326Sharti	/* SSCOP_IN_PEND */ {
4502121326Sharti		/* SIG_BGN */		{ sscop_inpend_bgn, NULL },
4503121326Sharti		/* SIG_BGAK */		{ sscop_inpend_bgak, NULL },
4504121326Sharti		/* SIG_END */		{ sscop_inpend_end, NULL },
4505121326Sharti		/* SIG_ENDAK */		{ sscop_inpend_endak, NULL },
4506121326Sharti		/* SIG_RS */		{ sscop_inpend_rs, NULL },
4507121326Sharti		/* SIG_RSAK */		{ sscop_inpend_rsak, NULL },
4508121326Sharti		/* SIG_BGREJ */		{ sscop_inpend_bgrej, NULL },
4509121326Sharti		/* SIG_SD */		{ sscop_inpend_sd, NULL },
4510121326Sharti		/* SIG_ER */		{ sscop_inpend_er, NULL },
4511121326Sharti		/* SIG_POLL */		{ sscop_inpend_poll, NULL },
4512121326Sharti		/* SIG_STAT */		{ sscop_inpend_stat, NULL },
4513121326Sharti		/* SIG_USTAT */		{ sscop_inpend_ustat, NULL },
4514121326Sharti		/* SIG_UD */		{ sscop_ud, NULL },
4515121326Sharti		/* SIG_MD */		{ sscop_md, NULL },
4516121326Sharti		/* SIG_ERAK */		{ sscop_inpend_erak, NULL },
4517121326Sharti		/* SIG_T_CC */		{ NULL, NULL },
4518121326Sharti		/* SIG_T_POLL */	{ NULL, NULL },
4519121326Sharti		/* SIG_T_KA */		{ NULL, NULL },
4520121326Sharti		/* SIG_T_NR */		{ NULL, NULL },
4521121326Sharti		/* SIG_T_IDLE */	{ NULL, NULL },
4522121326Sharti		/* SIG_PDU_Q */		{ sscop_flush_pduq, NULL },
4523121326Sharti		/* SIG_USER_DATA */	{ NULL, NULL },
4524121326Sharti		/* SIG_ESTAB_REQ */	{ NULL, NULL },
4525121326Sharti		/* SIG_ESTAB_RESP */	{ sscop_inpend_establish_resp, NULL },
4526121326Sharti		/* SIG_RELEASE_REQ */	{ sscop_inpend_release_req, NULL },
4527121326Sharti		/* SIG_RECOVER */	{ NULL, NULL },
4528121326Sharti		/* SIG_SYNC_REQ */	{ NULL, NULL },
4529121326Sharti		/* SIG_SYNC_RESP */	{ NULL, NULL },
4530121326Sharti		/* SIG_UDATA */		{ sscop_udata_req, NULL },
4531121326Sharti		/* SIG_MDATA */		{ sscop_mdata_req, NULL },
4532121326Sharti		/* SIG_UPDU_Q */	{ sscop_upduq, NULL },
4533121326Sharti		/* SIG_MPDU_Q */	{ sscop_mpduq, NULL },
4534121326Sharti		/* SIG_RETRIEVE */	{ sscop_retrieve, NULL },
4535121326Sharti	},
4536121326Sharti	/* SSCOP_OUT_DIS_PEND */ {
4537121326Sharti		/* SIG_BGN */		{ sscop_outdis_bgn, NULL },
4538121326Sharti		/* SIG_BGAK */		{ sscop_ignore_pdu, NULL },
4539121326Sharti		/* SIG_END */		{ sscop_outdis_end, NULL },
4540121326Sharti		/* SIG_ENDAK */		{ sscop_outdis_endak, NULL },
4541121326Sharti		/* SIG_RS */		{ sscop_ignore_pdu, NULL },
4542121326Sharti		/* SIG_RSAK */		{ sscop_ignore_pdu, NULL },
4543121326Sharti		/* SIG_BGREJ */		{ sscop_outdis_endak, NULL },
4544121326Sharti		/* SIG_SD */		{ sscop_ignore_pdu, NULL },
4545121326Sharti		/* SIG_ER */		{ sscop_ignore_pdu, NULL },
4546121326Sharti		/* SIG_POLL */		{ sscop_ignore_pdu, NULL },
4547121326Sharti		/* SIG_STAT */		{ sscop_ignore_pdu, NULL },
4548121326Sharti		/* SIG_USTAT */		{ sscop_ignore_pdu, NULL },
4549121326Sharti		/* SIG_UD */		{ sscop_ud, NULL },
4550121326Sharti		/* SIG_MD */		{ sscop_md, NULL },
4551121326Sharti		/* SIG_ERAK */		{ sscop_ignore_pdu, NULL },
4552121326Sharti		/* SIG_T_CC */		{ sscop_outdis_cc, NULL },
4553121326Sharti		/* SIG_T_POLL */	{ NULL, NULL },
4554121326Sharti		/* SIG_T_KA */		{ NULL, NULL },
4555121326Sharti		/* SIG_T_NR */		{ NULL, NULL },
4556121326Sharti		/* SIG_T_IDLE */	{ NULL, NULL },
4557121326Sharti		/* SIG_PDU_Q */		{ sscop_flush_pduq, NULL },
4558121326Sharti		/* SIG_USER_DATA */	{ NULL, NULL },
4559121326Sharti		/* SIG_ESTAB_REQ */	{ sscop_outdis_establish_req, NULL },
4560121326Sharti		/* SIG_ESTAB_RESP */	{ NULL, NULL },
4561121326Sharti		/* SIG_RELEASE_REQ */	{ NULL, NULL },
4562121326Sharti		/* SIG_RECOVER */	{ NULL, NULL },
4563121326Sharti		/* SIG_SYNC_REQ */	{ NULL, NULL },
4564121326Sharti		/* SIG_SYNC_RESP */	{ NULL, NULL },
4565121326Sharti		/* SIG_UDATA */		{ sscop_udata_req, NULL },
4566121326Sharti		/* SIG_MDATA */		{ sscop_mdata_req, NULL },
4567121326Sharti		/* SIG_UPDU_Q */	{ sscop_upduq, NULL },
4568121326Sharti		/* SIG_MPDU_Q */	{ sscop_mpduq, NULL },
4569121326Sharti		/* SIG_RETRIEVE */	{ sscop_retrieve, NULL },
4570121326Sharti	},
4571121326Sharti	/* SSCOP_OUT_RESYNC_PEND */ {
4572121326Sharti		/* SIG_BGN */		{ sscop_outsync_bgn, NULL },
4573121326Sharti		/* SIG_BGAK */		{ sscop_ignore_pdu, NULL },
4574121326Sharti		/* SIG_END */		{ sscop_outsync_end, NULL },
4575121326Sharti		/* SIG_ENDAK */		{ sscop_outsync_endak, NULL },
4576121326Sharti		/* SIG_RS */		{ sscop_outsync_rs, NULL },
4577121326Sharti		/* SIG_RSAK */		{ sscop_outsync_rsak, NULL },
4578121326Sharti		/* SIG_BGREJ */		{ sscop_outsync_bgrej, NULL },
4579121326Sharti		/* SIG_SD */		{ sscop_ignore_pdu, NULL },
4580121326Sharti		/* SIG_ER */		{ sscop_ignore_pdu, NULL },
4581121326Sharti		/* SIG_POLL */		{ sscop_ignore_pdu, NULL },
4582121326Sharti		/* SIG_STAT */		{ sscop_ignore_pdu, NULL },
4583121326Sharti		/* SIG_USTAT */		{ sscop_ignore_pdu, NULL },
4584121326Sharti		/* SIG_UD */		{ sscop_ud, NULL },
4585121326Sharti		/* SIG_MD */		{ sscop_md, NULL },
4586121326Sharti		/* SIG_ERAK */		{ sscop_ignore_pdu, NULL },
4587121326Sharti		/* SIG_T_CC */		{ sscop_outsync_cc, NULL },
4588121326Sharti		/* SIG_T_POLL */	{ NULL, NULL },
4589121326Sharti		/* SIG_T_KA */		{ NULL, NULL },
4590121326Sharti		/* SIG_T_NR */		{ NULL, NULL },
4591121326Sharti		/* SIG_T_IDLE */	{ NULL, NULL },
4592121326Sharti		/* SIG_PDU_Q */		{ sscop_flush_pduq, NULL },
4593121326Sharti		/* SIG_USER_DATA */	{ NULL, NULL },
4594121326Sharti		/* SIG_ESTAB_REQ */	{ NULL, NULL },
4595121326Sharti		/* SIG_ESTAB_RESP */	{ NULL, NULL },
4596121326Sharti		/* SIG_RELEASE_REQ */	{ sscop_outsync_release_req, NULL },
4597121326Sharti		/* SIG_RECOVER */	{ NULL, NULL },
4598121326Sharti		/* SIG_SYNC_REQ */	{ NULL, NULL },
4599121326Sharti		/* SIG_SYNC_RESP */	{ NULL, NULL },
4600121326Sharti		/* SIG_UDATA */		{ sscop_udata_req, NULL },
4601121326Sharti		/* SIG_MDATA */		{ sscop_mdata_req, NULL },
4602121326Sharti		/* SIG_UPDU_Q */	{ sscop_upduq, NULL },
4603121326Sharti		/* SIG_MPDU_Q */	{ sscop_mpduq, NULL },
4604121326Sharti		/* SIG_RETRIEVE */	{ NULL, NULL },
4605121326Sharti	},
4606121326Sharti	/* SSCOP_IN_RESYNC_PEND */ {
4607121326Sharti		/* SIG_BGN */		{ sscop_insync_bgn, NULL },
4608121326Sharti		/* SIG_BGAK */		{ sscop_insync_bgak, NULL },
4609121326Sharti		/* SIG_END */		{ sscop_insync_end, NULL },
4610121326Sharti		/* SIG_ENDAK */		{ sscop_insync_endak, NULL },
4611121326Sharti		/* SIG_RS */		{ sscop_insync_rs, NULL },
4612121326Sharti		/* SIG_RSAK */		{ sscop_insync_rsak, NULL },
4613121326Sharti		/* SIG_BGREJ */		{ sscop_insync_bgrej, NULL },
4614121326Sharti		/* SIG_SD */		{ sscop_insync_sd, NULL },
4615121326Sharti		/* SIG_ER */		{ sscop_insync_er, NULL },
4616121326Sharti		/* SIG_POLL */		{ sscop_insync_poll, NULL },
4617121326Sharti		/* SIG_STAT */		{ sscop_insync_stat, NULL },
4618121326Sharti		/* SIG_USTAT */		{ sscop_insync_ustat, NULL },
4619121326Sharti		/* SIG_UD */		{ sscop_ud, NULL },
4620121326Sharti		/* SIG_MD */		{ sscop_md, NULL },
4621121326Sharti		/* SIG_ERAK */		{ sscop_insync_erak, NULL },
4622121326Sharti		/* SIG_T_CC */		{ NULL, NULL },
4623121326Sharti		/* SIG_T_POLL */	{ NULL, NULL },
4624121326Sharti		/* SIG_T_KA */		{ NULL, NULL },
4625121326Sharti		/* SIG_T_NR */		{ NULL, NULL },
4626121326Sharti		/* SIG_T_IDLE */	{ NULL, NULL },
4627121326Sharti		/* SIG_PDU_Q */		{ sscop_flush_pduq, NULL },
4628121326Sharti		/* SIG_USER_DATA */	{ NULL, NULL },
4629121326Sharti		/* SIG_ESTAB_REQ */	{ NULL, NULL },
4630121326Sharti		/* SIG_ESTAB_RESP */	{ NULL, NULL },
4631121326Sharti		/* SIG_RELEASE_REQ */	{ sscop_insync_release_req, NULL },
4632121326Sharti		/* SIG_RECOVER */	{ NULL, NULL },
4633121326Sharti		/* SIG_SYNC_REQ */	{ NULL, NULL },
4634121326Sharti		/* SIG_SYNC_RESP */	{ sscop_insync_sync_resp, NULL },
4635121326Sharti		/* SIG_UDATA */		{ sscop_udata_req, NULL },
4636121326Sharti		/* SIG_MDATA */		{ sscop_mdata_req, NULL },
4637121326Sharti		/* SIG_UPDU_Q */	{ sscop_upduq, NULL },
4638121326Sharti		/* SIG_MPDU_Q */	{ sscop_mpduq, NULL },
4639121326Sharti		/* SIG_RETRIEVE */	{ sscop_retrieve, NULL },
4640121326Sharti	},
4641121326Sharti	/* SSCOP_OUT_REC_PEND */ {
4642121326Sharti		/* SIG_BGN */		{ sscop_outrec_bgn, NULL },
4643121326Sharti		/* SIG_BGAK */		{ sscop_outrec_bgak, NULL },
4644121326Sharti		/* SIG_END */		{ sscop_outrec_end, NULL },
4645121326Sharti		/* SIG_ENDAK */		{ sscop_outrec_endak, NULL },
4646121326Sharti		/* SIG_RS */		{ sscop_outrec_rs, NULL },
4647121326Sharti		/* SIG_RSAK */		{ sscop_outrec_rsak, NULL },
4648121326Sharti		/* SIG_BGREJ */		{ sscop_outrec_bgrej, NULL },
4649121326Sharti		/* SIG_SD */		{ sscop_ignore_pdu, NULL },
4650121326Sharti		/* SIG_ER */		{ sscop_outrec_er, NULL },
4651121326Sharti		/* SIG_POLL */		{ sscop_ignore_pdu, NULL },
4652121326Sharti		/* SIG_STAT */		{ sscop_ignore_pdu, NULL },
4653121326Sharti		/* SIG_USTAT */		{ sscop_ignore_pdu, NULL },
4654121326Sharti		/* SIG_UD */		{ sscop_ud, NULL },
4655121326Sharti		/* SIG_MD */		{ sscop_md, NULL },
4656121326Sharti		/* SIG_ERAK */		{ sscop_outrec_erak, NULL },
4657121326Sharti		/* SIG_T_CC */		{ sscop_outrec_cc, NULL },
4658121326Sharti		/* SIG_T_POLL */	{ NULL, NULL },
4659121326Sharti		/* SIG_T_KA */		{ NULL, NULL },
4660121326Sharti		/* SIG_T_NR */		{ NULL, NULL },
4661121326Sharti		/* SIG_T_IDLE */	{ NULL, NULL },
4662121326Sharti		/* SIG_PDU_Q */		{ sscop_outrec_pduq, NULL },
4663121326Sharti		/* SIG_USER_DATA */	{ sscop_outrec_userdata, NULL },
4664121326Sharti		/* SIG_ESTAB_REQ */	{ NULL, NULL },
4665121326Sharti		/* SIG_ESTAB_RESP */	{ NULL, NULL },
4666121326Sharti		/* SIG_RELEASE_REQ */	{ sscop_outrec_release_req, NULL },
4667121326Sharti		/* SIG_RECOVER */	{ NULL, NULL },
4668121326Sharti		/* SIG_SYNC_REQ */	{ sscop_outrec_sync_req, NULL },
4669121326Sharti		/* SIG_SYNC_RESP */	{ NULL, NULL },
4670121326Sharti		/* SIG_UDATA */		{ sscop_udata_req, NULL },
4671121326Sharti		/* SIG_MDATA */		{ sscop_mdata_req, NULL },
4672121326Sharti		/* SIG_UPDU_Q */	{ sscop_upduq, NULL },
4673121326Sharti		/* SIG_MPDU_Q */	{ sscop_mpduq, NULL },
4674121326Sharti		/* SIG_RETRIEVE */	{ NULL, NULL },
4675121326Sharti	},
4676121326Sharti	/* SSCOP_REC_PEND */ {
4677121326Sharti		/* SIG_BGN */		{ sscop_rec_bgn, NULL },
4678121326Sharti		/* SIG_BGAK */		{ sscop_rec_bgak, NULL },
4679121326Sharti		/* SIG_END */		{ sscop_rec_end, NULL },
4680121326Sharti		/* SIG_ENDAK */		{ sscop_rec_endak, NULL },
4681121326Sharti		/* SIG_RS */		{ sscop_rec_rs, NULL },
4682121326Sharti		/* SIG_RSAK */		{ sscop_rec_rsak, NULL },
4683121326Sharti		/* SIG_BGREJ */		{ sscop_rec_bgrej, NULL },
4684121326Sharti		/* SIG_SD */		{ sscop_ignore_pdu, NULL },
4685121326Sharti		/* SIG_ER */		{ sscop_rec_er, NULL },
4686121326Sharti		/* SIG_POLL */		{ sscop_ignore_pdu, NULL },
4687121326Sharti		/* SIG_STAT */		{ sscop_rec_stat, NULL },
4688121326Sharti		/* SIG_USTAT */		{ sscop_rec_ustat, NULL },
4689121326Sharti		/* SIG_UD */		{ sscop_ud, NULL },
4690121326Sharti		/* SIG_MD */		{ sscop_md, NULL },
4691121326Sharti		/* SIG_ERAK */		{ sscop_ignore_pdu, NULL },
4692121326Sharti		/* SIG_T_CC */		{ NULL, NULL },
4693121326Sharti		/* SIG_T_POLL */	{ NULL, NULL },
4694121326Sharti		/* SIG_T_KA */		{ NULL, NULL },
4695121326Sharti		/* SIG_T_NR */		{ NULL, NULL },
4696121326Sharti		/* SIG_T_IDLE */	{ NULL, NULL },
4697121326Sharti		/* SIG_PDU_Q */		{ sscop_rec_pduq, NULL },
4698121326Sharti		/* SIG_USER_DATA */	{ NULL, NULL },
4699121326Sharti		/* SIG_ESTAB_REQ */	{ NULL, NULL },
4700121326Sharti		/* SIG_ESTAB_RESP */	{ NULL, NULL },
4701121326Sharti		/* SIG_RELEASE_REQ */	{ sscop_rec_release_req, NULL },
4702121326Sharti		/* SIG_RECOVER */	{ sscop_rec_recover, NULL },
4703121326Sharti		/* SIG_SYNC_REQ */	{ sscop_rec_sync_req, NULL },
4704121326Sharti		/* SIG_SYNC_RESP */	{ NULL, NULL },
4705121326Sharti		/* SIG_UDATA */		{ sscop_udata_req, NULL },
4706121326Sharti		/* SIG_MDATA */		{ sscop_mdata_req, NULL },
4707121326Sharti		/* SIG_UPDU_Q */	{ sscop_upduq, NULL },
4708121326Sharti		/* SIG_MPDU_Q */	{ sscop_mpduq, NULL },
4709121326Sharti		/* SIG_RETRIEVE */	{ sscop_retrieve, NULL },
4710121326Sharti	},
4711121326Sharti	/* SSCOP_IN_REC_PEND */ {
4712121326Sharti		/* SIG_BGN */		{ sscop_inrec_bgn, NULL },
4713121326Sharti		/* SIG_BGAK */		{ sscop_inrec_bgak, NULL },
4714121326Sharti		/* SIG_END */		{ sscop_inrec_end, NULL },
4715121326Sharti		/* SIG_ENDAK */		{ sscop_inrec_endak, NULL },
4716121326Sharti		/* SIG_RS */		{ sscop_inrec_rs, NULL },
4717121326Sharti		/* SIG_RSAK */		{ sscop_inrec_rsak, NULL },
4718121326Sharti		/* SIG_BGREJ */		{ sscop_inrec_bgrej, NULL },
4719121326Sharti		/* SIG_SD */		{ sscop_inrec_sd, NULL },
4720121326Sharti		/* SIG_ER */		{ sscop_inrec_er, NULL },
4721121326Sharti		/* SIG_POLL */		{ sscop_inrec_poll, NULL },
4722121326Sharti		/* SIG_STAT */		{ sscop_inrec_stat, NULL },
4723121326Sharti		/* SIG_USTAT */		{ sscop_inrec_ustat, NULL },
4724121326Sharti		/* SIG_UD */		{ sscop_ud, NULL },
4725121326Sharti		/* SIG_MD */		{ sscop_md, NULL },
4726121326Sharti		/* SIG_ERAK */		{ sscop_inrec_erak, NULL },
4727121326Sharti		/* SIG_T_CC */		{ NULL, NULL },
4728121326Sharti		/* SIG_T_POLL */	{ NULL, NULL },
4729121326Sharti		/* SIG_T_KA */		{ NULL, NULL },
4730121326Sharti		/* SIG_T_NR */		{ NULL, NULL },
4731121326Sharti		/* SIG_T_IDLE */	{ NULL, NULL },
4732121326Sharti		/* SIG_PDU_Q */		{ sscop_inrec_pduq, NULL },
4733121326Sharti		/* SIG_USER_DATA */	{ NULL, NULL },
4734121326Sharti		/* SIG_ESTAB_REQ */	{ NULL, NULL },
4735121326Sharti		/* SIG_ESTAB_RESP */	{ NULL, NULL },
4736121326Sharti		/* SIG_RELEASE_REQ */	{ sscop_inrec_release_req, NULL },
4737121326Sharti		/* SIG_RECOVER */	{ sscop_inrec_recover, NULL },
4738121326Sharti		/* SIG_SYNC_REQ */	{ sscop_inrec_sync_req, NULL },
4739121326Sharti		/* SIG_SYNC_RESP */	{ NULL, NULL },
4740121326Sharti		/* SIG_UDATA */		{ sscop_udata_req, NULL },
4741121326Sharti		/* SIG_MDATA */		{ sscop_mdata_req, NULL },
4742121326Sharti		/* SIG_UPDU_Q */	{ sscop_upduq, NULL },
4743121326Sharti		/* SIG_MPDU_Q */	{ sscop_mpduq, NULL },
4744121326Sharti		/* SIG_RETRIEVE */	{ sscop_retrieve, NULL },
4745121326Sharti	},
4746121326Sharti	/* SSCOP_READY */ {
4747121326Sharti		/* SIG_BGN */		{ sscop_ready_bgn, NULL },
4748121326Sharti		/* SIG_BGAK */		{ sscop_ignore_pdu, NULL },
4749121326Sharti		/* SIG_END */		{ sscop_ready_end, NULL },
4750121326Sharti		/* SIG_ENDAK */		{ sscop_ready_endak, NULL },
4751121326Sharti		/* SIG_RS */		{ sscop_ready_rs, NULL },
4752121326Sharti		/* SIG_RSAK */		{ sscop_ignore_pdu, NULL },
4753121326Sharti		/* SIG_BGREJ */		{ sscop_ready_bgrej, NULL },
4754121326Sharti		/* SIG_SD */		{ sscop_ready_sd, NULL },
4755121326Sharti		/* SIG_ER */		{ sscop_ready_er, NULL },
4756121326Sharti		/* SIG_POLL */		{ sscop_ready_poll, NULL },
4757121326Sharti		/* SIG_STAT */		{ sscop_ready_stat, NULL },
4758121326Sharti		/* SIG_USTAT */		{ sscop_ready_ustat, NULL },
4759121326Sharti		/* SIG_UD */		{ sscop_ud, NULL },
4760121326Sharti		/* SIG_MD */		{ sscop_md, NULL },
4761121326Sharti		/* SIG_ERAK */		{ sscop_ignore_pdu, NULL },
4762121326Sharti		/* SIG_T_CC */		{ NULL, NULL },
4763121326Sharti		/* SIG_T_POLL */	{ sscop_ready_tpoll, NULL },
4764121326Sharti		/* SIG_T_KA */		{ sscop_ready_tka, NULL },
4765121326Sharti		/* SIG_T_NR */		{ sscop_ready_nr, NULL },
4766121326Sharti		/* SIG_T_IDLE */	{ sscop_ready_tidle, NULL },
4767121326Sharti		/* SIG_PDU_Q */		{ sscop_ready_pduq, c_ready_pduq },
4768121326Sharti		/* SIG_USER_DATA */	{ sscop_ready_userdata, NULL },
4769121326Sharti		/* SIG_ESTAB_REQ */	{ NULL, NULL },
4770121326Sharti		/* SIG_ESTAB_RESP */	{ NULL, NULL },
4771121326Sharti		/* SIG_RELEASE_REQ */	{ sscop_ready_release_req, NULL },
4772121326Sharti		/* SIG_RECOVER */	{ NULL, NULL },
4773121326Sharti		/* SIG_SYNC_REQ */	{ sscop_ready_sync_req, NULL },
4774121326Sharti		/* SIG_SYNC_RESP */	{ NULL, NULL },
4775121326Sharti		/* SIG_UDATA */		{ sscop_udata_req, NULL },
4776121326Sharti		/* SIG_MDATA */		{ sscop_mdata_req, NULL },
4777121326Sharti		/* SIG_UPDU_Q */	{ sscop_upduq, NULL },
4778121326Sharti		/* SIG_MPDU_Q */	{ sscop_mpduq, NULL },
4779121326Sharti		/* SIG_RETRIEVE */	{ NULL, NULL },
4780121326Sharti	}
4781121326Sharti};
4782121326Sharti
4783121326Sharti/*
4784121326Sharti * Try to execute a signal. It is executed if
4785121326Sharti *   - it is illegal (in this case it is effectively ignored)
4786121326Sharti *   - it has no condition
4787121326Sharti *   - its condition is true
4788121326Sharti * If it has a condition and that is false, the function does nothing and
4789121326Sharti * returns 0.
4790121326Sharti * If the signal gets executed, the signal function is responsible to release
4791121326Sharti * the message (if any).
4792121326Sharti */
4793121326Shartistatic int
4794121326Shartisig_exec(struct sscop *sscop, u_int sig, struct sscop_msg *msg)
4795121326Sharti{
4796121326Sharti	void (*func)(struct sscop *, struct sscop_msg *);
4797121326Sharti	int (*cond)(struct sscop *);
4798121326Sharti
4799121326Sharti	func = state_matrix[sscop->state][sig].func;
4800121326Sharti	cond = state_matrix[sscop->state][sig].cond;
4801121326Sharti
4802121326Sharti	if(func == NULL) {
4803121326Sharti		VERBOSE(sscop, SSCOP_DBG_BUG, (sscop, sscop->aarg,
4804121326Sharti		    "no handler for %s in state %s - ignored",
4805121326Sharti		    events[sig], states[sscop->state]));
4806121326Sharti		SSCOP_MSG_FREE(msg);
4807121326Sharti		return 1;
4808121326Sharti	}
4809121326Sharti	if(cond == NULL || (*cond)(sscop)) {
4810121326Sharti		VERBOSE(sscop, SSCOP_DBG_EXEC, (sscop, sscop->aarg,
4811121326Sharti		    "executing %s in %s", events[sig],
4812121326Sharti		    states[sscop->state]));
4813121326Sharti		(*func)(sscop, msg);
4814121326Sharti		return 1;
4815121326Sharti	}
4816121326Sharti	VERBOSE(sscop, SSCOP_DBG_EXEC, (sscop, sscop->aarg,
4817121326Sharti	    "delaying %s in %s", events[sig],
4818121326Sharti	    states[sscop->state]));
4819121326Sharti
4820121326Sharti	return 0;
4821121326Sharti}
4822121326Sharti
4823121326Sharti/*
4824121326Sharti * Deliver a signal to the given sscop
4825121326Sharti * If it is delivered from inside a signal handler - queue it. If not,
4826121326Sharti * execute it. After execution loop through the queue and execute all
4827121326Sharti * pending signals. Signals, that cannot be executed because of entry
4828121326Sharti * conditions are skipped.
4829121326Sharti */
4830121326Shartistatic void
4831121326Shartisscop_signal(struct sscop *sscop, u_int sig, struct sscop_msg *msg)
4832121326Sharti{
4833121326Sharti	struct sscop_sig *s;
4834121326Sharti
4835121326Sharti	VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg,
4836121326Sharti	    "got signal %s in state %s%s", events[sig],
4837121326Sharti	    states[sscop->state], sscop->in_sig ? " -- queuing" : ""));
4838121326Sharti
4839121326Sharti	SIG_ALLOC(s);
4840121326Sharti	if(s == NULL) {
4841121326Sharti		FAILURE("sscop: cannot allocate signal");
4842121326Sharti		SSCOP_MSG_FREE(msg);
4843121326Sharti		return;
4844121326Sharti	}
4845121326Sharti	s->sig = sig;
4846121326Sharti	s->msg = msg;
4847121326Sharti	SIGQ_APPEND(&sscop->sigs, s);
4848121326Sharti
4849121326Sharti	if(!sscop->in_sig)
4850121326Sharti		handle_sigs(sscop);
4851121326Sharti}
4852121326Sharti
4853121326Sharti/*
4854121326Sharti * Loop through the signal queue until we can't execute any signals.
4855121326Sharti */
4856121326Shartistatic void
4857121326Shartihandle_sigs(struct sscop *sscop)
4858121326Sharti{
4859121326Sharti	struct sscop_sig *s;
4860121326Sharti	sscop_sigq_head_t dsigs, q;
4861121326Sharti	int exec;
4862121326Sharti
4863121326Sharti	sscop->in_sig++;
4864121326Sharti
4865121326Sharti	/*
4866121326Sharti	 * Copy the current signal queue to the local one and empty
4867121326Sharti	 * the signal queue. Then loop through the signals. After one
4868121326Sharti	 * pass we have a list of delayed signals because of entry
4869121326Sharti	 * conditions and a new list of signals. Merge them. Repeat until
4870121326Sharti	 * the signal queue is either empty or contains only delayed signals.
4871121326Sharti	 */
4872121326Sharti	SIGQ_INIT(&q);
4873121326Sharti	SIGQ_INIT(&dsigs);
4874121326Sharti	do {
4875121326Sharti		exec = 0;
4876121326Sharti
4877121326Sharti		/*
4878121326Sharti		 * Copy signal list and make sscop list empty
4879121326Sharti		 */
4880121326Sharti		SIGQ_MOVE(&sscop->sigs, &q);
4881121326Sharti
4882121326Sharti		/*
4883121326Sharti		 * Loop through the list
4884121326Sharti		 */
4885121326Sharti		while((s = SIGQ_GET(&q)) != NULL) {
4886121326Sharti			if(sig_exec(sscop, s->sig, s->msg)) {
4887121326Sharti				exec = 1;
4888121326Sharti				SIG_FREE(s);
4889121326Sharti			} else {
4890121326Sharti				SIGQ_APPEND(&dsigs, s);
4891121326Sharti			}
4892121326Sharti		}
4893121326Sharti
4894121326Sharti		/*
4895121326Sharti		 * Merge lists by inserting delayed signals in front of
4896121326Sharti		 * the signal list. preserving the order.
4897121326Sharti		 */
4898121326Sharti		SIGQ_PREPEND(&dsigs, &sscop->sigs);
4899121326Sharti	} while(exec);
4900121326Sharti	sscop->in_sig--;
4901121326Sharti}
4902121326Sharti
4903121326Sharti/*
4904121326Sharti * Save a signal that should be executed only if state changes.
4905121326Sharti */
4906121326Shartistatic void
4907121326Shartisscop_save_signal(struct sscop *sscop, u_int sig, struct sscop_msg *msg)
4908121326Sharti{
4909121326Sharti	struct sscop_sig *s;
4910121326Sharti
4911121326Sharti	SIG_ALLOC(s);
4912121326Sharti	if(s == NULL) {
4913121326Sharti		FAILURE("sscop: cannot allocate signal");
4914121326Sharti		SSCOP_MSG_FREE(msg);
4915121326Sharti		return;
4916121326Sharti	}
4917121326Sharti	s->sig = sig;
4918121326Sharti	s->msg = msg;
4919121326Sharti	SIGQ_APPEND(&sscop->saved_sigs, s);
4920121326Sharti}
4921121326Sharti
4922121326Sharti/*
4923121326Sharti * Set a new state. If signals are waiting for a state change - append them to
4924121326Sharti * the signal queue, so they get executed.
4925121326Sharti */
4926121326Shartistatic void
4927121326Shartisscop_set_state(struct sscop *sscop, u_int nstate)
4928121326Sharti{
4929121326Sharti	VERBOSE(sscop, SSCOP_DBG_STATE, (sscop, sscop->aarg,
4930121326Sharti	    "changing state from %s to %s",
4931121326Sharti	    states[sscop->state], states[nstate]));
4932121326Sharti
4933121326Sharti	sscop->state = nstate;
4934121326Sharti	SIGQ_MOVE(&sscop->saved_sigs, &sscop->sigs);
4935121326Sharti}
4936121326Sharti
4937121326Shartivoid
4938121326Shartisscop_setdebug(struct sscop *sscop, u_int n)
4939121326Sharti{
4940121326Sharti	sscop->debug = n;
4941121326Sharti}
4942121326Sharti
4943121326Shartiu_int
4944121326Shartisscop_getdebug(const struct sscop *sscop)
4945121326Sharti{
4946121326Sharti	return (sscop->debug);
4947121326Sharti}
4948