saal_sscop.c revision 121326
1193326Sed/* 2193326Sed * Copyright (c) 1996-2003 3193326Sed * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4193326Sed * All rights reserved. 5193326Sed * 6193326Sed * Redistribution and use in source and binary forms, with or without 7193326Sed * modification, are permitted provided that the following conditions 8193326Sed * are met: 9193326Sed * 1. Redistributions of source code must retain the above copyright 10193326Sed * notice, this list of conditions and the following disclaimer. 11193326Sed * 2. Redistributions in binary form must reproduce the above copyright 12193326Sed * notice, this list of conditions and the following disclaimer in the 13193326Sed * documentation and/or other materials provided with the distribution. 14212904Sdim * 15193326Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16193326Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17263509Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18221345Sdim * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19252723Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20207619Srdivacky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21193326Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22245431Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23221345Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24207619Srdivacky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25235633Sdim * SUCH DAMAGE. 26207619Srdivacky * 27200583Srdivacky * Author: Hartmut Brandt <harti@freebsd.org> 28193326Sed * 29252723Sdim * $Begemot: libunimsg/atm/saal/saal_sscop.c,v 1.10 2003/09/19 12:02:03 hbb Exp $ 30252723Sdim * 31263509Sdim * Core SSCOP code (ITU-T Q.2110) 32252723Sdim */ 33252723Sdim 34212904Sdim#include <netnatm/saal/sscop.h> 35252723Sdim#include <netnatm/saal/sscoppriv.h> 36252723Sdim 37212904Sdim#ifndef FAILURE 38252723Sdim#define FAILURE(S) 39252723Sdim#endif 40252723Sdim 41235633Sdim#define MKSTR(S) #S 42193326Sed 43198092Srdivackystatic const char *const sscop_sigs[] = { 44193326Sed MKSTR(SSCOP_ESTABLISH_request), 45193326Sed MKSTR(SSCOP_ESTABLISH_indication), 46193326Sed MKSTR(SSCOP_ESTABLISH_response), 47193326Sed MKSTR(SSCOP_ESTABLISH_confirm), 48193326Sed MKSTR(SSCOP_RELEASE_request), 49193326Sed MKSTR(SSCOP_RELEASE_indication), 50193326Sed MKSTR(SSCOP_RELEASE_confirm), 51193326Sed MKSTR(SSCOP_DATA_request), 52193326Sed MKSTR(SSCOP_DATA_indication), 53193326Sed MKSTR(SSCOP_UDATA_request), 54193326Sed MKSTR(SSCOP_UDATA_indication), 55193326Sed MKSTR(SSCOP_RECOVER_indication), 56193326Sed MKSTR(SSCOP_RECOVER_response), 57199990Srdivacky MKSTR(SSCOP_RESYNC_request), 58193326Sed MKSTR(SSCOP_RESYNC_indication), 59193326Sed MKSTR(SSCOP_RESYNC_response), 60193326Sed MKSTR(SSCOP_RESYNC_confirm), 61193326Sed MKSTR(SSCOP_RETRIEVE_request), 62193326Sed MKSTR(SSCOP_RETRIEVE_indication), 63198092Srdivacky MKSTR(SSCOP_RETRIEVE_COMPL_indication), 64193326Sed}; 65193326Sed 66193326Sedstatic const char *const sscop_msigs[] = { 67193326Sed MKSTR(SSCOP_MDATA_request), 68193326Sed MKSTR(SSCOP_MDATA_indication), 69235633Sdim MKSTR(SSCOP_MERROR_indication), 70252723Sdim}; 71193326Sed 72193326Sedstatic const char *const states[] = { 73193326Sed MKSTR(SSCOP_IDLE), 74193326Sed MKSTR(SSCOP_OUT_PEND), 75193326Sed MKSTR(SSCOP_IN_PEND), 76218893Sdim MKSTR(SSCOP_OUT_DIS_PEND), 77193326Sed MKSTR(SSCOP_OUT_RESYNC_PEND), 78193326Sed MKSTR(SSCOP_IN_RESYNC_PEND), 79193326Sed MKSTR(SSCOP_OUT_REC_PEND), 80193326Sed MKSTR(SSCOP_REC_PEND), 81193326Sed MKSTR(SSCOP_IN_REC_PEND), 82193326Sed MKSTR(SSCOP_READY), 83193326Sed}; 84193326Sed 85193326Sed#ifdef SSCOP_DEBUG 86193326Sedstatic const char *const events[] = { 87193326Sed MKSTR(SIG_BGN), 88193326Sed MKSTR(SIG_BGAK), 89193326Sed MKSTR(SIG_END), 90193326Sed MKSTR(SIG_ENDAK), 91193326Sed MKSTR(SIG_RS), 92193326Sed MKSTR(SIG_RSAK), 93193326Sed MKSTR(SIG_BGREJ), 94193326Sed MKSTR(SIG_SD), 95235633Sdim MKSTR(SIG_ER), 96193326Sed MKSTR(SIG_POLL), 97193326Sed MKSTR(SIG_STAT), 98193326Sed MKSTR(SIG_USTAT), 99193326Sed MKSTR(SIG_UD), 100193326Sed MKSTR(SIG_MD), 101193326Sed MKSTR(SIG_ERAK), 102218893Sdim 103235633Sdim MKSTR(SIG_T_CC), 104193326Sed MKSTR(SIG_T_POLL), 105193326Sed MKSTR(SIG_T_KA), 106193326Sed MKSTR(SIG_T_NR), 107193326Sed MKSTR(SIG_T_IDLE), 108193326Sed 109193326Sed MKSTR(SIG_PDU_Q), 110193326Sed MKSTR(SIG_USER_DATA), 111193326Sed MKSTR(SIG_ESTAB_REQ), 112193326Sed MKSTR(SIG_ESTAB_RESP), 113193326Sed MKSTR(SIG_RELEASE_REQ), 114193326Sed MKSTR(SIG_RECOVER), 115193326Sed MKSTR(SIG_SYNC_REQ), 116235633Sdim MKSTR(SIG_SYNC_RESP), 117193326Sed MKSTR(SIG_UDATA), 118193326Sed MKSTR(SIG_MDATA), 119193326Sed MKSTR(SIG_UPDU_Q), 120235633Sdim MKSTR(SIG_MPDU_Q), 121252723Sdim MKSTR(SIG_RETRIEVE), 122252723Sdim}; 123252723Sdim 124252723Sdimstatic const char *const pdus[] = { 125252723Sdim "illegale PDU type 0", /* no PDU type 0 */ 126252723Sdim MKSTR(PDU_BGN), 127252723Sdim MKSTR(PDU_BGAK), 128252723Sdim MKSTR(PDU_END), 129252723Sdim MKSTR(PDU_ENDAK), 130252723Sdim MKSTR(PDU_RS), 131252723Sdim MKSTR(PDU_RSAK), 132252723Sdim MKSTR(PDU_BGREJ), 133252723Sdim MKSTR(PDU_SD), 134252723Sdim MKSTR(PDU_ER), 135252723Sdim MKSTR(PDU_POLL), 136252723Sdim MKSTR(PDU_STAT), 137252723Sdim MKSTR(PDU_USTAT), 138235633Sdim MKSTR(PDU_UD), 139235633Sdim MKSTR(PDU_MD), 140235633Sdim MKSTR(PDU_ERAK), 141235633Sdim}; 142235633Sdim#endif 143235633Sdim 144235633SdimMEMINIT(); 145235633Sdim 146235633Sdimstatic void sscop_signal(struct sscop *, u_int, struct sscop_msg *); 147235633Sdimstatic void sscop_save_signal(struct sscop *, u_int, struct sscop_msg *); 148193326Sedstatic void handle_sigs(struct sscop *); 149193326Sedstatic void sscop_set_state(struct sscop *, u_int); 150252723Sdim 151252723Sdim/************************************************************/ 152252723Sdim 153245431Sdim 154245431Sdim/************************************************************/ 155223017Sdim/* 156223017Sdim * Queue macros 157223017Sdim */ 158223017Sdim#define SSCOP_MSG_FREE(MSG) \ 159235633Sdim do { \ 160235633Sdim if(MSG) { \ 161235633Sdim MBUF_FREE((MSG)->m); \ 162223017Sdim MSG_FREE((MSG)); \ 163223017Sdim } \ 164223017Sdim } while(0) 165223017Sdim 166245431Sdim 167223017Sdim#define QFIND(Q,RN) \ 168223017Sdim ({ \ 169223017Sdim struct sscop_msg *_msg = NULL, *_m; \ 170223017Sdim MSGQ_FOREACH(_m, (Q)) { \ 171223017Sdim if(_m->seqno == (RN)) { \ 172223017Sdim _msg = _m; \ 173223017Sdim break; \ 174223017Sdim } \ 175223017Sdim } \ 176223017Sdim _msg; \ 177223017Sdim }) 178223017Sdim 179223017Sdim#define QINSERT(Q,M) \ 180223017Sdim do { \ 181223017Sdim struct sscop_msg *_msg = NULL, *_m; \ 182223017Sdim MSGQ_FOREACH(_m, (Q)) { \ 183223017Sdim if (_m->seqno > (M)->seqno) { \ 184223017Sdim _msg = _m; \ 185223017Sdim break; \ 186223017Sdim } \ 187223017Sdim } \ 188223017Sdim if (_msg != NULL) \ 189223017Sdim MSGQ_INSERT_BEFORE(_msg, (M)); \ 190223017Sdim else \ 191223017Sdim MSGQ_APPEND((Q), (M)); \ 192223017Sdim } while (0) 193235633Sdim 194235633Sdim 195223017Sdim/* 196223017Sdim * Send an error indication to the management plane. 197223017Sdim */ 198223017Sdim#define MAAL_ERROR(S,E,C) \ 199223017Sdim do { \ 200223017Sdim VERBOSE(S, SSCOP_DBG_USIG, ((S), (S)->aarg, \ 201223017Sdim "MAA-Signal %s in state %s", \ 202223017Sdim sscop_msigs[SSCOP_MERROR_indication], states[(S)->state])); \ 203223017Sdim (S)->funcs->send_manage((S), (S)->aarg, \ 204223017Sdim SSCOP_MERROR_indication, NULL, (E), (C)); \ 205223017Sdim } while(0) 206223017Sdim 207223017Sdim#define MAAL_DATA(S,M) \ 208223017Sdim do { \ 209223017Sdim VERBOSE(S, SSCOP_DBG_USIG, ((S), (S)->aarg, \ 210223017Sdim "MAA-Signal %s in state %s", \ 211223017Sdim sscop_msigs[SSCOP_MDATA_indication], states[(S)->state])); \ 212223017Sdim (S)->funcs->send_manage((S), (S)->aarg, \ 213223017Sdim SSCOP_MDATA_indication, (M), 0, 0); \ 214223017Sdim } while(0) 215223017Sdim 216223017Sdim#define AAL_DATA(S,D,M,N) \ 217223017Sdim do { \ 218235633Sdim VERBOSE(S, SSCOP_DBG_USIG, ((S), (S)->aarg, \ 219223017Sdim "AA-Signal %s in state %s", \ 220223017Sdim sscop_sigs[D], states[(S)->state])); \ 221223017Sdim (S)->funcs->send_upper((S), (S)->aarg, (D), (M), (N)); \ 222223017Sdim } while(0) 223245431Sdim 224223017Sdim#define AAL_SIG(S,D) \ 225223017Sdim do { \ 226223017Sdim VERBOSE(S, SSCOP_DBG_USIG, ((S), (S)->aarg, \ 227223017Sdim "AA-Signal %s in state %s", \ 228223017Sdim sscop_sigs[D], states[(S)->state])); \ 229224145Sdim (S)->funcs->send_upper((S), (S)->aarg, (D), NULL, 0); \ 230224145Sdim } while(0) 231224145Sdim 232223017Sdim#ifdef SSCOP_DEBUG 233223017Sdim#define AAL_SEND(S,M) do { \ 234223017Sdim if (ISVERBOSE(S, SSCOP_DBG_PDU)) \ 235223017Sdim sscop_dump_pdu(S, "tx", (M)); \ 236223017Sdim (S)->funcs->send_lower((S), (S)->aarg, (M)); \ 237223017Sdim } while(0) 238223017Sdim#else 239223017Sdim#define AAL_SEND(S,M) (S)->funcs->send_lower((S), (S)->aarg, (M)) 240223017Sdim#endif 241223017Sdim 242223017Sdim 243223017Sdim/* 244223017Sdim * Free a save user-to-user data buffer and set the pointer to zero 245223017Sdim * to signal, that it is free. 246223017Sdim */ 247235633Sdim#define FREE_UU(F) \ 248223017Sdim do { \ 249223017Sdim if(sscop->F) { \ 250223017Sdim MBUF_FREE(sscop->F); \ 251198092Srdivacky sscop->F = NULL; \ 252212904Sdim } \ 253198092Srdivacky } while(0) 254198092Srdivacky 255198092Srdivacky#define SET_UU(F,U) \ 256198092Srdivacky do { \ 257198092Srdivacky FREE_UU(F); \ 258198092Srdivacky sscop->F = U->m; \ 259198092Srdivacky U->m = NULL; \ 260198092Srdivacky SSCOP_MSG_FREE(U); \ 261198092Srdivacky } while(0) 262198092Srdivacky 263198092Srdivacky#define AAL_UU_SIGNAL(S, SIG, M, PL, SN) \ 264198092Srdivacky do { \ 265198092Srdivacky if(MBUF_LEN((M)->m) > 0) { \ 266218893Sdim MBUF_UNPAD((M)->m,(PL)); \ 267218893Sdim AAL_DATA((S), (SIG), (M)->m, (SN)); \ 268201361Srdivacky (M)->m = NULL; \ 269201361Srdivacky } else { \ 270252723Sdim AAL_DATA((S), (SIG), NULL, (SN)); \ 271245431Sdim } \ 272201361Srdivacky SSCOP_MSG_FREE((M)); \ 273198092Srdivacky } while(0) 274201361Srdivacky 275198092Srdivacky 276252723Sdim 277218893SdimTIMER_FUNC(cc, CC) 278198092SrdivackyTIMER_FUNC(nr, NR) 279198092SrdivackyTIMER_FUNC(ka, KA) 280198092SrdivackyTIMER_FUNC(poll, POLL) 281198092SrdivackyTIMER_FUNC(idle, IDLE) 282218893Sdim 283218893Sdim/************************************************************/ 284218893Sdim/* 285218893Sdim * INSTANCE AND TYPE HANDLING. 286218893Sdim */ 287218893Sdim#ifdef SSCOP_DEBUG 288218893Sdimstatic void 289218893Sdimsscop_dump_pdu(struct sscop *sscop, const char *dir, 290218893Sdim const struct SSCOP_MBUF_T *m) 291218893Sdim{ 292218893Sdim u_int32_t v1, v2, v3, v4; 293218893Sdim u_int size = MBUF_LEN(m); 294198092Srdivacky u_int n, i; 295198092Srdivacky 296198092Srdivacky if (size < 8) 297193326Sed return; 298193326Sed 299193326Sed v1 = MBUF_TRAIL32(m, -1); 300193326Sed v2 = MBUF_TRAIL32(m, -2); 301212904Sdim 302212904Sdim switch ((v1 >> 24) & 0xf) { 303212904Sdim 304194711Sed case 0: 305198092Srdivacky return; 306212904Sdim 307194179Sed case PDU_BGN: 308194179Sed sscop->funcs->verbose(sscop, sscop->aarg, 309193326Sed "%s BGN n(mr)=%u n(sq)=%u pl=%u", 310235633Sdim dir, v1 & 0xffffff, v2 & 0xff, (v1 >> 30) & 0x3); 311193326Sed return; 312193326Sed 313193326Sed case PDU_BGAK: 314193326Sed sscop->funcs->verbose(sscop, sscop->aarg, 315193326Sed "%s BGAK n(mr)=%u pl=%u", 316193326Sed dir, v1 & 0xffffff, (v1 >> 30) & 0x3); 317218893Sdim return; 318218893Sdim 319218893Sdim case PDU_END: 320218893Sdim sscop->funcs->verbose(sscop, sscop->aarg, 321218893Sdim "%s END r=%u s=%u pl=%u", 322218893Sdim dir, (v1 >> 29) & 1, (v1 >> 28) & 1, (v1 >> 30) & 0x3); 323193326Sed return; 324212904Sdim 325212904Sdim case PDU_ENDAK: 326193326Sed sscop->funcs->verbose(sscop, sscop->aarg, "%s ENDAK", dir); 327193326Sed return; 328193326Sed 329193326Sed case PDU_RS: 330212904Sdim sscop->funcs->verbose(sscop, sscop->aarg, 331193326Sed "%s RS n(mr)=%u n(sq)=%u pl=%u", 332193326Sed dir, v1 & 0xffffff, v2 & 0xff, (v1 >> 30) & 0x3); 333193326Sed return; 334193326Sed 335193326Sed case PDU_RSAK: 336193326Sed sscop->funcs->verbose(sscop, sscop->aarg, "%s RSAK n(mr)=%u", 337212904Sdim dir, v1 & 0xffffff); 338194179Sed return; 339194179Sed 340194711Sed case PDU_BGREJ: 341194711Sed sscop->funcs->verbose(sscop, sscop->aarg, "%s BGREJ pl=%u", 342198092Srdivacky dir, (v1 >> 30) & 0x3); 343212904Sdim return; 344263509Sdim 345194179Sed case PDU_SD: 346193326Sed sscop->funcs->verbose(sscop, sscop->aarg, "%s SD n(s)=%u pl=%u", 347193326Sed dir, v1 & 0xffffff, (v1 >> 30) & 0x3); 348193326Sed return; 349193326Sed 350212904Sdim case PDU_ER: 351194711Sed sscop->funcs->verbose(sscop, sscop->aarg, "%s ER n(mr)=%u n(sq)=%u", 352194711Sed dir, v1 & 0xffffff, v2 & 0xff); 353198092Srdivacky return; 354212904Sdim 355194179Sed case PDU_POLL: 356194179Sed sscop->funcs->verbose(sscop, sscop->aarg, "%s POLL n(s)=%u n(ps)=%u", 357193326Sed dir, v1 & 0xffffff, v2 & 0xffffff); 358193326Sed return; 359193326Sed 360193326Sed case PDU_STAT: 361193326Sed if (size < 12) 362193326Sed return; 363193326Sed v3 = MBUF_TRAIL32(m, -3); 364193326Sed sscop->funcs->verbose(sscop, sscop->aarg, 365193326Sed "%s STAT n(r)=%u n(mr)=%u n(ps)=%u", 366193326Sed dir, v1 & 0xffffff, v2 & 0xffffff, v3 & 0xffffff); 367193326Sed n = (size - 12) / 4; 368193326Sed for (i = 0; i < (size - 12) / 4; i++, n--) { 369193326Sed v4 = MBUF_TRAIL32(m, -4 - (int)i); 370193326Sed sscop->funcs->verbose(sscop, sscop->aarg, 371193326Sed " LE(%u)=%u", n, v4 & 0xffffff); 372252723Sdim } 373193326Sed return; 374193326Sed 375193326Sed case PDU_USTAT: 376252723Sdim if (size < 16) 377252723Sdim return; 378252723Sdim sscop->funcs->verbose(sscop, sscop->aarg, 379252723Sdim "%s STAT n(r)=%u n(mr)=%u LE1=%u LE2=%u", 380252723Sdim dir, v1 & 0xffffff, v2 & 0xffffff, 381252723Sdim MBUF_TRAIL32(m, -4) & 0xffffff, 382252723Sdim MBUF_TRAIL32(m, -3) & 0xffffff); 383193326Sed return; 384193326Sed 385212904Sdim case PDU_UD: 386193326Sed sscop->funcs->verbose(sscop, sscop->aarg, 387193326Sed "%s UD pl=%u", dir, (v1 >> 30) & 0x3); 388193326Sed return; 389252723Sdim 390252723Sdim case PDU_MD: 391193326Sed sscop->funcs->verbose(sscop, sscop->aarg, 392193326Sed "%s MD pl=%u", dir, (v1 >> 30) & 0x3); 393193326Sed return; 394193326Sed 395193326Sed case PDU_ERAK: 396193326Sed sscop->funcs->verbose(sscop, sscop->aarg, 397193326Sed "%s ERAK n(mr)=%u", dir, v1 & 0xffffff); 398193326Sed return; 399252723Sdim } 400252723Sdim} 401193326Sed#endif 402193326Sed 403193326Sed 404193326Sed/* 405263509Sdim * Initialize state of variables 406263509Sdim */ 407263509Sdimstatic void 408263509Sdimsscop_init(struct sscop *sscop) 409263509Sdim{ 410263509Sdim sscop->state = SSCOP_IDLE; 411263509Sdim 412263509Sdim sscop->vt_sq = 0; 413263509Sdim sscop->vr_sq = 0; 414263509Sdim sscop->clear_buffers = 1; 415263509Sdim 416245431Sdim sscop->ll_busy = 0; 417245431Sdim 418245431Sdim sscop->rxq = 0; 419245431Sdim} 420235633Sdim 421235633Sdimstatic void 422193326Sedsscop_clear(struct sscop *sscop) 423193326Sed{ 424193326Sed TIMER_STOP(sscop, cc); 425193326Sed TIMER_STOP(sscop, ka); 426193326Sed TIMER_STOP(sscop, nr); 427193326Sed TIMER_STOP(sscop, idle); 428193326Sed TIMER_STOP(sscop, poll); 429193326Sed 430193326Sed FREE_UU(uu_bgn); 431193326Sed FREE_UU(uu_bgak); 432193326Sed FREE_UU(uu_bgrej); 433193326Sed FREE_UU(uu_end); 434193326Sed FREE_UU(uu_rs); 435193326Sed 436198092Srdivacky MSGQ_CLEAR(&sscop->xq); 437198092Srdivacky MSGQ_CLEAR(&sscop->uxq); 438263509Sdim MSGQ_CLEAR(&sscop->mxq); 439263509Sdim MSGQ_CLEAR(&sscop->xbuf); 440263509Sdim MSGQ_CLEAR(&sscop->rbuf); 441198092Srdivacky 442193326Sed SIGQ_CLEAR(&sscop->sigs); 443193326Sed SIGQ_CLEAR(&sscop->saved_sigs); 444193326Sed} 445193326Sed 446235633Sdim 447235633Sdim/* 448221345Sdim * Allocate instance memory, initialize the state of all variables. 449235633Sdim */ 450263509Sdimstruct sscop * 451263509Sdimsscop_create(void *a, const struct sscop_funcs *funcs) 452263509Sdim{ 453263509Sdim struct sscop *sscop; 454263509Sdim 455263509Sdim MEMZALLOC(sscop, struct sscop *, sizeof(struct sscop)); 456263509Sdim if (sscop == NULL) 457263509Sdim return (NULL); 458263509Sdim 459235633Sdim if (a == NULL) 460263509Sdim sscop->aarg = sscop; 461263509Sdim else 462235633Sdim sscop->aarg = a; 463235633Sdim sscop->funcs = funcs; 464235633Sdim 465235633Sdim sscop->maxk = MAXK; 466221345Sdim sscop->maxj = MAXJ; 467221345Sdim sscop->maxcc = MAXCC; 468221345Sdim sscop->maxpd = MAXPD; 469221345Sdim sscop->maxstat = MAXSTAT; 470221345Sdim sscop->timercc = TIMERCC; 471221345Sdim sscop->timerka = TIMERKA; 472235633Sdim sscop->timernr = TIMERNR; 473221345Sdim sscop->timerpoll = TIMERPOLL; 474221345Sdim sscop->timeridle = TIMERIDLE; 475221345Sdim sscop->robustness = 0; 476221345Sdim sscop->poll_after_rex = 0; 477221345Sdim sscop->mr = MAXMR; 478221345Sdim 479221345Sdim TIMER_INIT(sscop, cc); 480221345Sdim TIMER_INIT(sscop, nr); 481221345Sdim TIMER_INIT(sscop, ka); 482221345Sdim TIMER_INIT(sscop, poll); 483221345Sdim TIMER_INIT(sscop, idle); 484221345Sdim 485221345Sdim MSGQ_INIT(&sscop->xq); 486221345Sdim MSGQ_INIT(&sscop->uxq); 487202379Srdivacky MSGQ_INIT(&sscop->mxq); 488202379Srdivacky MSGQ_INIT(&sscop->rbuf); 489202379Srdivacky MSGQ_INIT(&sscop->xbuf); 490202379Srdivacky 491202379Srdivacky SIGQ_INIT(&sscop->sigs); 492202379Srdivacky SIGQ_INIT(&sscop->saved_sigs); 493202379Srdivacky 494202379Srdivacky sscop_init(sscop); 495221345Sdim 496202379Srdivacky return (sscop); 497198092Srdivacky} 498198092Srdivacky 499198092Srdivacky/* 500235633Sdim * Free all resources in a sscop instance 501235633Sdim */ 502198092Srdivackyvoid 503198092Srdivackysscop_destroy(struct sscop *sscop) 504198092Srdivacky{ 505198092Srdivacky sscop_reset(sscop); 506198092Srdivacky 507198092Srdivacky MEMFREE(sscop); 508198092Srdivacky} 509198092Srdivacky 510235633Sdim/* 511207619Srdivacky * Reset the SSCOP instance. 512207619Srdivacky */ 513218893Sdimvoid 514205219Srdivackysscop_reset(struct sscop *sscop) 515198092Srdivacky{ 516198092Srdivacky sscop_clear(sscop); 517198092Srdivacky sscop_init(sscop); 518198092Srdivacky} 519207619Srdivacky 520235633Sdimvoid 521198092Srdivackysscop_getparam(const struct sscop *sscop, struct sscop_param *p) 522198092Srdivacky{ 523198092Srdivacky p->timer_cc = sscop->timercc; 524198092Srdivacky p->timer_poll = sscop->timerpoll; 525198092Srdivacky p->timer_keep_alive = sscop->timerka; 526198092Srdivacky p->timer_no_response = sscop->timernr; 527198092Srdivacky p->timer_idle = sscop->timeridle; 528198092Srdivacky p->maxk = sscop->maxk; 529198092Srdivacky p->maxj = sscop->maxj; 530198092Srdivacky p->maxcc = sscop->maxcc; 531198092Srdivacky p->maxpd = sscop->maxpd; 532198092Srdivacky p->maxstat = sscop->maxstat; 533198092Srdivacky p->mr = sscop->mr; 534198092Srdivacky p->flags = 0; 535198092Srdivacky if(sscop->robustness) 536198092Srdivacky p->flags |= SSCOP_ROBUST; 537198092Srdivacky if(sscop->poll_after_rex) 538198092Srdivacky p->flags |= SSCOP_POLLREX; 539198092Srdivacky} 540198092Srdivacky 541198092Srdivackyint 542198092Srdivackysscop_setparam(struct sscop *sscop, struct sscop_param *p, u_int *pmask) 543198092Srdivacky{ 544198092Srdivacky u_int mask = *pmask; 545198092Srdivacky 546198092Srdivacky /* can change only in idle state */ 547198092Srdivacky if (sscop->state != SSCOP_IDLE) 548198092Srdivacky return (EISCONN); 549198092Srdivacky 550198092Srdivacky *pmask = 0; 551198092Srdivacky 552198092Srdivacky /* 553198092Srdivacky * first check all parameters 554198092Srdivacky */ 555198092Srdivacky if ((mask & SSCOP_SET_TCC) && p->timer_cc == 0) 556198092Srdivacky *pmask |= SSCOP_SET_TCC; 557198092Srdivacky if ((mask & SSCOP_SET_TPOLL) && p->timer_poll == 0) 558198092Srdivacky *pmask |= SSCOP_SET_TPOLL; 559198092Srdivacky if ((mask & SSCOP_SET_TKA) && p->timer_keep_alive == 0) 560198092Srdivacky *pmask |= SSCOP_SET_TKA; 561198092Srdivacky if ((mask & SSCOP_SET_TNR) && p->timer_no_response == 0) 562198092Srdivacky *pmask |= SSCOP_SET_TNR; 563198092Srdivacky if ((mask & SSCOP_SET_TIDLE) && p->timer_idle == 0) 564198092Srdivacky *pmask |= SSCOP_SET_TIDLE; 565198092Srdivacky if ((mask & SSCOP_SET_MAXK) && p->maxk > MAXMAXK) 566198092Srdivacky *pmask |= SSCOP_SET_MAXK; 567198092Srdivacky if ((mask & SSCOP_SET_MAXJ) && p->maxj > MAXMAXJ) 568198092Srdivacky *pmask |= SSCOP_SET_MAXJ; 569198092Srdivacky if ((mask & SSCOP_SET_MAXCC) && p->maxcc > 255) 570193326Sed *pmask |= SSCOP_SET_MAXCC; 571193326Sed if ((mask & SSCOP_SET_MAXPD) && p->maxpd >= (1 << 24)) 572193326Sed *pmask |= SSCOP_SET_MAXPD; 573252723Sdim if ((mask & SSCOP_SET_MAXSTAT) && 574252723Sdim ((p->maxstat & 1) == 0 || p->maxstat == 1 || p->maxstat == 2 || 575252723Sdim p->maxstat * 4 > MAXMAXK - 8)) 576252723Sdim *pmask |= SSCOP_SET_MAXSTAT; 577252723Sdim if ((mask & SSCOP_SET_MR) && p->mr >= (1 << 24) - 1) 578252723Sdim *pmask |= SSCOP_SET_MR; 579252723Sdim 580252723Sdim if (*pmask) 581252723Sdim return (EINVAL); 582252723Sdim 583252723Sdim 584252723Sdim /* 585252723Sdim * now set it 586252723Sdim */ 587252723Sdim if (mask & SSCOP_SET_TCC) 588252723Sdim sscop->timercc = p->timer_cc; 589235633Sdim 590226890Sdim if (mask & SSCOP_SET_TPOLL) 591235633Sdim sscop->timerpoll = p->timer_poll; 592226890Sdim 593226890Sdim if (mask & SSCOP_SET_TKA) 594226890Sdim sscop->timerka = p->timer_keep_alive; 595226890Sdim 596226890Sdim if (mask & SSCOP_SET_TNR) 597226890Sdim sscop->timernr = p->timer_no_response; 598226890Sdim 599263509Sdim if (mask & SSCOP_SET_TIDLE) 600263509Sdim sscop->timeridle = p->timer_idle; 601263509Sdim 602263509Sdim if (mask & SSCOP_SET_MAXK) 603263509Sdim sscop->maxk = p->maxk; 604263509Sdim if (mask & SSCOP_SET_MAXJ) 605263509Sdim sscop->maxj = p->maxj; 606263509Sdim 607263509Sdim if (mask & SSCOP_SET_MAXCC) 608263509Sdim sscop->maxcc = p->maxcc; 609263509Sdim if (mask & SSCOP_SET_MAXPD) 610203955Srdivacky sscop->maxpd = p->maxpd; 611195341Sed if (mask & SSCOP_SET_MAXSTAT) 612195341Sed sscop->maxstat = p->maxstat; 613193326Sed 614193326Sed if (mask & SSCOP_SET_MR) 615193326Sed sscop->mr = p->mr; 616221345Sdim 617221345Sdim if (mask & SSCOP_SET_ROBUST) 618221345Sdim sscop->robustness = ((p->flags & SSCOP_ROBUST) != 0); 619221345Sdim 620221345Sdim if (mask & SSCOP_SET_POLLREX) 621221345Sdim sscop->poll_after_rex = ((p->flags & SSCOP_POLLREX) != 0); 622221345Sdim 623235633Sdim return (0); 624221345Sdim} 625221345Sdim 626221345Sdimenum sscop_state 627221345Sdimsscop_getstate(const struct sscop *sscop) 628221345Sdim{ 629221345Sdim return (sscop->state); 630221345Sdim} 631221345Sdim 632221345Sdim 633221345Sdim/************************************************************/ 634221345Sdim/* 635221345Sdim * EXTERNAL INPUT SIGNAL MAPPING 636221345Sdim */ 637221345Sdim 638221345Sdim/* 639221345Sdim * Map AA signal to SSCOP internal signal 640221345Sdim */ 641221345Sdimint 642221345Sdimsscop_aasig(struct sscop *sscop, enum sscop_aasig sig, 643221345Sdim struct SSCOP_MBUF_T *m, u_int arg) 644221345Sdim{ 645221345Sdim struct sscop_msg *msg; 646221345Sdim 647221345Sdim if (sig >= sizeof(sscop_sigs)/sizeof(sscop_sigs[0])) { 648221345Sdim VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg, 649221345Sdim "AA-Signal %u - bad signal", sig)); 650221345Sdim MBUF_FREE(m); 651221345Sdim return (EINVAL); 652221345Sdim } 653221345Sdim VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg, 654221345Sdim "AA-Signal %s in state %s with%s message", 655221345Sdim sscop_sigs[sig], states[sscop->state], m ? "" : "out")); 656221345Sdim 657221345Sdim MSG_ALLOC(msg); 658193326Sed if (msg == NULL) { 659193326Sed FAILURE("sscop: cannot allocate aasig"); 660193326Sed MBUF_FREE(m); 661193326Sed return (ENOMEM); 662193326Sed } 663193326Sed 664193326Sed switch(sig) { 665193326Sed 666193326Sed case SSCOP_ESTABLISH_request: 667193326Sed msg->m = m; 668252723Sdim msg->rexmit = arg; 669193326Sed sscop_signal(sscop, SIG_ESTAB_REQ, msg); 670193326Sed break; 671193326Sed 672193326Sed case SSCOP_ESTABLISH_response: 673193326Sed msg->m = m; 674193326Sed msg->rexmit = arg; 675193326Sed sscop_signal(sscop, SIG_ESTAB_RESP, msg); 676193326Sed break; 677193326Sed 678193326Sed case SSCOP_RELEASE_request: 679198092Srdivacky msg->m = m; 680193326Sed sscop_signal(sscop, SIG_RELEASE_REQ, msg); 681198092Srdivacky break; 682193326Sed 683193326Sed case SSCOP_DATA_request: 684193326Sed msg->m = m; 685198092Srdivacky sscop_signal(sscop, SIG_USER_DATA, msg); 686193326Sed break; 687193326Sed 688193326Sed case SSCOP_UDATA_request: 689198092Srdivacky msg->m = m; 690193326Sed sscop_signal(sscop, SIG_UDATA, msg); 691198092Srdivacky break; 692193326Sed 693193326Sed case SSCOP_RECOVER_response: 694193326Sed MBUF_FREE(m); 695193326Sed MSG_FREE(msg); 696193326Sed sscop_signal(sscop, SIG_RECOVER, NULL); 697193326Sed break; 698193326Sed 699193326Sed case SSCOP_RESYNC_request: 700193326Sed msg->m = m; 701193326Sed sscop_signal(sscop, SIG_SYNC_REQ, msg); 702193326Sed break; 703194179Sed 704193326Sed case SSCOP_RESYNC_response: 705193326Sed MBUF_FREE(m); 706193326Sed MSG_FREE(msg); 707193326Sed sscop_signal(sscop, SIG_SYNC_RESP, NULL); 708193326Sed break; 709193326Sed 710226890Sdim case SSCOP_RETRIEVE_request: 711226890Sdim MBUF_FREE(m); 712235633Sdim msg->rexmit = arg; 713235633Sdim sscop_signal(sscop, SIG_RETRIEVE, msg); 714235633Sdim break; 715226890Sdim 716226890Sdim case SSCOP_ESTABLISH_indication: 717226890Sdim case SSCOP_ESTABLISH_confirm: 718226890Sdim case SSCOP_RELEASE_indication: 719226890Sdim case SSCOP_RELEASE_confirm: 720226890Sdim case SSCOP_DATA_indication: 721226890Sdim case SSCOP_UDATA_indication: 722235633Sdim case SSCOP_RECOVER_indication: 723245431Sdim case SSCOP_RESYNC_indication: 724245431Sdim case SSCOP_RESYNC_confirm: 725245431Sdim case SSCOP_RETRIEVE_indication: 726226890Sdim case SSCOP_RETRIEVE_COMPL_indication: 727226890Sdim MBUF_FREE(m); 728226890Sdim MSG_FREE(msg); 729226890Sdim return EINVAL; 730226890Sdim } 731245431Sdim 732245431Sdim return 0; 733245431Sdim} 734245431Sdim 735245431Sdim/* 736245431Sdim * Signal from layer management. 737245431Sdim */ 738245431Sdimint 739245431Sdimsscop_maasig(struct sscop *sscop, enum sscop_maasig sig, struct SSCOP_MBUF_T *m) 740245431Sdim{ 741245431Sdim struct sscop_msg *msg; 742245431Sdim 743245431Sdim if (sig >= sizeof(sscop_msigs)/sizeof(sscop_msigs[0])) { 744245431Sdim VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg, 745226890Sdim "MAA-Signal %u - bad signal", sig)); 746235633Sdim MBUF_FREE(m); 747235633Sdim return (EINVAL); 748235633Sdim } 749226890Sdim VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg, 750235633Sdim "MAA-Signal %s in state %s with%s message", 751235633Sdim sscop_msigs[sig], states[sscop->state], m ? "" : "out")); 752235633Sdim 753235633Sdim MSG_ALLOC(msg); 754235633Sdim if (msg == NULL) { 755235633Sdim FAILURE("sscop: cannot allocate maasig"); 756235633Sdim MBUF_FREE(m); 757226890Sdim return (ENOMEM); 758235633Sdim } 759226890Sdim 760235633Sdim switch (sig) { 761245431Sdim 762245431Sdim case SSCOP_MDATA_request: 763235633Sdim msg->m = m; 764235633Sdim sscop_signal(sscop, SIG_MDATA, msg); 765235633Sdim break; 766235633Sdim 767226890Sdim case SSCOP_MDATA_indication: 768226890Sdim case SSCOP_MERROR_indication: 769235633Sdim MBUF_FREE(m); 770235633Sdim MSG_FREE(msg); 771235633Sdim return (EINVAL); 772235633Sdim } 773226890Sdim return (0); 774226890Sdim} 775226890Sdim 776226890Sdim/* 777226890Sdim * Map PDU to SSCOP signal. 778235633Sdim */ 779226890Sdimvoid 780235633Sdimsscop_input(struct sscop *sscop, struct SSCOP_MBUF_T *m) 781235633Sdim{ 782235633Sdim struct sscop_msg *msg; 783235633Sdim union pdu pdu; 784235633Sdim u_int size; 785235633Sdim 786235633Sdim MSG_ALLOC(msg); 787235633Sdim if(msg == NULL) { 788226890Sdim FAILURE("sscop: cannot allocate in pdu msg"); 789226890Sdim MBUF_FREE(m); 790226890Sdim return; 791226890Sdim } 792226890Sdim 793226890Sdim msg->m = m; 794235633Sdim msg->rexmit = 0; 795245431Sdim 796226890Sdim size = MBUF_LEN(m); 797226890Sdim 798226890Sdim if(size % 4 != 0 || size < 4) 799235633Sdim goto err; 800235633Sdim 801235633Sdim pdu.sscop_null = MBUF_TRAIL32(m, -1); 802235633Sdim 803226890Sdim VERBOSE(sscop, SSCOP_DBG_PDU, (sscop, sscop->aarg, 804226890Sdim "got %s, size=%u", pdus[pdu.sscop_type], size)); 805226890Sdim 806226890Sdim#ifdef SSCOP_DEBUG 807252723Sdim#define ENSURE(C,F) if(!(C)) { VERBOSE(sscop, SSCOP_DBG_PDU, F); goto err; } 808226890Sdim#else 809252723Sdim#define ENSURE(C,F) if(!(C)) goto err 810252723Sdim#endif 811226890Sdim 812252723Sdim#ifdef SSCOP_DEBUG 813252723Sdim if (ISVERBOSE(sscop, SSCOP_DBG_PDU)) 814226890Sdim sscop_dump_pdu(sscop, "rx", m); 815226890Sdim#endif 816226890Sdim 817226890Sdim switch(pdu.sscop_type) { 818226890Sdim 819226890Sdim default: 820226890Sdim ENSURE(0, (sscop, sscop->aarg, 821226890Sdim "Bad PDU type %u", pdu.sscop_type)); 822226890Sdim break; 823226890Sdim 824252723Sdim case PDU_BGN: 825226890Sdim ENSURE(size >= 8U, (sscop, sscop->aarg, 826226890Sdim "PDU_BGN size=%u", size)); 827226890Sdim ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg, 828226890Sdim "PDU_BGN size=%u pl=%u", size, pdu.sscop_pl)); 829226890Sdim ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg, 830226890Sdim "PDU_BGN size=%u", size)); 831226890Sdim sscop_signal(sscop, SIG_BGN, msg); 832226890Sdim break; 833226890Sdim 834226890Sdim case PDU_BGAK: 835226890Sdim ENSURE(size >= 8U, (sscop, sscop->aarg, 836226890Sdim "PDU_BGAK size=%u", size)); 837226890Sdim ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg, 838226890Sdim "PDU_BGAK size=%u pl=%u", size, pdu.sscop_pl)); 839226890Sdim ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg, 840226890Sdim "PDU_BGAK size=%u", size)); 841226890Sdim sscop_signal(sscop, SIG_BGAK, msg); 842226890Sdim break; 843226890Sdim 844226890Sdim case PDU_END: 845226890Sdim ENSURE(size >= 8U, (sscop, sscop->aarg, 846226890Sdim "PDU_END size=%u", size)); 847226890Sdim ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg, 848252723Sdim "PDU_END size=%u pl=%u", size, pdu.sscop_pl)); 849252723Sdim ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg, 850252723Sdim "PDU_END size=%u", size)); 851252723Sdim sscop_signal(sscop, SIG_END, msg); 852252723Sdim break; 853252723Sdim 854226890Sdim case PDU_ENDAK: 855226890Sdim ENSURE(size == 8U, (sscop, sscop->aarg, 856226890Sdim "PDU_ENDAK size=%u", size)); 857252723Sdim sscop_signal(sscop, SIG_ENDAK, msg); 858252723Sdim break; 859252723Sdim 860252723Sdim case PDU_BGREJ: 861252723Sdim ENSURE(size >= 8U, (sscop, sscop->aarg, 862252723Sdim "PDU_BGREJ size=%u", size)); 863252723Sdim ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg, 864252723Sdim "PDU_BGREJ size=%u pl=%u", size, pdu.sscop_pl)); 865252723Sdim ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg, 866252723Sdim "PDU_BGREJ size=%u", size)); 867252723Sdim sscop_signal(sscop, SIG_BGREJ, msg); 868252723Sdim break; 869252723Sdim 870252723Sdim case PDU_SD: 871252723Sdim ENSURE(size >= 4U + pdu.sscop_pl, (sscop, sscop->aarg, 872252723Sdim "PDU_SD size=%u pl=%u", size, pdu.sscop_pl)); 873252723Sdim ENSURE(size <= 4U + sscop->maxk, (sscop, sscop->aarg, 874252723Sdim "PDU_SD size=%u", size)); 875252723Sdim sscop_signal(sscop, SIG_SD, msg); 876252723Sdim break; 877252723Sdim 878252723Sdim case PDU_UD: 879252723Sdim ENSURE(size >= 4U + pdu.sscop_pl, (sscop, sscop->aarg, 880252723Sdim "PDU_UD size=%u pl=%u", size, pdu.sscop_pl)); 881252723Sdim ENSURE(size <= 4U + sscop->maxk, (sscop, sscop->aarg, 882252723Sdim "PDU_UD size=%u", size)); 883263509Sdim sscop_signal(sscop, SIG_UD, msg); 884252723Sdim break; 885252723Sdim 886252723Sdim case PDU_MD: 887252723Sdim ENSURE(size >= 4U + pdu.sscop_pl, (sscop, sscop->aarg, 888252723Sdim "PDU_MD size=%u pl=%u", size, pdu.sscop_pl)); 889252723Sdim ENSURE(size <= 4U + sscop->maxk, (sscop, sscop->aarg, 890252723Sdim "PDU_MD size=%u", size)); 891252723Sdim sscop_signal(sscop, SIG_MD, msg); 892252723Sdim break; 893252723Sdim 894226890Sdim case PDU_POLL: 895252723Sdim ENSURE(size == 8U, (sscop, sscop->aarg, 896252723Sdim "PDU_POLL size=%u", size)); 897226890Sdim sscop_signal(sscop, SIG_POLL, msg); 898252723Sdim break; 899252723Sdim 900252723Sdim case PDU_STAT: 901252723Sdim ENSURE(size >= 12U, (sscop, sscop->aarg, 902252723Sdim "PDU_STAT size=%u", size)); 903252723Sdim ENSURE(size <= 12U + 4 * sscop->maxstat, (sscop, sscop->aarg, 904252723Sdim "PDU_STAT size=%u", size)); 905252723Sdim sscop_signal(sscop, SIG_STAT, msg); 906226890Sdim break; 907226890Sdim 908226890Sdim case PDU_RS: 909226890Sdim ENSURE(size >= 8U, (sscop, sscop->aarg, 910226890Sdim "PDU_RS size=%u", size)); 911226890Sdim ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg, 912226890Sdim "PDU_RS size=%u pl=%u", size, pdu.sscop_pl)); 913226890Sdim ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg, 914226890Sdim "PDU_RS size=%u", size)); 915226890Sdim sscop_signal(sscop, SIG_RS, msg); 916226890Sdim break; 917226890Sdim 918226890Sdim case PDU_RSAK: 919226890Sdim ENSURE(size == 8U, (sscop, sscop->aarg, 920226890Sdim "PDU_RSAK size=%u", size)); 921226890Sdim sscop_signal(sscop, SIG_RSAK, msg); 922226890Sdim break; 923226890Sdim 924226890Sdim case PDU_ER: 925226890Sdim ENSURE(size == 8U, (sscop, sscop->aarg, 926226890Sdim "PDU_ER size=%u", size)); 927226890Sdim sscop_signal(sscop, SIG_ER, msg); 928226890Sdim break; 929263509Sdim 930263509Sdim case PDU_ERAK: 931263509Sdim ENSURE(size == 8U, (sscop, sscop->aarg, 932226890Sdim "PDU_ERAK size=%u", size)); 933226890Sdim sscop_signal(sscop, SIG_ERAK, msg); 934235633Sdim break; 935235633Sdim 936235633Sdim case PDU_USTAT: 937235633Sdim ENSURE(size == 16U, (sscop, sscop->aarg, 938235633Sdim "PDU_ERAK size=%u", size)); 939226890Sdim sscop_signal(sscop, SIG_USTAT, msg); 940226890Sdim break; 941226890Sdim } 942226890Sdim#undef ENSURE 943226890Sdim return; 944226890Sdim 945226890Sdim err: 946226890Sdim MAAL_ERROR(sscop, 'U', 0); 947226890Sdim SSCOP_MSG_FREE(msg); 948226890Sdim} 949226890Sdim 950226890Sdim/************************************************************/ 951226890Sdim/* 952226890Sdim * UTILITIES 953226890Sdim */ 954226890Sdim 955226890Sdim/* 956252723Sdim * Move the receiver window by N packets 957252723Sdim */ 958252723Sdimu_int 959252723Sdimsscop_window(struct sscop *sscop, u_int n) 960263509Sdim{ 961252723Sdim sscop->vr_mr += n; 962252723Sdim return (SEQNO_DIFF(sscop->vr_mr, sscop->vr_r)); 963252723Sdim} 964252723Sdim 965252723Sdim/* 966252723Sdim * Lower layer busy handling 967252723Sdim */ 968252723Sdimu_int 969252723Sdimsscop_setbusy(struct sscop *sscop, int busy) 970252723Sdim{ 971252723Sdim u_int old = sscop->ll_busy; 972252723Sdim 973252723Sdim if (busy > 0) 974252723Sdim sscop->ll_busy = 1; 975252723Sdim else if (busy == 0) { 976252723Sdim sscop->ll_busy = 0; 977252723Sdim if(old) 978252723Sdim handle_sigs(sscop); 979252723Sdim } 980252723Sdim 981252723Sdim return (old); 982252723Sdim} 983252723Sdim 984252723Sdimconst char * 985252723Sdimsscop_signame(enum sscop_aasig sig) 986252723Sdim{ 987252723Sdim static char str[40]; 988252723Sdim 989252723Sdim if (sig >= sizeof(sscop_sigs)/sizeof(sscop_sigs[0])) { 990252723Sdim sprintf(str, "BAD SSCOP_AASIG %u", sig); 991252723Sdim return (str); 992252723Sdim } else { 993252723Sdim return (sscop_sigs[sig]); 994252723Sdim } 995252723Sdim} 996252723Sdim 997252723Sdimconst char * 998252723Sdimsscop_msigname(enum sscop_maasig sig) 999252723Sdim{ 1000252723Sdim static char str[40]; 1001252723Sdim 1002252723Sdim if (sig >= sizeof(sscop_msigs)/sizeof(sscop_msigs[0])) { 1003252723Sdim sprintf(str, "BAD SSCOP_MAASIG %u", sig); 1004252723Sdim return (str); 1005252723Sdim } else { 1006252723Sdim return (sscop_msigs[sig]); 1007252723Sdim } 1008252723Sdim} 1009252723Sdim 1010252723Sdimconst char * 1011252723Sdimsscop_statename(enum sscop_state s) 1012252723Sdim{ 1013252723Sdim static char str[40]; 1014252723Sdim 1015252723Sdim if (s >= sizeof(states)/sizeof(states[0])) { 1016252723Sdim sprintf(str, "BAD SSCOP_STATE %u", s); 1017252723Sdim return (str); 1018252723Sdim } else { 1019252723Sdim return (states[s]); 1020252723Sdim } 1021252723Sdim} 1022252723Sdim 1023252723Sdim 1024252723Sdim/************************************************************/ 1025252723Sdim/* 1026252723Sdim * MACROS 1027252723Sdim */ 1028252723Sdim 1029252723Sdim/* 1030252723Sdim * p 75: release buffers 1031252723Sdim */ 1032252723Sdimstatic void 1033252723Sdimm_release_buffers(struct sscop *sscop) 1034252723Sdim{ 1035252723Sdim MSGQ_CLEAR(&sscop->xq); 1036252723Sdim MSGQ_CLEAR(&sscop->xbuf); 1037252723Sdim sscop->rxq = 0; 1038252723Sdim MSGQ_CLEAR(&sscop->rbuf); 1039252723Sdim} 1040252723Sdim 1041252723Sdim/* 1042252723Sdim * P 75: Prepare retrival 1043252723Sdim */ 1044252723Sdimstatic void 1045252723Sdimm_prepare_retrieval(struct sscop *sscop) 1046252723Sdim{ 1047252723Sdim struct sscop_msg *msg; 1048252723Sdim 1049252723Sdim if (sscop->clear_buffers) { 1050252723Sdim MSGQ_CLEAR(&sscop->xq); 1051252723Sdim MSGQ_CLEAR(&sscop->xbuf); 1052252723Sdim } 1053252723Sdim MSGQ_FOREACH(msg, &sscop->xbuf) 1054252723Sdim msg->rexmit = 0; 1055252723Sdim sscop->rxq = 0; 1056252723Sdim 1057252723Sdim MSGQ_CLEAR(&sscop->rbuf); 1058252723Sdim} 1059252723Sdim 1060252723Sdim/* 1061252723Sdim * P 75: Prepare retrival 1062252723Sdim */ 1063252723Sdimstatic void 1064252723Sdimm_prepare_recovery(struct sscop *sscop) 1065252723Sdim{ 1066252723Sdim struct sscop_msg *msg; 1067252723Sdim 1068252723Sdim if(sscop->clear_buffers) { 1069252723Sdim MSGQ_CLEAR(&sscop->xq); 1070252723Sdim MSGQ_CLEAR(&sscop->xbuf); 1071252723Sdim } 1072252723Sdim MSGQ_FOREACH(msg, &sscop->xbuf) 1073252723Sdim msg->rexmit = 0; 1074226890Sdim sscop->rxq = 0; 1075226890Sdim} 1076226890Sdim 1077226890Sdim 1078226890Sdim/* 1079226890Sdim * P 75: Clear transmitter 1080235633Sdim */ 1081226890Sdimstatic void 1082226890Sdimm_clear_transmitter(struct sscop *sscop) 1083226890Sdim{ 1084226890Sdim if(!sscop->clear_buffers) { 1085226890Sdim MSGQ_CLEAR(&sscop->xq); 1086235633Sdim MSGQ_CLEAR(&sscop->xbuf); 1087226890Sdim } 1088226890Sdim} 1089226890Sdim 1090226890Sdim 1091226890Sdim/* 1092226890Sdim * p 75: Deliver data 1093226890Sdim * Freeing the message is the responibility of the handler function. 1094252723Sdim */ 1095252723Sdimstatic void 1096226890Sdimm_deliver_data(struct sscop *sscop) 1097252723Sdim{ 1098226890Sdim struct sscop_msg *msg; 1099252723Sdim u_int sn; 1100226890Sdim 1101226890Sdim if ((msg = MSGQ_GET(&sscop->rbuf)) == NULL) 1102252723Sdim return; 1103252723Sdim 1104252723Sdim if (sscop->clear_buffers) { 1105226890Sdim MSGQ_CLEAR(&sscop->rbuf); 1106252723Sdim return; 1107252723Sdim } 1108252723Sdim 1109252723Sdim sn = msg->seqno + 1; 1110252723Sdim AAL_DATA(sscop, SSCOP_DATA_indication, msg->m, msg->seqno); 1111226890Sdim MSG_FREE(msg); 1112226890Sdim 1113226890Sdim while ((msg = MSGQ_GET(&sscop->rbuf)) != NULL) { 1114226890Sdim ASSERT(msg->seqno == sn); 1115226890Sdim if (++sn == SSCOP_MAXSEQNO) 1116235633Sdim sn = 0; 1117235633Sdim AAL_DATA(sscop, SSCOP_DATA_indication, msg->m, msg->seqno); 1118235633Sdim MSG_FREE(msg); 1119235633Sdim } 1120235633Sdim} 1121235633Sdim 1122226890Sdim/* 1123235633Sdim * P 75: Initialize state variables 1124226890Sdim */ 1125226890Sdimstatic void 1126226890Sdimm_initialize_state(struct sscop *sscop) 1127226890Sdim{ 1128226890Sdim sscop->vt_s = 0; 1129226890Sdim sscop->vt_ps = 0; 1130226890Sdim sscop->vt_a = 0; 1131226890Sdim 1132226890Sdim sscop->vt_pa = 1; 1133226890Sdim sscop->vt_pd = 0; 1134226890Sdim sscop->credit = 1; 1135226890Sdim 1136226890Sdim sscop->vr_r = 0; 1137245431Sdim sscop->vr_h = 0; 1138226890Sdim} 1139226890Sdim 1140226890Sdim/* 1141226890Sdim * p 76: Data retrieval 1142226890Sdim */ 1143226890Sdimstatic void 1144226890Sdimm_data_retrieval(struct sscop *sscop, u_int rn) 1145226890Sdim{ 1146226890Sdim struct sscop_msg *s; 1147226890Sdim 1148226890Sdim if (rn != SSCOP_RETRIEVE_UNKNOWN) { 1149226890Sdim if(rn >= SSCOP_RETRIEVE_TOTAL) 1150226890Sdim rn = sscop->vt_a; 1151226890Sdim else 1152226890Sdim rn++; 1153226890Sdim while(rn >= sscop->vt_a && rn < sscop->vt_s) { 1154226890Sdim if(rn == SSCOP_MAXSEQNO) rn = 0; 1155226890Sdim if((s = QFIND(&sscop->xbuf, rn)) != NULL) { 1156226890Sdim MSGQ_REMOVE(&sscop->xbuf, s); 1157226890Sdim AAL_DATA(sscop, SSCOP_RETRIEVE_indication, 1158226890Sdim s->m, 0); 1159226890Sdim MSG_FREE(s); 1160226890Sdim } 1161226890Sdim rn++; 1162226890Sdim } 1163226890Sdim } 1164226890Sdim 1165226890Sdim while((s = MSGQ_GET(&sscop->xq)) != NULL) { 1166226890Sdim AAL_DATA(sscop, SSCOP_RETRIEVE_indication, s->m, 0); 1167252723Sdim MSG_FREE(s); 1168252723Sdim } 1169252723Sdim AAL_SIG(sscop, SSCOP_RETRIEVE_COMPL_indication); 1170252723Sdim} 1171252723Sdim 1172252723Sdim/* 1173252723Sdim * P 76: Detect retransmission. PDU type must already be stripped. 1174252723Sdim */ 1175252723Sdimstatic int 1176226890Sdimm_detect_retransmission(struct sscop *sscop, struct sscop_msg *msg) 1177226890Sdim{ 1178252723Sdim union bgn bgn; 1179252723Sdim 1180252723Sdim bgn.sscop_null = MBUF_TRAIL32(msg->m, -1); 1181252723Sdim 1182226890Sdim if (sscop->vr_sq == bgn.sscop_bgns) 1183226890Sdim return (1); 1184226890Sdim 1185226890Sdim sscop->vr_sq = bgn.sscop_bgns; 1186226890Sdim return (0); 1187235633Sdim} 1188235633Sdim 1189235633Sdim/* 1190235633Sdim * P 76: Set POLL timer 1191235633Sdim */ 1192235633Sdimstatic void 1193235633Sdimm_set_poll_timer(struct sscop *sscop) 1194235633Sdim{ 1195235633Sdim if(MSGQ_EMPTY(&sscop->xq) && sscop->vt_s == sscop->vt_a) 1196235633Sdim TIMER_RESTART(sscop, ka); 1197252723Sdim else 1198235633Sdim TIMER_RESTART(sscop, poll); 1199252723Sdim} 1200235633Sdim 1201235633Sdim/* 1202235633Sdim * P 77: Reset data transfer timers 1203252723Sdim */ 1204252723Sdimstatic void 1205235633Sdimm_reset_data_xfer_timers(struct sscop *sscop) 1206235633Sdim{ 1207226890Sdim TIMER_STOP(sscop, ka); 1208226890Sdim TIMER_STOP(sscop, nr); 1209226890Sdim TIMER_STOP(sscop, idle); 1210193326Sed TIMER_STOP(sscop, poll); 1211193326Sed} 1212193326Sed 1213193326Sed/* 1214193326Sed * P 77: Set data transfer timers 1215193326Sed */ 1216235633Sdimstatic void 1217202379Srdivackym_set_data_xfer_timers(struct sscop *sscop) 1218193326Sed{ 1219193326Sed TIMER_RESTART(sscop, poll); 1220198092Srdivacky TIMER_RESTART(sscop, nr); 1221193326Sed} 1222193326Sed 1223193326Sed/* 1224193326Sed * P 77: Initialize VR(MR) 1225203955Srdivacky */ 1226193326Sedstatic void 1227263509Sdimm_initialize_mr(struct sscop *sscop) 1228263509Sdim{ 1229263509Sdim sscop->vr_mr = sscop->mr; 1230263509Sdim} 1231263509Sdim 1232263509Sdim/************************************************************/ 1233263509Sdim/* 1234263509Sdim * CONDITIONS 1235263509Sdim */ 1236263509Sdimstatic int 1237193326Sedc_ready_pduq(struct sscop *sscop) 1238263509Sdim{ 1239263509Sdim if (!sscop->ll_busy && 1240263509Sdim (sscop->rxq != 0 || 1241263509Sdim sscop->vt_s < sscop->vt_ms || 1242263509Sdim TIMER_ISACT(sscop, idle))) 1243263509Sdim return (1); 1244263509Sdim return (0); 1245263509Sdim} 1246263509Sdim 1247263509Sdim/************************************************************/ 1248263509Sdim/* 1249263509Sdim * SEND PDUS 1250263509Sdim */ 1251263509Sdim 1252263509Sdim/* 1253263509Sdim * Send BG PDU. 1254193326Sed */ 1255193326Sedstatic void 1256245431Sdimsend_bgn(struct sscop *sscop, struct SSCOP_MBUF_T *uu) 1257245431Sdim{ 1258245431Sdim union pdu pdu; 1259245431Sdim union bgn bgn; 1260245431Sdim struct SSCOP_MBUF_T *m; 1261245431Sdim 1262245431Sdim pdu.sscop_null = 0; 1263245431Sdim pdu.sscop_type = PDU_BGN; 1264245431Sdim pdu.sscop_ns = sscop->vr_mr; 1265245431Sdim 1266245431Sdim bgn.sscop_null = 0; 1267245431Sdim bgn.sscop_bgns = sscop->vt_sq; 1268245431Sdim 1269245431Sdim if(uu) { 1270245431Sdim if ((m = MBUF_DUP(uu)) == NULL) { 1271245431Sdim FAILURE("sscop: cannot allocate BGN"); 1272245431Sdim return; 1273245431Sdim } 1274245431Sdim pdu.sscop_pl += MBUF_PAD4(m); 1275245431Sdim } else { 1276245431Sdim if ((m = MBUF_ALLOC(8)) == NULL) { 1277245431Sdim FAILURE("sscop: cannot allocate BGN"); 1278245431Sdim return; 1279245431Sdim } 1280245431Sdim } 1281245431Sdim 1282245431Sdim MBUF_APPEND32(m, bgn.sscop_null); 1283245431Sdim MBUF_APPEND32(m, pdu.sscop_null); 1284263509Sdim 1285245431Sdim AAL_SEND(sscop, m); 1286245431Sdim} 1287245431Sdim 1288245431Sdim/* 1289245431Sdim * Send BGREJ PDU. 1290198092Srdivacky */ 1291193326Sedstatic void 1292193326Sedsend_bgrej(struct sscop *sscop, struct SSCOP_MBUF_T *uu) 1293193326Sed{ 1294193326Sed union pdu pdu; 1295193326Sed union bgn bgn; 1296193326Sed struct SSCOP_MBUF_T *m; 1297193326Sed 1298218893Sdim pdu.sscop_null = 0; 1299218893Sdim pdu.sscop_type = PDU_BGREJ; 1300212904Sdim bgn.sscop_null = 0; 1301212904Sdim 1302193326Sed if(uu) { 1303193326Sed if((m = MBUF_DUP(uu)) == NULL) { 1304193326Sed FAILURE("sscop: cannot allocate BGREJ"); 1305193326Sed return; 1306193326Sed } 1307193326Sed pdu.sscop_pl += MBUF_PAD4(m); 1308193326Sed } else { 1309193326Sed if((m = MBUF_ALLOC(8)) == NULL) { 1310218893Sdim FAILURE("sscop: cannot allocate BGREJ"); 1311218893Sdim return; 1312218893Sdim } 1313218893Sdim } 1314218893Sdim 1315218893Sdim MBUF_APPEND32(m, bgn.sscop_null); 1316245431Sdim MBUF_APPEND32(m, pdu.sscop_null); 1317245431Sdim 1318245431Sdim AAL_SEND(sscop, m); 1319245431Sdim} 1320245431Sdim 1321245431Sdim/* 1322245431Sdim * Send BGAK PDU. 1323245431Sdim */ 1324245431Sdimstatic void 1325245431Sdimsend_bgak(struct sscop *sscop, struct SSCOP_MBUF_T *uu) 1326245431Sdim{ 1327245431Sdim union pdu pdu; 1328245431Sdim union bgn bgn; 1329245431Sdim struct SSCOP_MBUF_T *m; 1330245431Sdim 1331245431Sdim pdu.sscop_null = 0; 1332245431Sdim pdu.sscop_type = PDU_BGAK; 1333245431Sdim pdu.sscop_ns = sscop->vr_mr; 1334245431Sdim bgn.sscop_null = 0; 1335245431Sdim 1336245431Sdim if(uu) { 1337245431Sdim if((m = MBUF_DUP(uu)) == NULL) { 1338198092Srdivacky FAILURE("sscop: cannot allocate BGAK"); 1339212904Sdim return; 1340218893Sdim } 1341245431Sdim pdu.sscop_pl += MBUF_PAD4(m); 1342193326Sed } else { 1343193326Sed if((m = MBUF_ALLOC(8)) == NULL) { 1344193326Sed FAILURE("sscop: cannot allocate BGAK"); 1345193326Sed return; 1346193326Sed } 1347193326Sed } 1348193326Sed 1349193326Sed MBUF_APPEND32(m, bgn.sscop_null); 1350193326Sed MBUF_APPEND32(m, pdu.sscop_null); 1351193326Sed 1352193326Sed AAL_SEND(sscop, m); 1353193326Sed} 1354193326Sed 1355193326Sed/* 1356193326Sed * Send SD PDU. The function makes a duplicate of the message. 1357193326Sed */ 1358193326Sedstatic void 1359198092Srdivackysend_sd(struct sscop *sscop, struct SSCOP_MBUF_T *m, u_int seqno) 1360245431Sdim{ 1361212904Sdim union pdu pdu; 1362193326Sed 1363212904Sdim if((m = MBUF_DUP(m)) == NULL) { 1364193326Sed FAILURE("sscop: cannot allocate SD"); 1365198092Srdivacky return; 1366198092Srdivacky } 1367193326Sed 1368203955Srdivacky pdu.sscop_null = 0; 1369193326Sed pdu.sscop_pl = 0; 1370263509Sdim pdu.sscop_type = PDU_SD; 1371198092Srdivacky pdu.sscop_ns = seqno; 1372200583Srdivacky 1373263509Sdim pdu.sscop_pl += MBUF_PAD4(m); 1374263509Sdim 1375263509Sdim MBUF_APPEND32(m, pdu.sscop_null); 1376263509Sdim 1377263509Sdim AAL_SEND(sscop, m); 1378263509Sdim} 1379263509Sdim 1380263509Sdim/* 1381263509Sdim * Send a UD PDU. The caller must free the sscop msg part. 1382263509Sdim */ 1383263509Sdimstatic void 1384263509Sdimsend_ud(struct sscop *sscop, struct SSCOP_MBUF_T *m) 1385221345Sdim{ 1386263509Sdim union pdu pdu; 1387221345Sdim 1388263509Sdim pdu.sscop_null = 0; 1389263509Sdim pdu.sscop_type = PDU_UD; 1390263509Sdim 1391263509Sdim pdu.sscop_pl += MBUF_PAD4(m); 1392200583Srdivacky 1393218893Sdim MBUF_APPEND32(m, pdu.sscop_null); 1394199990Srdivacky 1395199990Srdivacky AAL_SEND(sscop, m); 1396193326Sed} 1397212904Sdim 1398212904Sdim/* 1399263509Sdim * Send a MD PDU. The caller must free the sscop msg part. 1400200583Srdivacky */ 1401200583Srdivackystatic void 1402212904Sdimsend_md(struct sscop *sscop, struct SSCOP_MBUF_T *m) 1403218893Sdim{ 1404200583Srdivacky union pdu pdu; 1405200583Srdivacky 1406193326Sed pdu.sscop_null = 0; 1407193326Sed pdu.sscop_type = PDU_MD; 1408198092Srdivacky 1409198092Srdivacky pdu.sscop_pl += MBUF_PAD4(m); 1410193326Sed 1411212904Sdim MBUF_APPEND32(m, pdu.sscop_null); 1412212904Sdim 1413252723Sdim AAL_SEND(sscop, m); 1414193326Sed} 1415218893Sdim 1416218893Sdim/* 1417194711Sed * Send END PDU. 1418194711Sed */ 1419194711Sedstatic void 1420193326Sedsend_end(struct sscop *sscop, int src, struct SSCOP_MBUF_T *uu) 1421212904Sdim{ 1422204643Srdivacky union pdu pdu; 1423204643Srdivacky struct SSCOP_MBUF_T *m; 1424204643Srdivacky 1425252723Sdim sscop->last_end_src = src; 1426252723Sdim 1427252723Sdim pdu.sscop_null = 0; 1428252723Sdim pdu.sscop_s = src; 1429252723Sdim pdu.sscop_type = PDU_END; 1430252723Sdim 1431252723Sdim if(uu) { 1432252723Sdim if((m = MBUF_DUP(uu)) == NULL) { 1433252723Sdim FAILURE("sscop: cannot allocate END"); 1434252723Sdim return; 1435252723Sdim } 1436252723Sdim pdu.sscop_pl += MBUF_PAD4(m); 1437252723Sdim } else { 1438252723Sdim if((m = MBUF_ALLOC(8)) == NULL) { 1439252723Sdim FAILURE("sscop: cannot allocate END"); 1440252723Sdim return; 1441212904Sdim } 1442212904Sdim } 1443218893Sdim 1444218893Sdim MBUF_APPEND32(m, 0); 1445218893Sdim MBUF_APPEND32(m, pdu.sscop_null); 1446218893Sdim 1447218893Sdim AAL_SEND(sscop, m); 1448218893Sdim} 1449193326Sed 1450218893Sdim/* 1451218893Sdim * Send USTAT PDU. List must be terminated by -1. 1452193326Sed */ 1453245431Sdimstatic void 1454245431Sdimsend_ustat(struct sscop *sscop, ...) 1455198092Srdivacky{ 1456193326Sed va_list ap; 1457193326Sed int f; 1458193326Sed u_int n; 1459193326Sed union pdu pdu; 1460193326Sed union seqno seqno; 1461193326Sed struct SSCOP_MBUF_T *m; 1462193326Sed 1463193326Sed va_start(ap, sscop); 1464193326Sed n = 0; 1465193326Sed while((f = va_arg(ap, int)) >= 0) 1466193326Sed n++; 1467193326Sed va_end(ap); 1468193326Sed 1469193326Sed if((m = MBUF_ALLOC(n * 4 + 8)) == NULL) { 1470193326Sed FAILURE("sscop: cannot allocate USTAT"); 1471193326Sed return; 1472193326Sed } 1473193326Sed 1474193326Sed va_start(ap, sscop); 1475193326Sed while((f = va_arg(ap, int)) >= 0) { 1476198092Srdivacky seqno.sscop_null = 0; 1477193326Sed seqno.sscop_n = f; 1478199482Srdivacky MBUF_APPEND32(m, seqno.sscop_null); 1479235633Sdim } 1480235633Sdim va_end(ap); 1481235633Sdim 1482193326Sed seqno.sscop_null = 0; 1483193326Sed seqno.sscop_n = sscop->vr_mr; 1484193326Sed MBUF_APPEND32(m, seqno.sscop_null); 1485235633Sdim 1486193326Sed pdu.sscop_null = 0; 1487235633Sdim pdu.sscop_type = PDU_USTAT; 1488193326Sed pdu.sscop_ns = sscop->vr_r; 1489193326Sed MBUF_APPEND32(m, pdu.sscop_null); 1490193326Sed 1491193326Sed AAL_SEND(sscop, m); 1492198092Srdivacky} 1493193326Sed 1494193326Sed/* 1495193326Sed * Send ER PDU. 1496193326Sed */ 1497235633Sdimstatic void 1498193326Sedsend_er(struct sscop *sscop) 1499245431Sdim{ 1500245431Sdim union pdu pdu; 1501245431Sdim union bgn bgn; 1502245431Sdim struct SSCOP_MBUF_T *m; 1503245431Sdim 1504245431Sdim pdu.sscop_null = 0; 1505245431Sdim pdu.sscop_type = PDU_ER; 1506245431Sdim pdu.sscop_ns = sscop->vr_mr; 1507245431Sdim 1508245431Sdim bgn.sscop_null = 0; 1509245431Sdim bgn.sscop_bgns = sscop->vt_sq; 1510245431Sdim 1511245431Sdim if((m = MBUF_ALLOC(8)) == NULL) { 1512245431Sdim FAILURE("sscop: cannot allocate ER"); 1513245431Sdim return; 1514193326Sed } 1515193326Sed MBUF_APPEND32(m, bgn.sscop_null); 1516193326Sed MBUF_APPEND32(m, pdu.sscop_null); 1517193326Sed 1518203955Srdivacky AAL_SEND(sscop, m); 1519193326Sed} 1520193326Sed 1521193326Sed/* 1522193326Sed * Send POLL PDU. 1523198092Srdivacky */ 1524193326Sedstatic void 1525193326Sedsend_poll(struct sscop *sscop) 1526193326Sed{ 1527193326Sed union pdu pdu; 1528193326Sed union seqno seqno; 1529193326Sed struct SSCOP_MBUF_T *m; 1530193326Sed 1531226890Sdim seqno.sscop_null = 0; 1532193326Sed seqno.sscop_n = sscop->vt_ps; 1533193326Sed 1534193326Sed pdu.sscop_null = 0; 1535193326Sed pdu.sscop_ns = sscop->vt_s; 1536193326Sed pdu.sscop_type = PDU_POLL; 1537263509Sdim 1538193326Sed if((m = MBUF_ALLOC(8)) == NULL) { 1539193326Sed FAILURE("sscop: cannot allocate POLL"); 1540198092Srdivacky return; 1541198092Srdivacky } 1542198092Srdivacky MBUF_APPEND32(m, seqno.sscop_null); 1543235633Sdim MBUF_APPEND32(m, pdu.sscop_null); 1544198092Srdivacky 1545204962Srdivacky AAL_SEND(sscop, m); 1546252723Sdim} 1547204962Srdivacky 1548198092Srdivacky/* 1549198092Srdivacky * Send STAT PDU. List is already in buffer. 1550252723Sdim */ 1551204962Srdivackystatic void 1552198092Srdivackysend_stat(struct sscop *sscop, u_int nps, struct SSCOP_MBUF_T *m) 1553252723Sdim{ 1554252723Sdim union pdu pdu; 1555252723Sdim union seqno seqno; 1556252723Sdim 1557252723Sdim seqno.sscop_null = 0; 1558252723Sdim seqno.sscop_n = nps; 1559203955Srdivacky MBUF_APPEND32(m, seqno.sscop_null); 1560203955Srdivacky 1561198092Srdivacky seqno.sscop_null = 0; 1562198092Srdivacky seqno.sscop_n = sscop->vr_mr; 1563198092Srdivacky MBUF_APPEND32(m, seqno.sscop_null); 1564198092Srdivacky 1565198092Srdivacky pdu.sscop_null = 0; 1566235633Sdim pdu.sscop_type = PDU_STAT; 1567198092Srdivacky pdu.sscop_ns = sscop->vr_r; 1568198092Srdivacky MBUF_APPEND32(m, pdu.sscop_null); 1569252723Sdim 1570204962Srdivacky AAL_SEND(sscop, m); 1571198092Srdivacky} 1572198092Srdivacky 1573252723Sdim/* 1574204962Srdivacky * Send ENDAK PDU. 1575198092Srdivacky */ 1576198092Srdivackystatic void 1577198092Srdivackysend_endak(struct sscop *sscop) 1578198092Srdivacky{ 1579198092Srdivacky union pdu pdu; 1580207619Srdivacky union seqno seqno; 1581212904Sdim struct SSCOP_MBUF_T *m; 1582207619Srdivacky 1583207619Srdivacky seqno.sscop_null = 0; 1584207619Srdivacky pdu.sscop_null = 0; 1585207619Srdivacky pdu.sscop_type = PDU_ENDAK; 1586207619Srdivacky 1587207619Srdivacky if((m = MBUF_ALLOC(8)) == NULL) { 1588207619Srdivacky FAILURE("sscop: cannot allocate ENDAK"); 1589207619Srdivacky return; 1590207619Srdivacky } 1591207619Srdivacky MBUF_APPEND32(m, seqno.sscop_null); 1592207619Srdivacky MBUF_APPEND32(m, pdu.sscop_null); 1593207619Srdivacky 1594207619Srdivacky AAL_SEND(sscop, m); 1595207619Srdivacky} 1596207619Srdivacky 1597207619Srdivacky/* 1598207619Srdivacky * Send ERAK PDU. 1599207619Srdivacky */ 1600212904Sdimstatic void 1601207619Srdivackysend_erak(struct sscop *sscop) 1602207619Srdivacky{ 1603208600Srdivacky union pdu pdu; 1604208600Srdivacky union seqno seqno; 1605212904Sdim struct SSCOP_MBUF_T *m; 1606212904Sdim 1607212904Sdim seqno.sscop_null = 0; 1608208600Srdivacky pdu.sscop_null = 0; 1609208600Srdivacky pdu.sscop_type = PDU_ERAK; 1610208600Srdivacky pdu.sscop_ns = sscop->vr_mr; 1611208600Srdivacky 1612208600Srdivacky if((m = MBUF_ALLOC(8)) == NULL) { 1613208600Srdivacky FAILURE("sscop: cannot allocate ERAK"); 1614208600Srdivacky return; 1615198092Srdivacky } 1616198092Srdivacky MBUF_APPEND32(m, seqno.sscop_null); 1617198092Srdivacky MBUF_APPEND32(m, pdu.sscop_null); 1618198092Srdivacky 1619198092Srdivacky AAL_SEND(sscop, m); 1620198092Srdivacky} 1621198092Srdivacky 1622198092Srdivacky/* 1623198092Srdivacky * Send RS PDU 1624198092Srdivacky */ 1625205219Srdivackystatic void 1626198092Srdivackysend_rs(struct sscop *sscop, int resend, struct SSCOP_MBUF_T *uu) 1627198092Srdivacky{ 1628207619Srdivacky union pdu pdu; 1629212904Sdim union bgn bgn; 1630198092Srdivacky struct SSCOP_MBUF_T *m; 1631198092Srdivacky 1632198092Srdivacky pdu.sscop_null = 0; 1633198092Srdivacky pdu.sscop_type = PDU_RS; 1634198092Srdivacky pdu.sscop_ns = resend ? sscop->rs_mr : sscop->vr_mr; 1635198092Srdivacky 1636198092Srdivacky bgn.sscop_null = 0; 1637198092Srdivacky bgn.sscop_bgns = resend ? sscop->rs_sq : sscop->vt_sq; 1638198092Srdivacky 1639198092Srdivacky sscop->rs_mr = pdu.sscop_ns; 1640198092Srdivacky sscop->rs_sq = bgn.sscop_bgns; 1641198092Srdivacky 1642207619Srdivacky if(uu) { 1643207619Srdivacky if((m = MBUF_DUP(uu)) == NULL) { 1644207619Srdivacky FAILURE("sscop: cannot allocate RS"); 1645207619Srdivacky return; 1646207619Srdivacky } 1647207619Srdivacky pdu.sscop_pl += MBUF_PAD4(m); 1648207619Srdivacky } else { 1649207619Srdivacky if((m = MBUF_ALLOC(8)) == NULL) { 1650207619Srdivacky FAILURE("sscop: cannot allocate RS"); 1651207619Srdivacky return; 1652207619Srdivacky } 1653203955Srdivacky } 1654207619Srdivacky 1655207619Srdivacky MBUF_APPEND32(m, bgn.sscop_null); 1656207619Srdivacky MBUF_APPEND32(m, pdu.sscop_null); 1657207619Srdivacky 1658207619Srdivacky AAL_SEND(sscop, m); 1659198092Srdivacky} 1660198092Srdivacky 1661263509Sdim/* 1662263509Sdim * Send RSAK pdu 1663263509Sdim */ 1664263509Sdimstatic void 1665263509Sdimsend_rsak(struct sscop *sscop) 1666263509Sdim{ 1667263509Sdim union pdu pdu; 1668263509Sdim union seqno seqno; 1669263509Sdim struct SSCOP_MBUF_T *m; 1670263509Sdim 1671263509Sdim seqno.sscop_null = 0; 1672263509Sdim pdu.sscop_null = 0; 1673263509Sdim pdu.sscop_type = PDU_RSAK; 1674263509Sdim pdu.sscop_ns = sscop->vr_mr; 1675263509Sdim 1676263509Sdim if((m = MBUF_ALLOC(8)) == NULL) { 1677263509Sdim FAILURE("sscop: cannot allocate RSAK"); 1678263509Sdim return; 1679263509Sdim } 1680263509Sdim 1681263509Sdim MBUF_APPEND32(m, seqno.sscop_null); 1682263509Sdim MBUF_APPEND32(m, pdu.sscop_null); 1683198092Srdivacky 1684198092Srdivacky AAL_SEND(sscop, m); 1685198092Srdivacky} 1686198092Srdivacky 1687198092Srdivacky/************************************************************/ 1688199482Srdivacky/* 1689212904Sdim * P 31; IDLE && AA-ESTABLISH-request 1690199482Srdivacky * arg is UU data (opt). 1691198092Srdivacky */ 1692205219Srdivackystatic void 1693205219Srdivackysscop_idle_establish_req(struct sscop *sscop, struct sscop_msg *uu) 1694198092Srdivacky{ 1695207619Srdivacky u_int br = uu->rexmit; 1696207619Srdivacky 1697198092Srdivacky SET_UU(uu_bgn, uu); 1698198092Srdivacky 1699198092Srdivacky m_clear_transmitter(sscop); 1700198092Srdivacky 1701198092Srdivacky sscop->clear_buffers = br; 1702198092Srdivacky 1703198092Srdivacky sscop->vt_cc = 1; 1704198092Srdivacky sscop->vt_sq++; 1705198092Srdivacky 1706198092Srdivacky m_initialize_mr(sscop); 1707198092Srdivacky 1708198092Srdivacky send_bgn(sscop, sscop->uu_bgn); 1709198092Srdivacky 1710198092Srdivacky TIMER_RESTART(sscop, cc); 1711198092Srdivacky 1712198092Srdivacky sscop_set_state(sscop, SSCOP_OUT_PEND); 1713198092Srdivacky} 1714198092Srdivacky 1715198092Srdivacky/* 1716198092Srdivacky * P 31: IDLE && BGN PDU 1717198092Srdivacky * arg is the received PDU (freed). 1718198092Srdivacky */ 1719198092Srdivackystatic void 1720198092Srdivackysscop_idle_bgn(struct sscop *sscop, struct sscop_msg *msg) 1721198092Srdivacky{ 1722198092Srdivacky union pdu pdu; 1723198092Srdivacky union bgn bgn; 1724198092Srdivacky 1725198092Srdivacky pdu.sscop_null = MBUF_STRIP32(msg->m); 1726198092Srdivacky 1727198092Srdivacky if(sscop->robustness) { 1728198092Srdivacky bgn.sscop_null = MBUF_STRIP32(msg->m); 1729198092Srdivacky sscop->vr_sq = bgn.sscop_bgns; 1730198092Srdivacky } else { 1731193326Sed if(m_detect_retransmission(sscop, msg)) { 1732193326Sed send_bgrej(sscop, sscop->uu_bgrej); 1733193326Sed SSCOP_MSG_FREE(msg); 1734193326Sed return; 1735210299Sed } 1736226890Sdim (void)MBUF_STRIP32(msg->m); 1737226890Sdim } 1738226890Sdim 1739226890Sdim sscop->vt_ms = pdu.sscop_ns; 1740210299Sed sscop_set_state(sscop, SSCOP_IN_PEND); 1741212904Sdim 1742210299Sed AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0); 1743210299Sed} 1744226890Sdim 1745210299Sed/* 1746210299Sed * p 31: IDLE && ENDAK PDU 1747245431Sdim * p 34: OUT_PEND && ENDAK PDU 1748263509Sdim * p 34: OUT_PEND && SD PDU 1749245431Sdim * p 34: OUT_PEND && ERAK PDU 1750245431Sdim * p 34: OUT_PEND && END PDU 1751245431Sdim * p 34: OUT_PEND && STAT PDU 1752263509Sdim * p 34: OUT_PEND && USTAT PDU 1753263509Sdim * p 34: OUT_PEND && POLL PDU 1754263509Sdim * p 36: OUT_PEND && RS PDU 1755245431Sdim * p 36: OUT_PEND && RSAK PDU 1756263509Sdim * p 40: OUTGOING_DISCONNECT_PENDING && SD PDU 1757245431Sdim * p 40: OUTGOING_DISCONNECT_PENDING && BGAK PDU 1758263509Sdim * p 40: OUTGOING_DISCONNECT_PENDING && POLL PDU 1759263509Sdim * p 40: OUTGOING_DISCONNECT_PENDING && STAT PDU 1760263509Sdim * p 40: OUTGOING_DISCONNECT_PENDING && USTAT PDU 1761263509Sdim * p 41: OUTGOING_DISCONNECT_PENDING && ERAK PDU 1762263509Sdim * p 42: OUTGOING_DISCONNECT_PENDING && ER PDU 1763263509Sdim * p 42: OUTGOING_DISCONNECT_PENDING && RS PDU 1764263509Sdim * p 42: OUTGOING_DISCONNECT_PENDING && RSAK PDU 1765263509Sdim * p 43: OUTGOING_RESYNC && ER PDU 1766263509Sdim * p 43: OUTGOING_RESYNC && POLL PDU 1767263509Sdim * p 44: OUTGOING_RESYNC && STAT PDU 1768263509Sdim * p 44: OUTGOING_RESYNC && USTAT PDU 1769263509Sdim * p 45: OUTGOING_RESYNC && BGAK PDU 1770263509Sdim * p 45: OUTGOING_RESYNC && SD PDU 1771245431Sdim * p 45: OUTGOING_RESYNC && ERAK PDU 1772245431Sdim * P 60: READY && BGAK PDU 1773263509Sdim * P 60: READY && ERAK PDU 1774263509Sdim * arg is pdu (freed). 1775263509Sdim */ 1776245431Sdimstatic void 1777263509Sdimsscop_ignore_pdu(struct sscop *sscop __unused, struct sscop_msg *msg) 1778263509Sdim{ 1779263509Sdim SSCOP_MSG_FREE(msg); 1780245431Sdim} 1781263509Sdim 1782263509Sdim/* 1783263509Sdim * p 31: IDLE && END PDU 1784245431Sdim * arg is pdu (freed). 1785263509Sdim */ 1786263509Sdimstatic void 1787245431Sdimsscop_idle_end(struct sscop *sscop, struct sscop_msg *msg) 1788218893Sdim{ 1789263509Sdim SSCOP_MSG_FREE(msg); 1790263509Sdim send_endak(sscop); 1791263509Sdim} 1792263509Sdim 1793263509Sdim/* 1794263509Sdim * p 31: IDLE && ER PDU 1795263509Sdim * arg is pdu (freed). 1796263509Sdim */ 1797263509Sdimstatic void 1798263509Sdimsscop_idle_er(struct sscop *sscop, struct sscop_msg *msg) 1799263509Sdim{ 1800263509Sdim SSCOP_MSG_FREE(msg); 1801263509Sdim MAAL_ERROR(sscop, 'L', 0); 1802263509Sdim FREE_UU(uu_end); 1803218893Sdim send_end(sscop, 1, NULL); 1804263509Sdim} 1805218893Sdim 1806245431Sdim/* 1807245431Sdim * p 31: IDLE && BGREJ PDU 1808245431Sdim * arg is pdu (freed). 1809245431Sdim */ 1810245431Sdimstatic void 1811218893Sdimsscop_idle_bgrej(struct sscop *sscop, struct sscop_msg *msg) 1812245431Sdim{ 1813245431Sdim SSCOP_MSG_FREE(msg); 1814218893Sdim MAAL_ERROR(sscop, 'D', 0); 1815218893Sdim FREE_UU(uu_end); 1816218893Sdim} 1817245431Sdim 1818218893Sdim/* 1819245431Sdim * p 32: IDLE && POLL PDU 1820218893Sdim * arg is pdu (freed). 1821218893Sdim */ 1822263509Sdimstatic void 1823263509Sdimsscop_idle_poll(struct sscop *sscop, struct sscop_msg *msg) 1824218893Sdim{ 1825218893Sdim SSCOP_MSG_FREE(msg); 1826218893Sdim MAAL_ERROR(sscop, 'G', 0); 1827263509Sdim FREE_UU(uu_end); 1828263509Sdim send_end(sscop, 1, NULL); 1829218893Sdim} 1830218893Sdim 1831218893Sdim/* 1832218893Sdim * p 32: IDLE && SD PDU 1833245431Sdim * arg is pdu (freed). 1834245431Sdim */ 1835245431Sdimstatic void 1836245431Sdimsscop_idle_sd(struct sscop *sscop, struct sscop_msg *msg) 1837245431Sdim{ 1838245431Sdim SSCOP_MSG_FREE(msg); 1839245431Sdim MAAL_ERROR(sscop, 'A', 0); 1840245431Sdim FREE_UU(uu_end); 1841245431Sdim send_end(sscop, 1, NULL); 1842245431Sdim} 1843252723Sdim 1844252723Sdim/* 1845252723Sdim * p 32: IDLE && BGAK PDU 1846252723Sdim * arg is pdu (freed). 1847252723Sdim */ 1848252723Sdimstatic void 1849252723Sdimsscop_idle_bgak(struct sscop *sscop, struct sscop_msg *msg) 1850193326Sed{ 1851193326Sed SSCOP_MSG_FREE(msg); 1852223017Sdim MAAL_ERROR(sscop, 'C', 0); 1853245431Sdim FREE_UU(uu_end); 1854245431Sdim send_end(sscop, 1, NULL); 1855252723Sdim} 1856193326Sed 1857198092Srdivacky/* 1858226890Sdim * p 32: IDLE && ERAK PDU 1859245431Sdim * arg is pdu (freed). 1860193326Sed */ 1861212904Sdimstatic void 1862212904Sdimsscop_idle_erak(struct sscop *sscop, struct sscop_msg *msg) 1863212904Sdim{ 1864218893Sdim SSCOP_MSG_FREE(msg); 1865218893Sdim MAAL_ERROR(sscop, 'M', 0); 1866218893Sdim FREE_UU(uu_end); 1867235633Sdim send_end(sscop, 1, NULL); 1868218893Sdim} 1869193326Sed 1870193326Sed/* 1871210299Sed * p 32: IDLE && STAT PDU 1872198092Srdivacky * arg is pdu (freed). 1873198092Srdivacky */ 1874224145Sdimstatic void 1875210299Sedsscop_idle_stat(struct sscop *sscop, struct sscop_msg *msg) 1876245431Sdim{ 1877245431Sdim SSCOP_MSG_FREE(msg); 1878245431Sdim MAAL_ERROR(sscop, 'H', 0); 1879245431Sdim FREE_UU(uu_end); 1880245431Sdim send_end(sscop, 1, NULL); 1881245431Sdim} 1882245431Sdim 1883245431Sdim/* 1884245431Sdim * p 32: IDLE && USTAT PDU 1885245431Sdim * arg is pdu (freed). 1886245431Sdim */ 1887245431Sdimstatic void 1888245431Sdimsscop_idle_ustat(struct sscop *sscop, struct sscop_msg *msg) 1889245431Sdim{ 1890245431Sdim SSCOP_MSG_FREE(msg); 1891245431Sdim MAAL_ERROR(sscop, 'I', 0); 1892245431Sdim FREE_UU(uu_end); 1893245431Sdim send_end(sscop, 1, NULL); 1894245431Sdim} 1895245431Sdim 1896245431Sdim/* 1897245431Sdim * p 33: IDLE & RS PDU 1898245431Sdim * arg is pdu (freed). 1899245431Sdim */ 1900245431Sdimstatic void 1901245431Sdimsscop_idle_rs(struct sscop *sscop, struct sscop_msg *msg) 1902245431Sdim{ 1903245431Sdim SSCOP_MSG_FREE(msg); 1904245431Sdim MAAL_ERROR(sscop, 'J', 0); 1905245431Sdim FREE_UU(uu_end); 1906245431Sdim send_end(sscop, 1, NULL); 1907245431Sdim} 1908245431Sdim 1909245431Sdim/* 1910245431Sdim * p 33: IDLE & RSAK PDU 1911245431Sdim * arg is pdu (freed). 1912245431Sdim */ 1913245431Sdimstatic void 1914245431Sdimsscop_idle_rsak(struct sscop *sscop, struct sscop_msg *msg) 1915245431Sdim{ 1916245431Sdim SSCOP_MSG_FREE(msg); 1917245431Sdim MAAL_ERROR(sscop, 'K', 0); 1918245431Sdim FREE_UU(uu_end); 1919245431Sdim send_end(sscop, 1, NULL); 1920193326Sed} 1921193326Sed 1922193326Sed/* 1923193326Sed * p 33: IDLE && PDU_Q 1924193326Sed * p XX: OUTPEND && PDU_Q 1925193326Sed * p 39: IN_PEND && PDU_Q 1926252723Sdim * p 45: OUT_RESYNC_PEND && PDU_Q 1927252723Sdim * p 48: IN_RESYNC_PEND && PDU_Q 1928252723Sdim * no arg 1929252723Sdim */ 1930252723Sdimstatic void 1931252723Sdimsscop_flush_pduq(struct sscop *sscop __unused, struct sscop_msg *unused __unused) 1932252723Sdim{ 1933198092Srdivacky#if 0 1934252723Sdim MSGQ_CLEAR(&sscop->xq); 1935252723Sdim#endif 1936193326Sed} 1937252723Sdim 1938252723Sdim/* 1939252723Sdim * p 34: OUT_PEND && BGAK PDU 1940252723Sdim * arg is pdu (freed). 1941252723Sdim */ 1942252723Sdimstatic void 1943252723Sdimsscop_outpend_bgak(struct sscop *sscop, struct sscop_msg *msg) 1944193326Sed{ 1945193326Sed union pdu pdu; 1946193326Sed 1947193326Sed pdu.sscop_null = MBUF_STRIP32(msg->m); 1948193326Sed (void)MBUF_STRIP32(msg->m); 1949193326Sed 1950252723Sdim TIMER_STOP(sscop, cc); 1951252723Sdim sscop->vt_ms = pdu.sscop_ns; 1952252723Sdim 1953252723Sdim AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_confirm, msg, pdu.sscop_pl, 0); 1954252723Sdim 1955252723Sdim m_initialize_state(sscop); 1956252723Sdim m_set_data_xfer_timers(sscop); 1957252723Sdim 1958252723Sdim sscop_set_state(sscop, SSCOP_READY); 1959252723Sdim} 1960252723Sdim 1961252723Sdim/* 1962252723Sdim * P 34: OUT_PEND && BGREJ PDU 1963252723Sdim */ 1964252723Sdimstatic void 1965252723Sdimsscop_outpend_bgrej(struct sscop *sscop, struct sscop_msg *msg) 1966252723Sdim{ 1967252723Sdim union pdu pdu; 1968252723Sdim 1969252723Sdim pdu.sscop_null = MBUF_STRIP32(msg->m); 1970252723Sdim (void)MBUF_STRIP32(msg->m); 1971252723Sdim 1972252723Sdim TIMER_STOP(sscop, cc); 1973252723Sdim 1974252723Sdim AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication, msg, pdu.sscop_pl, 0); 1975252723Sdim 1976252723Sdim sscop_set_state(sscop, SSCOP_IDLE); 1977252723Sdim} 1978252723Sdim 1979252723Sdim/* 1980193326Sed * P 35: OUT_PEND && TIMER_CC expiry 1981218893Sdim * no arg 1982226890Sdim */ 1983226890Sdimstatic void 1984245431Sdimsscop_outpend_tcc(struct sscop *sscop, struct sscop_msg *unused __unused) 1985226890Sdim{ 1986226890Sdim if(sscop->vt_cc >= sscop->maxcc) { 1987226890Sdim MAAL_ERROR(sscop, 'O', 0); 1988226890Sdim FREE_UU(uu_end); 1989245431Sdim send_end(sscop, 1, NULL); 1990226890Sdim 1991226890Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 1992226890Sdim 1993226890Sdim sscop_set_state(sscop, SSCOP_IDLE); 1994226890Sdim } else { 1995245431Sdim sscop->vt_cc++; 1996226890Sdim send_bgn(sscop, sscop->uu_bgn); 1997226890Sdim TIMER_RESTART(sscop, cc); 1998226890Sdim } 1999226890Sdim} 2000226890Sdim 2001226890Sdim/* 2002226890Sdim * P 35: OUT_PEND && RELEASE_REQ 2003226890Sdim * arg is UU 2004226890Sdim */ 2005226890Sdimstatic void 2006226890Sdimsscop_outpend_release_req(struct sscop *sscop, struct sscop_msg *uu) 2007226890Sdim{ 2008226890Sdim SET_UU(uu_end, uu); 2009226890Sdim 2010226890Sdim TIMER_STOP(sscop, cc); 2011226890Sdim sscop->vt_cc = 1; 2012226890Sdim send_end(sscop, 0, sscop->uu_end); 2013218893Sdim TIMER_RESTART(sscop, cc); 2014218893Sdim 2015218893Sdim sscop_set_state(sscop, SSCOP_OUT_DIS_PEND); 2016218893Sdim} 2017218893Sdim 2018218893Sdim/* 2019218893Sdim * P 36: OUT_PEND && BGN PDU 2020235633Sdim * arg is the received PDU (freed). 2021235633Sdim */ 2022218893Sdimstatic void 2023218893Sdimsscop_outpend_bgn(struct sscop *sscop, struct sscop_msg *msg) 2024218893Sdim{ 2025235633Sdim union pdu pdu; 2026218893Sdim 2027218893Sdim pdu.sscop_null = MBUF_STRIP32(msg->m); 2028226890Sdim 2029252723Sdim if(m_detect_retransmission(sscop, msg)) { 2030252723Sdim SSCOP_MSG_FREE(msg); 2031252723Sdim return; 2032252723Sdim } 2033252723Sdim (void)MBUF_STRIP32(msg->m); 2034263509Sdim 2035263509Sdim TIMER_STOP(sscop, cc); 2036252723Sdim 2037252723Sdim sscop->vt_ms = pdu.sscop_ns; 2038252723Sdim 2039252723Sdim m_initialize_mr(sscop); 2040263509Sdim 2041252723Sdim send_bgak(sscop, sscop->uu_bgak); 2042193326Sed 2043252723Sdim AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_confirm, msg, pdu.sscop_pl, 0); 2044223017Sdim 2045245431Sdim m_initialize_state(sscop); 2046263509Sdim 2047212904Sdim m_set_data_xfer_timers(sscop); 2048193326Sed 2049193326Sed sscop_set_state(sscop, SSCOP_READY); 2050193326Sed} 2051193326Sed 2052193326Sed/* 2053193326Sed * p 37: IN_PEND && AA-ESTABLISH.response 2054193326Sed * arg is UU 2055193326Sed */ 2056193326Sedstatic void 2057193326Sedsscop_inpend_establish_resp(struct sscop *sscop, struct sscop_msg *uu) 2058193326Sed{ 2059193326Sed u_int br = uu->rexmit; 2060193326Sed 2061193326Sed SET_UU(uu_bgak, uu); 2062193326Sed 2063193326Sed m_clear_transmitter(sscop); 2064193326Sed sscop->clear_buffers = br; 2065193326Sed m_initialize_mr(sscop); 2066198092Srdivacky send_bgak(sscop, sscop->uu_bgak); 2067193326Sed m_initialize_state(sscop); 2068193326Sed m_set_data_xfer_timers(sscop); 2069198092Srdivacky 2070193326Sed sscop_set_state(sscop, SSCOP_READY); 2071193326Sed} 2072193326Sed 2073193326Sed/* 2074193326Sed * p 37: IN_PEND && AA-RELEASE.request 2075198092Srdivacky * arg is uu. 2076263509Sdim */ 2077263509Sdimstatic void 2078198092Srdivackysscop_inpend_release_req(struct sscop *sscop, struct sscop_msg *uu) 2079198092Srdivacky{ 2080263509Sdim SET_UU(uu_bgrej, uu); 2081263509Sdim 2082193326Sed send_bgrej(sscop, sscop->uu_bgrej); 2083193326Sed 2084245431Sdim sscop_set_state(sscop, SSCOP_IDLE); 2085245431Sdim} 2086245431Sdim 2087263509Sdim/* 2088263509Sdim * p 37: IN_PEND && BGN PDU 2089218893Sdim * arg is pdu. (freed) 2090221345Sdim */ 2091221345Sdimstatic void 2092221345Sdimsscop_inpend_bgn(struct sscop *sscop, struct sscop_msg *msg) 2093221345Sdim{ 2094221345Sdim union pdu pdu; 2095245431Sdim 2096218893Sdim pdu.sscop_null = MBUF_STRIP32(msg->m); 2097218893Sdim 2098193326Sed if(m_detect_retransmission(sscop, msg)) { 2099193326Sed SSCOP_MSG_FREE(msg); 2100245431Sdim return; 2101245431Sdim } 2102245431Sdim (void)MBUF_STRIP32(msg->m); 2103245431Sdim 2104245431Sdim sscop->vt_ms = pdu.sscop_ns; 2105245431Sdim 2106245431Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0); 2107245431Sdim AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0); 2108245431Sdim} 2109245431Sdim 2110245431Sdim/* 2111245431Sdim * p 37: IN_PEND && ER PDU 2112245431Sdim * arg is pdu (freed). 2113245431Sdim */ 2114245431Sdimstatic void 2115245431Sdimsscop_inpend_er(struct sscop *sscop, struct sscop_msg *msg) 2116245431Sdim{ 2117245431Sdim MAAL_ERROR(sscop, 'L', 0); 2118212904Sdim SSCOP_MSG_FREE(msg); 2119193326Sed} 2120193326Sed 2121245431Sdim/* 2122245431Sdim * p 37: IN_PEND && ENDAK PDU 2123245431Sdim * arg is pdu (freed). 2124245431Sdim */ 2125263509Sdimstatic void 2126263509Sdimsscop_inpend_endak(struct sscop *sscop, struct sscop_msg *msg) 2127263509Sdim{ 2128263509Sdim MAAL_ERROR(sscop, 'F', 0); 2129263509Sdim 2130245431Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2131245431Sdim 2132263509Sdim sscop_set_state(sscop, SSCOP_IDLE); 2133263509Sdim 2134263509Sdim SSCOP_MSG_FREE(msg); 2135263509Sdim} 2136263509Sdim 2137245431Sdim/* 2138263509Sdim * p 38: IN_PEND && BGAK PDU 2139263509Sdim * arg is pdu (freed). 2140263509Sdim */ 2141245431Sdimstatic void 2142263509Sdimsscop_inpend_bgak(struct sscop *sscop, struct sscop_msg *msg) 2143263509Sdim{ 2144263509Sdim MAAL_ERROR(sscop, 'C', 0); 2145245431Sdim 2146263509Sdim SSCOP_MSG_FREE(msg); 2147263509Sdim} 2148263509Sdim 2149245431Sdim/* 2150263509Sdim * p 38: IN_PEND && BGREJ PDU 2151252723Sdim * arg is pdu (freed). 2152252723Sdim */ 2153263509Sdimstatic void 2154263509Sdimsscop_inpend_bgrej(struct sscop *sscop, struct sscop_msg *msg) 2155263509Sdim{ 2156252723Sdim MAAL_ERROR(sscop, 'D', 0); 2157263509Sdim 2158263509Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2159252723Sdim 2160263509Sdim SSCOP_MSG_FREE(msg); 2161263509Sdim 2162252723Sdim sscop_set_state(sscop, SSCOP_IDLE); 2163263509Sdim} 2164252723Sdim 2165263509Sdim/* 2166263509Sdim * p 38: IN_PEND && SD PDU 2167245431Sdim * arg is pdu (freed). 2168263509Sdim */ 2169263509Sdimstatic void 2170263509Sdimsscop_inpend_sd(struct sscop *sscop, struct sscop_msg *msg) 2171263509Sdim{ 2172252723Sdim MAAL_ERROR(sscop, 'A', 0); 2173263509Sdim 2174263509Sdim SSCOP_MSG_FREE(msg); 2175263509Sdim 2176263509Sdim FREE_UU(uu_end); 2177263509Sdim send_end(sscop, 1, NULL); 2178263509Sdim 2179263509Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2180263509Sdim 2181263509Sdim sscop_set_state(sscop, SSCOP_IDLE); 2182263509Sdim} 2183263509Sdim 2184263509Sdim/* 2185263509Sdim * p 38: IN_PEND && USTAT PDU 2186263509Sdim * arg is pdu (freed). 2187263509Sdim */ 2188263509Sdimstatic void 2189263509Sdimsscop_inpend_ustat(struct sscop *sscop, struct sscop_msg *msg) 2190263509Sdim{ 2191245431Sdim MAAL_ERROR(sscop, 'I', 0); 2192245431Sdim 2193245431Sdim SSCOP_MSG_FREE(msg); 2194245431Sdim 2195245431Sdim FREE_UU(uu_end); 2196245431Sdim send_end(sscop, 1, NULL); 2197245431Sdim 2198245431Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2199245431Sdim 2200245431Sdim sscop_set_state(sscop, SSCOP_IDLE); 2201245431Sdim} 2202245431Sdim 2203245431Sdim/* 2204245431Sdim * p 38: IN_PEND && STAT PDU 2205245431Sdim * arg is pdu (freed). 2206245431Sdim */ 2207245431Sdimstatic void 2208245431Sdimsscop_inpend_stat(struct sscop *sscop, struct sscop_msg *msg) 2209245431Sdim{ 2210245431Sdim MAAL_ERROR(sscop, 'H', 0); 2211245431Sdim 2212245431Sdim SSCOP_MSG_FREE(msg); 2213245431Sdim 2214245431Sdim FREE_UU(uu_end); 2215245431Sdim send_end(sscop, 1, NULL); 2216245431Sdim 2217245431Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2218245431Sdim 2219245431Sdim sscop_set_state(sscop, SSCOP_IDLE); 2220245431Sdim} 2221263509Sdim 2222263509Sdim/* 2223263509Sdim * p 38: IN_PEND && POLL PDU 2224263509Sdim * arg is pdu (freed). 2225263509Sdim */ 2226263509Sdimstatic void 2227263509Sdimsscop_inpend_poll(struct sscop *sscop, struct sscop_msg *msg) 2228245431Sdim{ 2229245431Sdim MAAL_ERROR(sscop, 'G', 0); 2230245431Sdim 2231245431Sdim SSCOP_MSG_FREE(msg); 2232245431Sdim 2233245431Sdim FREE_UU(uu_end); 2234245431Sdim send_end(sscop, 1, NULL); 2235263509Sdim 2236263509Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2237263509Sdim 2238263509Sdim sscop_set_state(sscop, SSCOP_IDLE); 2239263509Sdim} 2240263509Sdim 2241263509Sdim/* 2242263509Sdim * p 39: IN_PEND && ERAK PDU 2243263509Sdim * arg is pdu (freed). 2244263509Sdim */ 2245245431Sdimstatic void 2246245431Sdimsscop_inpend_erak(struct sscop *sscop, struct sscop_msg *msg) 2247245431Sdim{ 2248245431Sdim SSCOP_MSG_FREE(msg); 2249245431Sdim MAAL_ERROR(sscop, 'M', 0); 2250245431Sdim} 2251245431Sdim 2252263509Sdim/* 2253263509Sdim * p 39: IN_PEND & RS PDU 2254263509Sdim * arg is pdu (freed). 2255263509Sdim */ 2256263509Sdimstatic void 2257263509Sdimsscop_inpend_rs(struct sscop *sscop, struct sscop_msg *msg) 2258263509Sdim{ 2259263509Sdim SSCOP_MSG_FREE(msg); 2260263509Sdim MAAL_ERROR(sscop, 'J', 0); 2261263509Sdim} 2262263509Sdim 2263263509Sdim/* 2264245431Sdim * p 39: IN_PEND & RSAK PDU 2265263509Sdim * arg is pdu (freed). 2266263509Sdim */ 2267263509Sdimstatic void 2268263509Sdimsscop_inpend_rsak(struct sscop *sscop, struct sscop_msg *msg) 2269263509Sdim{ 2270263509Sdim SSCOP_MSG_FREE(msg); 2271263509Sdim MAAL_ERROR(sscop, 'K', 0); 2272263509Sdim} 2273263509Sdim 2274263509Sdim/* 2275263509Sdim * p 39: IN_PEND && END PDU 2276263509Sdim * arg is pdu (freed). 2277263509Sdim * no uui 2278263509Sdim */ 2279263509Sdimstatic void 2280263509Sdimsscop_inpend_end(struct sscop *sscop, struct sscop_msg *msg) 2281263509Sdim{ 2282263509Sdim union pdu pdu; 2283245431Sdim 2284263509Sdim pdu.sscop_null = MBUF_STRIP32(msg->m); 2285263509Sdim (void)MBUF_STRIP32(msg->m); 2286263509Sdim 2287263509Sdim send_endak(sscop); 2288263509Sdim 2289263509Sdim AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication, 2290263509Sdim msg, pdu.sscop_pl, (u_int)pdu.sscop_s); 2291263509Sdim 2292263509Sdim sscop_set_state(sscop, SSCOP_IDLE); 2293263509Sdim} 2294263509Sdim 2295263509Sdim/* 2296263509Sdim * p 40: OUT_DIS_PEND && SSCOP_ESTABLISH_request 2297263509Sdim * no arg. 2298263509Sdim * no uui. 2299263509Sdim */ 2300263509Sdimstatic void 2301263509Sdimsscop_outdis_establish_req(struct sscop *sscop, struct sscop_msg *uu) 2302263509Sdim{ 2303263509Sdim SET_UU(uu_bgn, uu); 2304263509Sdim 2305263509Sdim TIMER_STOP(sscop, cc); 2306263509Sdim m_clear_transmitter(sscop); 2307263509Sdim sscop->clear_buffers = 1; 2308263509Sdim sscop->vt_cc = 1; 2309263509Sdim sscop->vt_sq++; 2310263509Sdim m_initialize_mr(sscop); 2311263509Sdim send_bgn(sscop, sscop->uu_bgn); 2312263509Sdim TIMER_RESTART(sscop, cc); 2313263509Sdim 2314263509Sdim sscop_set_state(sscop, SSCOP_OUT_PEND); 2315263509Sdim} 2316263509Sdim 2317263509Sdim/* 2318263509Sdim * p 41: OUT_DIS_PEND && END PDU 2319263509Sdim * arg is pdu (freed). 2320263509Sdim */ 2321263509Sdimstatic void 2322263509Sdimsscop_outdis_end(struct sscop *sscop, struct sscop_msg *msg) 2323263509Sdim{ 2324263509Sdim union pdu pdu; 2325263509Sdim 2326263509Sdim pdu.sscop_null = MBUF_STRIP32(msg->m); 2327263509Sdim (void)MBUF_STRIP32(msg->m); 2328263509Sdim 2329263509Sdim TIMER_STOP(sscop, cc); 2330263509Sdim send_endak(sscop); 2331263509Sdim 2332245431Sdim AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_confirm, msg, pdu.sscop_pl, 0); 2333245431Sdim 2334223017Sdim sscop_set_state(sscop, SSCOP_IDLE); 2335226890Sdim} 2336226890Sdim 2337226890Sdim/* 2338223017Sdim * p 41: OUT_DIS_PEND && ENDAK PDU 2339245431Sdim * p 41: OUT_DIS_PEND && BGREJ PDU 2340223017Sdim * arg is pdu (freed) 2341223017Sdim */ 2342245431Sdimstatic void 2343245431Sdimsscop_outdis_endak(struct sscop *sscop, struct sscop_msg *msg) 2344223017Sdim{ 2345223017Sdim union pdu pdu; 2346223017Sdim 2347223017Sdim pdu.sscop_null = MBUF_STRIP32(msg->m); 2348223017Sdim (void)MBUF_STRIP32(msg->m); 2349223017Sdim 2350223017Sdim TIMER_STOP(sscop, cc); 2351235633Sdim 2352235633Sdim AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_confirm, msg, pdu.sscop_pl, 0); 2353235633Sdim 2354235633Sdim sscop_set_state(sscop, SSCOP_IDLE); 2355235633Sdim} 2356235633Sdim 2357223017Sdim/* 2358252723Sdim * p 41: OUT_DIS_PEND && TIMER CC expiry 2359235633Sdim * no arg 2360245431Sdim */ 2361235633Sdimstatic void 2362245431Sdimsscop_outdis_cc(struct sscop *sscop, struct sscop_msg *unused __unused) 2363252723Sdim{ 2364252723Sdim if(sscop->vt_cc >= sscop->maxcc) { 2365223017Sdim MAAL_ERROR(sscop, 'O', 0); 2366223017Sdim AAL_SIG(sscop, SSCOP_RELEASE_confirm); 2367223017Sdim sscop_set_state(sscop, SSCOP_IDLE); 2368223017Sdim } else { 2369223017Sdim sscop->vt_cc++; 2370223017Sdim send_end(sscop, sscop->last_end_src, sscop->uu_end); 2371252723Sdim TIMER_RESTART(sscop, cc); 2372223017Sdim } 2373223017Sdim} 2374252723Sdim 2375223017Sdim/* 2376223017Sdim * p 42: OUT_DIS_PEND && BGN PDU 2377223017Sdim * arg is pdu (freed). 2378223017Sdim */ 2379223017Sdimstatic void 2380223017Sdimsscop_outdis_bgn(struct sscop *sscop, struct sscop_msg *msg) 2381223017Sdim{ 2382223017Sdim union pdu pdu; 2383223017Sdim 2384223017Sdim pdu.sscop_null = MBUF_STRIP32(msg->m); 2385201361Srdivacky 2386201361Srdivacky if(m_detect_retransmission(sscop, msg)) { 2387201361Srdivacky FREE_UU(uu_bgak); 2388201361Srdivacky send_bgak(sscop, NULL); 2389201361Srdivacky send_end(sscop, sscop->last_end_src, sscop->uu_end); 2390201361Srdivacky SSCOP_MSG_FREE(msg); 2391201361Srdivacky 2392201361Srdivacky } else { 2393201361Srdivacky (void)MBUF_STRIP32(msg->m); 2394201361Srdivacky 2395201361Srdivacky TIMER_STOP(sscop, cc); 2396201361Srdivacky sscop->vt_ms = pdu.sscop_ns; 2397201361Srdivacky AAL_SIG(sscop, SSCOP_RELEASE_confirm); 2398201361Srdivacky AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, 2399201361Srdivacky msg, pdu.sscop_pl, 0); 2400201361Srdivacky sscop_set_state(sscop, SSCOP_IN_PEND); 2401201361Srdivacky } 2402201361Srdivacky} 2403201361Srdivacky 2404201361Srdivacky/* 2405201361Srdivacky * p 43: OUT_RESYNC_PEND && BGN PDU 2406201361Srdivacky * arg is pdu (freed). 2407201361Srdivacky */ 2408201361Srdivackystatic void 2409201361Srdivackysscop_outsync_bgn(struct sscop *sscop, struct sscop_msg *msg) 2410201361Srdivacky{ 2411201361Srdivacky union pdu pdu; 2412201361Srdivacky 2413201361Srdivacky pdu.sscop_null = MBUF_STRIP32(msg->m); 2414201361Srdivacky 2415201361Srdivacky if(m_detect_retransmission(sscop, msg)) { 2416201361Srdivacky send_bgak(sscop, sscop->uu_bgak); 2417201361Srdivacky send_rs(sscop, 1, sscop->uu_rs); 2418201361Srdivacky SSCOP_MSG_FREE(msg); 2419201361Srdivacky } else { 2420201361Srdivacky (void)MBUF_STRIP32(msg->m); 2421201361Srdivacky 2422201361Srdivacky TIMER_STOP(sscop, cc); 2423201361Srdivacky sscop->vt_ms = pdu.sscop_ns; 2424201361Srdivacky AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0); 2425201361Srdivacky AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, 2426201361Srdivacky msg, pdu.sscop_pl, 0); 2427201361Srdivacky sscop_set_state(sscop, SSCOP_IN_PEND); 2428201361Srdivacky } 2429201361Srdivacky} 2430226890Sdim 2431212904Sdim/* 2432212904Sdim * p 43: OUT_RESYNC_PEND && ENDAK PDU 2433193326Sed * arg is pdu (freed). 2434207619Srdivacky */ 2435193326Sedstatic void 2436212904Sdimsscop_outsync_endak(struct sscop *sscop, struct sscop_msg *msg) 2437235633Sdim{ 2438193326Sed SSCOP_MSG_FREE(msg); 2439226890Sdim TIMER_STOP(sscop, cc); 2440226890Sdim MAAL_ERROR(sscop, 'F', 0); 2441226890Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2442235633Sdim sscop_set_state(sscop, SSCOP_IDLE); 2443235633Sdim} 2444226890Sdim 2445226890Sdim/* 2446226890Sdim * p 43: OUT_RESYNC_PEND && BGREJ PDU 2447226890Sdim * arg is pdu (freed). 2448226890Sdim */ 2449226890Sdimstatic void 2450226890Sdimsscop_outsync_bgrej(struct sscop *sscop, struct sscop_msg *msg) 2451226890Sdim{ 2452226890Sdim SSCOP_MSG_FREE(msg); 2453235633Sdim TIMER_STOP(sscop, cc); 2454226890Sdim MAAL_ERROR(sscop, 'D', 0); 2455193326Sed AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2456263509Sdim sscop_set_state(sscop, SSCOP_IDLE); 2457218893Sdim} 2458218893Sdim 2459245431Sdim/* 2460263509Sdim * p 43: OUT_RESYNC_PEND && END PDU 2461226890Sdim * arg is pdu (freed). 2462235633Sdim * no UU-data 2463226890Sdim */ 2464226890Sdimstatic void 2465235633Sdimsscop_outsync_end(struct sscop *sscop, struct sscop_msg *msg) 2466235633Sdim{ 2467235633Sdim union pdu pdu; 2468235633Sdim 2469235633Sdim pdu.sscop_null = MBUF_STRIP32(msg->m); 2470263509Sdim (void)MBUF_STRIP32(msg->m); 2471235633Sdim 2472235633Sdim TIMER_STOP(sscop, cc); 2473235633Sdim send_endak(sscop); 2474263509Sdim AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication, msg, pdu.sscop_pl, 2475235633Sdim (u_int)pdu.sscop_s); 2476235633Sdim sscop_set_state(sscop, SSCOP_IDLE); 2477235633Sdim} 2478263509Sdim 2479235633Sdim/* 2480235633Sdim * p 44: OUT_RESYNC && TIMER CC expiry 2481235633Sdim */ 2482235633Sdimstatic void 2483263509Sdimsscop_outsync_cc(struct sscop *sscop, struct sscop_msg *msg __unused) 2484235633Sdim{ 2485235633Sdim if(sscop->vt_cc == sscop->maxcc) { 2486235633Sdim MAAL_ERROR(sscop, 'O', 0); 2487235633Sdim FREE_UU(uu_end); 2488235633Sdim send_end(sscop, 1, NULL); 2489226890Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2490226890Sdim sscop_set_state(sscop, SSCOP_IDLE); 2491226890Sdim } else { 2492226890Sdim sscop->vt_cc++; 2493226890Sdim send_rs(sscop, 1, sscop->uu_rs); 2494226890Sdim TIMER_RESTART(sscop, cc); 2495226890Sdim } 2496235633Sdim} 2497226890Sdim 2498235633Sdim/* 2499226890Sdim * p 44: OUT_RESYNC && AA-RELEASE.request 2500194711Sed * arg is UU 2501194711Sed */ 2502198092Srdivackystatic void 2503198092Srdivackysscop_outsync_release_req(struct sscop *sscop, struct sscop_msg *uu) 2504198092Srdivacky{ 2505198092Srdivacky SET_UU(uu_end, uu); 2506212904Sdim 2507193326Sed TIMER_STOP(sscop, cc); 2508193326Sed sscop->vt_cc = 1; 2509193326Sed send_end(sscop, 0, sscop->uu_end); 2510193326Sed TIMER_RESTART(sscop, cc); 2511193326Sed sscop_set_state(sscop, SSCOP_OUT_DIS_PEND); 2512193326Sed} 2513193326Sed 2514193326Sed/* 2515193326Sed * p 45: OUT_RESYNC && RS PDU 2516193326Sed * arg is pdu (freed). 2517193326Sed */ 2518193326Sedstatic void 2519218893Sdimsscop_outsync_rs(struct sscop *sscop, struct sscop_msg *msg) 2520218893Sdim{ 2521218893Sdim union pdu pdu; 2522218893Sdim 2523218893Sdim pdu.sscop_null = MBUF_STRIP32(msg->m); 2524218893Sdim 2525193326Sed if(m_detect_retransmission(sscop, msg)) { 2526193326Sed SSCOP_MSG_FREE(msg); 2527195341Sed return; 2528195341Sed } 2529198092Srdivacky (void)MBUF_STRIP32(msg->m); 2530195341Sed 2531252723Sdim TIMER_STOP(sscop, cc); 2532235633Sdim sscop->vt_ms = pdu.sscop_ns; 2533252723Sdim m_initialize_mr(sscop); 2534252723Sdim send_rsak(sscop); 2535218893Sdim AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_confirm, msg, pdu.sscop_pl, 0); 2536218893Sdim m_initialize_state(sscop); 2537235633Sdim m_set_data_xfer_timers(sscop); 2538235633Sdim sscop_set_state(sscop, SSCOP_READY); 2539226890Sdim} 2540235633Sdim 2541218893Sdim/* 2542218893Sdim * p 45: OUT_RESYNC && RSAK PDU 2543193326Sed * arg is pdu (freed). 2544193326Sed */ 2545200583Srdivackystatic void 2546201361Srdivackysscop_outsync_rsak(struct sscop *sscop, struct sscop_msg *msg) 2547200583Srdivacky{ 2548201361Srdivacky union pdu pdu; 2549200583Srdivacky 2550235633Sdim pdu.sscop_null = MBUF_STRIP32(msg->m); 2551235633Sdim 2552201361Srdivacky SSCOP_MSG_FREE(msg); 2553201361Srdivacky 2554201361Srdivacky TIMER_STOP(sscop, cc); 2555193326Sed sscop->vt_ms = pdu.sscop_ns; 2556201361Srdivacky AAL_SIG(sscop, SSCOP_RESYNC_confirm); 2557201361Srdivacky m_initialize_state(sscop); 2558201361Srdivacky m_set_data_xfer_timers(sscop); 2559201361Srdivacky sscop_set_state(sscop, SSCOP_READY); 2560207619Srdivacky} 2561207619Srdivacky 2562207619Srdivacky/* 2563202879Srdivacky * p 46: IN_RESYNC_PEND && AA-RESYNC.response 2564202879Srdivacky */ 2565202879Srdivackystatic void 2566202879Srdivackysscop_insync_sync_resp(struct sscop *sscop, struct sscop_msg *noarg __unused) 2567202879Srdivacky{ 2568202879Srdivacky m_initialize_mr(sscop); 2569202879Srdivacky send_rsak(sscop); 2570202879Srdivacky m_clear_transmitter(sscop); 2571202879Srdivacky m_initialize_state(sscop); 2572221345Sdim m_set_data_xfer_timers(sscop); 2573221345Sdim sscop_set_state(sscop, SSCOP_READY); 2574221345Sdim} 2575204962Srdivacky 2576204962Srdivacky/* 2577204962Srdivacky * p 46: IN_RESYNC_PEND && AA-RELEASE.request 2578202879Srdivacky * arg is uu 2579210299Sed */ 2580202879Srdivackystatic void 2581202879Srdivackysscop_insync_release_req(struct sscop *sscop, struct sscop_msg *uu) 2582202879Srdivacky{ 2583201361Srdivacky SET_UU(uu_end, uu); 2584224145Sdim 2585235633Sdim sscop->vt_cc = 1; 2586202879Srdivacky send_end(sscop, 0, sscop->uu_end); 2587224145Sdim TIMER_RESTART(sscop, cc); 2588235633Sdim sscop_set_state(sscop, SSCOP_OUT_DIS_PEND); 2589224145Sdim} 2590235633Sdim 2591235633Sdim/* 2592235633Sdim * p 46: IN_RESYNC_PEND && ENDAK PDU 2593263509Sdim * arg is pdu (freed). 2594263509Sdim */ 2595263509Sdimstatic void 2596235633Sdimsscop_insync_endak(struct sscop *sscop, struct sscop_msg *msg) 2597224145Sdim{ 2598201361Srdivacky SSCOP_MSG_FREE(msg); 2599201361Srdivacky MAAL_ERROR(sscop, 'F', 0); 2600201361Srdivacky AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2601201361Srdivacky sscop_set_state(sscop, SSCOP_IDLE); 2602201361Srdivacky} 2603201361Srdivacky 2604201361Srdivacky/* 2605201361Srdivacky * p 46: IN_RESYNC_PEND && BGREJ PDU 2606263509Sdim * arg is pdu (freed). 2607263509Sdim */ 2608263509Sdimstatic void 2609263509Sdimsscop_insync_bgrej(struct sscop *sscop, struct sscop_msg *msg) 2610202379Srdivacky{ 2611263509Sdim SSCOP_MSG_FREE(msg); 2612263509Sdim MAAL_ERROR(sscop, 'D', 0); 2613235633Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2614202379Srdivacky sscop_set_state(sscop, SSCOP_IDLE); 2615202379Srdivacky} 2616202379Srdivacky 2617202379Srdivacky/* 2618201361Srdivacky * p 46: IN_RESYNC_PEND && END PDU 2619201361Srdivacky * arg is pdu (freed). 2620201361Srdivacky */ 2621201361Srdivackystatic void 2622201361Srdivackysscop_insync_end(struct sscop *sscop, struct sscop_msg *msg) 2623202879Srdivacky{ 2624201361Srdivacky union pdu pdu; 2625235633Sdim 2626201361Srdivacky pdu.sscop_null = MBUF_STRIP32(msg->m); 2627201361Srdivacky (void)MBUF_STRIP32(msg->m); 2628201361Srdivacky 2629201361Srdivacky send_endak(sscop); 2630202879Srdivacky AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication, 2631202879Srdivacky msg, pdu.sscop_pl, (u_int)pdu.sscop_s); 2632202879Srdivacky sscop_set_state(sscop, SSCOP_IDLE); 2633202879Srdivacky} 2634202879Srdivacky 2635201361Srdivacky/* 2636202879Srdivacky * p 47: IN_RESYNC_PEND && ER PDU 2637208600Srdivacky * arg is pdu (freed). 2638202879Srdivacky */ 2639201361Srdivackystatic void 2640201361Srdivackysscop_insync_er(struct sscop *sscop, struct sscop_msg *msg) 2641201361Srdivacky{ 2642200583Srdivacky SSCOP_MSG_FREE(msg); 2643200583Srdivacky MAAL_ERROR(sscop, 'L', 0); 2644198092Srdivacky} 2645235633Sdim 2646198092Srdivacky/* 2647198092Srdivacky * p 47: IN_RESYNC_PEND && BGN PDU 2648226890Sdim * arg is pdu (freed). 2649226890Sdim */ 2650226890Sdimstatic void 2651226890Sdimsscop_insync_bgn(struct sscop *sscop, struct sscop_msg *msg) 2652226890Sdim{ 2653226890Sdim union pdu pdu; 2654226890Sdim 2655226890Sdim pdu.sscop_null = MBUF_STRIP32(msg->m); 2656226890Sdim 2657226890Sdim if(m_detect_retransmission(sscop, msg)) { 2658226890Sdim MAAL_ERROR(sscop, 'B', 0); 2659226890Sdim SSCOP_MSG_FREE(msg); 2660226890Sdim return; 2661226890Sdim } 2662226890Sdim (void)MBUF_STRIP32(msg->m); 2663226890Sdim 2664226890Sdim sscop->vt_ms = pdu.sscop_ns; 2665226890Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0); 2666226890Sdim AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0); 2667226890Sdim 2668226890Sdim sscop_set_state(sscop, SSCOP_IN_PEND); 2669226890Sdim} 2670226890Sdim 2671226890Sdim/* 2672226890Sdim * p 47: IN_RESYNC_PEND && SD PDU 2673226890Sdim * arg is pdu (freed). 2674226890Sdim */ 2675226890Sdimstatic void 2676263509Sdimsscop_insync_sd(struct sscop *sscop, struct sscop_msg *msg) 2677226890Sdim{ 2678226890Sdim SSCOP_MSG_FREE(msg); 2679226890Sdim MAAL_ERROR(sscop, 'A', 0); 2680226890Sdim FREE_UU(uu_end); 2681226890Sdim send_end(sscop, 1, NULL); 2682226890Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2683226890Sdim sscop_set_state(sscop, SSCOP_IDLE); 2684226890Sdim} 2685226890Sdim 2686226890Sdim/* 2687226890Sdim * p 47: IN_RESYNC_PEND && POLL PDU 2688226890Sdim * arg is pdu (freed). 2689226890Sdim */ 2690226890Sdimstatic void 2691226890Sdimsscop_insync_poll(struct sscop *sscop, struct sscop_msg *msg) 2692226890Sdim{ 2693226890Sdim SSCOP_MSG_FREE(msg); 2694226890Sdim MAAL_ERROR(sscop, 'G', 0); 2695212904Sdim FREE_UU(uu_end); 2696235633Sdim send_end(sscop, 1, NULL); 2697226890Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2698218893Sdim sscop_set_state(sscop, SSCOP_IDLE); 2699218893Sdim} 2700218893Sdim 2701218893Sdim/* 2702218893Sdim * p 47: IN_RESYNC_PEND && STAT PDU 2703235633Sdim * arg is pdu (freed). 2704235633Sdim */ 2705235633Sdimstatic void 2706218893Sdimsscop_insync_stat(struct sscop *sscop, struct sscop_msg *msg) 2707218893Sdim{ 2708218893Sdim SSCOP_MSG_FREE(msg); 2709252723Sdim MAAL_ERROR(sscop, 'H', 0); 2710235633Sdim FREE_UU(uu_end); 2711252723Sdim send_end(sscop, 1, NULL); 2712252723Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2713252723Sdim sscop_set_state(sscop, SSCOP_IDLE); 2714235633Sdim} 2715252723Sdim 2716252723Sdim/* 2717235633Sdim * p 47: IN_RESYNC_PEND && USTAT PDU 2718245431Sdim * arg is pdu (freed). 2719235633Sdim */ 2720198092Srdivackystatic void 2721235633Sdimsscop_insync_ustat(struct sscop *sscop, struct sscop_msg *msg) 2722203955Srdivacky{ 2723203955Srdivacky SSCOP_MSG_FREE(msg); 2724224145Sdim MAAL_ERROR(sscop, 'I', 0); 2725218893Sdim FREE_UU(uu_end); 2726235633Sdim send_end(sscop, 1, NULL); 2727235633Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2728235633Sdim sscop_set_state(sscop, SSCOP_IDLE); 2729252723Sdim} 2730235633Sdim 2731235633Sdim/* 2732218893Sdim * p 48: IN_RESYNC_PEND && BGAK PDU 2733218893Sdim * arg is pdu (freed). 2734218893Sdim */ 2735218893Sdimstatic void 2736218893Sdimsscop_insync_bgak(struct sscop *sscop, struct sscop_msg *msg) 2737235633Sdim{ 2738235633Sdim MAAL_ERROR(sscop, 'C', 0); 2739235633Sdim SSCOP_MSG_FREE(msg); 2740218893Sdim} 2741252723Sdim 2742252723Sdim/* 2743218893Sdim * p 48: IN_RESYNC_PEND && ERAK PDU 2744218893Sdim * arg is pdu (freed). 2745218893Sdim */ 2746263509Sdimstatic void 2747263509Sdimsscop_insync_erak(struct sscop *sscop, struct sscop_msg *msg) 2748252723Sdim{ 2749218893Sdim MAAL_ERROR(sscop, 'M', 0); 2750218893Sdim SSCOP_MSG_FREE(msg); 2751252723Sdim} 2752218893Sdim 2753218893Sdim/* 2754218893Sdim * p 48: IN_RESYNC_PEND && RS PDU 2755252723Sdim * arg is pdu (freed). 2756193326Sed */ 2757203955Srdivackystatic void 2758218893Sdimsscop_insync_rs(struct sscop *sscop, struct sscop_msg *msg) 2759235633Sdim{ 2760235633Sdim union pdu pdu; 2761235633Sdim 2762218893Sdim pdu.sscop_null = MBUF_STRIP32(msg->m); 2763235633Sdim 2764235633Sdim if(m_detect_retransmission(sscop, msg)) { 2765235633Sdim SSCOP_MSG_FREE(msg); 2766203955Srdivacky return; 2767218893Sdim } 2768203955Srdivacky SSCOP_MSG_FREE(msg); 2769218893Sdim MAAL_ERROR(sscop, 'J', 0); 2770235633Sdim} 2771221345Sdim 2772235633Sdim/* 2773252723Sdim * p 48: IN_RESYNC_PEND && RSAK PDU 2774235633Sdim * arg is pdu (freed). 2775218893Sdim */ 2776235633Sdimstatic void 2777218893Sdimsscop_insync_rsak(struct sscop *sscop, struct sscop_msg *msg) 2778235633Sdim{ 2779252723Sdim MAAL_ERROR(sscop, 'K', 0); 2780235633Sdim SSCOP_MSG_FREE(msg); 2781235633Sdim} 2782252723Sdim 2783235633Sdim 2784235633Sdim/* 2785235633Sdim * p 49: OUT_REC_PEND && AA-DATA.request 2786221345Sdim * arg is message (queued). 2787221345Sdim */ 2788221345Sdimstatic void 2789221345Sdimsscop_outrec_userdata(struct sscop *sscop, struct sscop_msg *msg) 2790235633Sdim{ 2791235633Sdim if(!sscop->clear_buffers) { 2792235633Sdim MSGQ_APPEND(&sscop->xq, msg); 2793252723Sdim sscop_signal(sscop, SIG_PDU_Q, msg); 2794235633Sdim } else { 2795252723Sdim SSCOP_MSG_FREE(msg); 2796221345Sdim } 2797221345Sdim} 2798221345Sdim 2799235633Sdim/* 2800235633Sdim * p 49: OUT_REC_PEND && BGAK PDU 2801221345Sdim * arg is pdu (freed) 2802252723Sdim */ 2803221345Sdimstatic void 2804221345Sdimsscop_outrec_bgak(struct sscop *sscop, struct sscop_msg *msg) 2805252723Sdim{ 2806252723Sdim MAAL_ERROR(sscop, 'C', 0); 2807221345Sdim 2808221345Sdim SSCOP_MSG_FREE(msg); 2809221345Sdim} 2810245431Sdim 2811245431Sdim/* 2812245431Sdim * p 49: OUT_REC_PEND && ERAK PDU 2813245431Sdim * arg is pdu (freed) 2814245431Sdim */ 2815245431Sdimstatic void 2816245431Sdimsscop_outrec_erak(struct sscop *sscop, struct sscop_msg *msg) 2817245431Sdim{ 2818245431Sdim union pdu pdu; 2819245431Sdim 2820235633Sdim pdu.sscop_null = MBUF_STRIP32(msg->m); 2821221345Sdim 2822235633Sdim TIMER_STOP(sscop, cc); 2823198092Srdivacky sscop->vt_ms = pdu.sscop_ns; 2824198092Srdivacky m_deliver_data(sscop); 2825212904Sdim 2826200583Srdivacky AAL_SIG(sscop, SSCOP_RECOVER_indication); 2827235633Sdim 2828218893Sdim sscop_set_state(sscop, SSCOP_REC_PEND); 2829210299Sed 2830210299Sed SSCOP_MSG_FREE(msg); 2831226890Sdim} 2832210299Sed 2833210299Sed/* 2834210299Sed * p 49: OUT_REC_PEND && END PDU 2835210299Sed * arg is pdu (freed) 2836210299Sed */ 2837210299Sedstatic void 2838218893Sdimsscop_outrec_end(struct sscop *sscop, struct sscop_msg *msg) 2839210299Sed{ 2840210299Sed union pdu pdu; 2841210299Sed 2842235633Sdim pdu.sscop_null = MBUF_STRIP32(msg->m); 2843210299Sed (void)MBUF_STRIP32(msg->m); 2844235633Sdim 2845218893Sdim TIMER_STOP(sscop, cc); 2846218893Sdim send_endak(sscop); 2847218893Sdim AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication, 2848218893Sdim msg, pdu.sscop_pl, (u_int)pdu.sscop_s); 2849235633Sdim 2850226890Sdim MSGQ_CLEAR(&sscop->rbuf); 2851218893Sdim 2852218893Sdim sscop_set_state(sscop, SSCOP_IDLE); 2853218893Sdim} 2854218893Sdim 2855218893Sdim/* 2856218893Sdim * p 49: OUT_REC_PEND && ENDAK PDU 2857226890Sdim * arg is pdu (freed) 2858235633Sdim */ 2859226890Sdimstatic void 2860218893Sdimsscop_outrec_endak(struct sscop *sscop, struct sscop_msg *msg) 2861226890Sdim{ 2862210299Sed MAAL_ERROR(sscop, 'F', 0); 2863210299Sed TIMER_STOP(sscop, cc); 2864210299Sed AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2865210299Sed MSGQ_CLEAR(&sscop->rbuf); 2866218893Sdim 2867218893Sdim sscop_set_state(sscop, SSCOP_IDLE); 2868235633Sdim 2869218893Sdim SSCOP_MSG_FREE(msg); 2870210299Sed} 2871210299Sed 2872210299Sed/* 2873210299Sed * p 49: OUT_REC_PEND && BGREJ PDU 2874210299Sed * arg is pdu (freed) 2875210299Sed */ 2876210299Sedstatic void 2877210299Sedsscop_outrec_bgrej(struct sscop *sscop, struct sscop_msg *msg) 2878210299Sed{ 2879210299Sed MAAL_ERROR(sscop, 'D', 0); 2880210299Sed TIMER_STOP(sscop, cc); 2881210299Sed AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2882210299Sed MSGQ_CLEAR(&sscop->rbuf); 2883210299Sed 2884210299Sed sscop_set_state(sscop, SSCOP_IDLE); 2885210299Sed 2886210299Sed SSCOP_MSG_FREE(msg); 2887210299Sed} 2888210299Sed 2889210299Sed/* 2890210299Sed * p 50: OUT_REC_PEND && TIMER CC expiry 2891210299Sed * no arg. 2892210299Sed */ 2893224145Sdimstatic void 2894198092Srdivackysscop_outrec_cc(struct sscop *sscop, struct sscop_msg *unused __unused) 2895226890Sdim{ 2896226890Sdim if(sscop->vt_cc >= sscop->maxcc) { 2897235633Sdim MAAL_ERROR(sscop, 'O', 0); 2898235633Sdim FREE_UU(uu_end); 2899193326Sed send_end(sscop, 1, NULL); 2900193326Sed AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 2901203955Srdivacky MSGQ_CLEAR(&sscop->rbuf); 2902203955Srdivacky sscop_set_state(sscop, SSCOP_IDLE); 2903203955Srdivacky } else { 2904203955Srdivacky sscop->vt_cc++; 2905203955Srdivacky send_er(sscop); 2906203955Srdivacky TIMER_RESTART(sscop, cc); 2907208600Srdivacky } 2908203955Srdivacky} 2909263509Sdim 2910203955Srdivacky/* 2911263509Sdim * p 50: OUT_REC_PEND && SSCOP_RELEASE_request 2912203955Srdivacky * arg is UU 2913203955Srdivacky */ 2914235633Sdimstatic void 2915252723Sdimsscop_outrec_release_req(struct sscop *sscop, struct sscop_msg *uu) 2916235633Sdim{ 2917235633Sdim SET_UU(uu_end, uu); 2918252723Sdim 2919235633Sdim TIMER_STOP(sscop, cc); 2920235633Sdim sscop->vt_cc = 1; 2921203955Srdivacky send_end(sscop, 0, sscop->uu_end); 2922207619Srdivacky MSGQ_CLEAR(&sscop->rbuf); 2923235633Sdim TIMER_RESTART(sscop, cc); 2924235633Sdim 2925235633Sdim sscop_set_state(sscop, SSCOP_OUT_DIS_PEND); 2926235633Sdim} 2927252723Sdim 2928252723Sdim/* 2929203955Srdivacky * p 51: OUT_REC_PEND && AA-RESYNC.request 2930203955Srdivacky * arg is uu 2931218893Sdim */ 2932252723Sdimstatic void 2933252723Sdimsscop_outrec_sync_req(struct sscop *sscop, struct sscop_msg *uu) 2934203955Srdivacky{ 2935252723Sdim SET_UU(uu_rs, uu); 2936203955Srdivacky 2937203955Srdivacky TIMER_STOP(sscop, cc); 2938203955Srdivacky sscop->vt_cc = 1; 2939203955Srdivacky sscop->vt_sq++; 2940203955Srdivacky m_initialize_mr(sscop); 2941203955Srdivacky send_rs(sscop, 0, sscop->uu_rs); 2942203955Srdivacky m_clear_transmitter(sscop); 2943203955Srdivacky MSGQ_CLEAR(&sscop->rbuf); 2944203955Srdivacky TIMER_RESTART(sscop, cc); 2945203955Srdivacky} 2946226890Sdim 2947235633Sdim/* 2948198092Srdivacky * p 51: OUT_REC_PEND && BGN PDU 2949218893Sdim * arg is pdu (freed). 2950226890Sdim * no uui 2951235633Sdim */ 2952226890Sdimstatic void 2953235633Sdimsscop_outrec_bgn(struct sscop *sscop, struct sscop_msg *msg) 2954193326Sed{ 2955193326Sed union pdu pdu; 2956226890Sdim 2957252723Sdim pdu.sscop_null = MBUF_STRIP32(msg->m); 2958252723Sdim 2959252723Sdim if(m_detect_retransmission(sscop, msg)) { 2960252723Sdim MAAL_ERROR(sscop, 'B', 0); 2961226890Sdim SSCOP_MSG_FREE(msg); 2962226890Sdim } else { 2963226890Sdim (void)MBUF_STRIP32(msg->m); 2964226890Sdim 2965226890Sdim TIMER_STOP(sscop, cc); 2966226890Sdim sscop->vt_ms = pdu.sscop_ns; 2967226890Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0); 2968226890Sdim AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, 2969226890Sdim msg, pdu.sscop_pl, 0); 2970207619Srdivacky MSGQ_CLEAR(&sscop->rbuf); 2971207619Srdivacky 2972207619Srdivacky sscop_set_state(sscop, SSCOP_IN_PEND); 2973207619Srdivacky } 2974207619Srdivacky} 2975252723Sdim 2976252723Sdim/* 2977207619Srdivacky * p 51: OUT_REC_PEND && ER PDU 2978207619Srdivacky * arg is pdu (freed). 2979207619Srdivacky */ 2980207619Srdivackystatic void 2981207619Srdivackysscop_outrec_er(struct sscop *sscop, struct sscop_msg *msg) 2982207619Srdivacky{ 2983207619Srdivacky union pdu pdu; 2984218893Sdim 2985207619Srdivacky pdu.sscop_null = MBUF_STRIP32(msg->m); 2986207619Srdivacky 2987207619Srdivacky if(m_detect_retransmission(sscop, msg)) { 2988207619Srdivacky MAAL_ERROR(sscop, 'L', 0); 2989212904Sdim } else { 2990207619Srdivacky TIMER_STOP(sscop, cc); 2991207619Srdivacky sscop->vt_ms = pdu.sscop_ns; 2992252723Sdim m_initialize_mr(sscop); 2993252723Sdim send_erak(sscop); 2994252723Sdim m_deliver_data(sscop); 2995252723Sdim 2996252723Sdim AAL_SIG(sscop, SSCOP_RECOVER_indication); 2997252723Sdim 2998252723Sdim sscop_set_state(sscop, SSCOP_REC_PEND); 2999252723Sdim } 3000252723Sdim 3001252723Sdim SSCOP_MSG_FREE(msg); 3002252723Sdim} 3003252723Sdim 3004252723Sdim/* 3005252723Sdim * p 52: OUT_REC_PEND && SD PDU queued 3006252723Sdim * no arg. 3007252723Sdim */ 3008252723Sdimstatic void 3009252723Sdimsscop_outrec_pduq(struct sscop *sscop, struct sscop_msg *msg) 3010252723Sdim{ 3011252723Sdim sscop_save_signal(sscop, SIG_PDU_Q, msg); 3012252723Sdim} 3013252723Sdim 3014252723Sdim/* 3015252723Sdim * p 52: OUT_REC_PEND && RSAK PDU 3016252723Sdim * arg is pdu (freed). 3017252723Sdim */ 3018252723Sdimstatic void 3019252723Sdimsscop_outrec_rsak(struct sscop *sscop, struct sscop_msg *msg) 3020207619Srdivacky{ 3021207619Srdivacky SSCOP_MSG_FREE(msg); 3022207619Srdivacky MAAL_ERROR(sscop, 'K', 0); 3023252723Sdim} 3024252723Sdim 3025207619Srdivacky/* 3026207619Srdivacky * p 52: OUT_REC_PEND && RS PDU 3027207619Srdivacky * arg is pdu (freed). 3028226890Sdim */ 3029207619Srdivackystatic void 3030226890Sdimsscop_outrec_rs(struct sscop *sscop, struct sscop_msg *msg) 3031207619Srdivacky{ 3032207619Srdivacky union pdu pdu; 3033235633Sdim 3034207619Srdivacky pdu.sscop_null = MBUF_STRIP32(msg->m); 3035235633Sdim 3036235633Sdim if(m_detect_retransmission(sscop, msg)) { 3037218893Sdim SSCOP_MSG_FREE(msg); 3038218893Sdim MAAL_ERROR(sscop, 'J', 0); 3039226890Sdim return; 3040235633Sdim } 3041235633Sdim (void)MBUF_STRIP32(msg->m); 3042207619Srdivacky 3043207619Srdivacky TIMER_STOP(sscop, cc); 3044207619Srdivacky sscop->vt_ms = pdu.sscop_ns; 3045207619Srdivacky AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_indication, msg, pdu.sscop_pl, 0); 3046207619Srdivacky MSGQ_CLEAR(&sscop->rbuf); 3047226890Sdim sscop_set_state(sscop, SSCOP_IN_RESYNC_PEND); 3048226890Sdim} 3049226890Sdim 3050226890Sdim/* 3051212904Sdim * p 53: REC_PEND && BGAK PDU 3052212904Sdim * arg is pdu (freed) 3053221345Sdim */ 3054221345Sdimstatic void 3055226890Sdimsscop_rec_bgak(struct sscop *sscop, struct sscop_msg *msg) 3056226890Sdim{ 3057212904Sdim MAAL_ERROR(sscop, 'C', 0); 3058207619Srdivacky 3059207619Srdivacky SSCOP_MSG_FREE(msg); 3060207619Srdivacky} 3061252723Sdim 3062252723Sdim/* 3063207619Srdivacky * p 53: REC_PEND && END PDU 3064207619Srdivacky * arg is pdu (freed) 3065207619Srdivacky * no uui 3066212904Sdim */ 3067218893Sdimstatic void 3068212904Sdimsscop_rec_end(struct sscop *sscop, struct sscop_msg *msg) 3069212904Sdim{ 3070207619Srdivacky union pdu pdu; 3071207619Srdivacky 3072218893Sdim pdu.sscop_null = MBUF_STRIP32(msg->m); 3073207619Srdivacky (void)MBUF_STRIP32(msg->m); 3074207619Srdivacky 3075207619Srdivacky send_endak(sscop); 3076207619Srdivacky AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication, 3077207619Srdivacky msg, pdu.sscop_pl, (u_int)pdu.sscop_s); 3078218893Sdim 3079207619Srdivacky sscop_set_state(sscop, SSCOP_IDLE); 3080207619Srdivacky} 3081207619Srdivacky 3082207619Srdivacky/* 3083207619Srdivacky * p 53: REC_PEND && ENDAK PDU 3084226890Sdim * arg is pdu (freed) 3085226890Sdim */ 3086226890Sdimstatic void 3087226890Sdimsscop_rec_endak(struct sscop *sscop, struct sscop_msg *msg) 3088226890Sdim{ 3089207619Srdivacky MAAL_ERROR(sscop, 'F', 0); 3090207619Srdivacky AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 3091207619Srdivacky sscop_set_state(sscop, SSCOP_IDLE); 3092226890Sdim SSCOP_MSG_FREE(msg); 3093218893Sdim} 3094208600Srdivacky 3095208600Srdivacky/* 3096208600Srdivacky * p 53: REC_PEND && BGREJ PDU 3097210299Sed * arg is pdu (freed) 3098210299Sed */ 3099226890Sdimstatic void 3100226890Sdimsscop_rec_bgrej(struct sscop *sscop, struct sscop_msg *msg) 3101207619Srdivacky{ 3102207619Srdivacky MAAL_ERROR(sscop, 'D', 0); 3103224145Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 3104224145Sdim sscop_set_state(sscop, SSCOP_IDLE); 3105226890Sdim SSCOP_MSG_FREE(msg); 3106226890Sdim} 3107235633Sdim 3108207619Srdivacky/* 3109235633Sdim * p 54: REC_PEND && RELEASE 3110235633Sdim * arg is UU 3111218893Sdim */ 3112208600Srdivackystatic void 3113235633Sdimsscop_rec_release_req(struct sscop *sscop, struct sscop_msg *uu) 3114235633Sdim{ 3115226890Sdim SET_UU(uu_end, uu); 3116226890Sdim 3117226890Sdim sscop->vt_cc = 1; 3118226890Sdim send_end(sscop, 0, sscop->uu_end); 3119208600Srdivacky TIMER_RESTART(sscop, cc); 3120208600Srdivacky 3121208600Srdivacky sscop_set_state(sscop, SSCOP_OUT_DIS_PEND); 3122208600Srdivacky} 3123226890Sdim 3124226890Sdim/* 3125208600Srdivacky * p 54: REC_PEND && RSAK PDU 3126226890Sdim * arg is pdu (freed). 3127212904Sdim */ 3128208600Srdivackystatic void 3129208600Srdivackysscop_rec_rsak(struct sscop *sscop, struct sscop_msg *msg) 3130208600Srdivacky{ 3131235633Sdim MAAL_ERROR(sscop, 'K', 0); 3132208600Srdivacky SSCOP_MSG_FREE(msg); 3133208600Srdivacky} 3134208600Srdivacky 3135226890Sdim 3136208600Srdivacky/* 3137226890Sdim * p 54: REC_PEND && RS PDU 3138226890Sdim * arg is pdu (freed). 3139226890Sdim */ 3140226890Sdimstatic void 3141226890Sdimsscop_rec_rs(struct sscop *sscop, struct sscop_msg *msg) 3142226890Sdim{ 3143226890Sdim union pdu pdu; 3144226890Sdim 3145208600Srdivacky pdu.sscop_null = MBUF_STRIP32(msg->m); 3146208600Srdivacky 3147208600Srdivacky if(m_detect_retransmission(sscop, msg)) { 3148208600Srdivacky SSCOP_MSG_FREE(msg); 3149226890Sdim MAAL_ERROR(sscop, 'J', 0); 3150208600Srdivacky return; 3151208600Srdivacky } 3152226890Sdim (void)MBUF_STRIP32(msg->m); 3153208600Srdivacky 3154208600Srdivacky sscop->vt_ms = pdu.sscop_ns; 3155226890Sdim AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_indication, msg, pdu.sscop_pl, 0); 3156208600Srdivacky 3157208600Srdivacky sscop_set_state(sscop, SSCOP_IN_RESYNC_PEND); 3158208600Srdivacky} 3159235633Sdim 3160208600Srdivacky/* 3161208600Srdivacky * p 54: REC_PEND && RECOVER response 3162208600Srdivacky * no arg 3163208600Srdivacky */ 3164208600Srdivackystatic void 3165221345Sdimsscop_rec_recover(struct sscop *sscop, struct sscop_msg *unused __unused) 3166208600Srdivacky{ 3167208600Srdivacky if(!sscop->clear_buffers) { 3168252723Sdim MSGQ_CLEAR(&sscop->xbuf); 3169208600Srdivacky } 3170208600Srdivacky m_initialize_state(sscop); 3171208600Srdivacky m_set_data_xfer_timers(sscop); 3172212904Sdim 3173235633Sdim sscop_set_state(sscop, SSCOP_READY); 3174208600Srdivacky} 3175208600Srdivacky 3176235633Sdim/* 3177235633Sdim * p 54: REC_PEND && RESYNC request 3178235633Sdim * arg is uu 3179226890Sdim */ 3180208600Srdivackystatic void 3181226890Sdimsscop_rec_sync_req(struct sscop *sscop, struct sscop_msg *uu) 3182212904Sdim{ 3183226890Sdim SET_UU(uu_rs, uu); 3184226890Sdim 3185208600Srdivacky m_clear_transmitter(sscop); 3186226890Sdim sscop->vt_cc = 1; 3187208600Srdivacky sscop->vt_sq++; 3188208600Srdivacky m_initialize_mr(sscop); 3189226890Sdim send_rs(sscop, 0, sscop->uu_rs); 3190226890Sdim TIMER_RESTART(sscop, cc); 3191226890Sdim 3192226890Sdim sscop_set_state(sscop, SSCOP_OUT_RESYNC_PEND); 3193226890Sdim} 3194208600Srdivacky 3195208600Srdivacky/* 3196208600Srdivacky * p 55: REC_PEND && SD PDU queued 3197226890Sdim * no arg 3198208600Srdivacky */ 3199226890Sdimstatic void 3200226890Sdimsscop_rec_pduq(struct sscop *sscop, struct sscop_msg *msg) 3201226890Sdim{ 3202226890Sdim sscop_save_signal(sscop, SIG_PDU_Q, msg); 3203208600Srdivacky} 3204208600Srdivacky 3205208600Srdivacky/* 3206208600Srdivacky * p 55: REC_PEND && ER PDU 3207207619Srdivacky * arg is pdu (freed). 3208208600Srdivacky */ 3209207619Srdivackystatic void 3210208600Srdivackysscop_rec_er(struct sscop *sscop, struct sscop_msg *msg) 3211207619Srdivacky{ 3212226890Sdim union pdu pdu; 3213252723Sdim 3214207619Srdivacky pdu.sscop_null = MBUF_STRIP32(msg->m); 3215212904Sdim 3216208600Srdivacky if(m_detect_retransmission(sscop, msg)) { 3217226890Sdim send_erak(sscop); 3218218893Sdim } else { 3219207619Srdivacky MAAL_ERROR(sscop, 'L', 0); 3220207619Srdivacky } 3221208600Srdivacky SSCOP_MSG_FREE(msg); 3222226890Sdim} 3223226890Sdim 3224226890Sdim/* 3225226890Sdim * p 55: REC_PEND && BGN PDU 3226226890Sdim * arg is pdu (freed) 3227226890Sdim * no uui 3228226890Sdim */ 3229226890Sdimstatic void 3230226890Sdimsscop_rec_bgn(struct sscop *sscop, struct sscop_msg *msg) 3231226890Sdim{ 3232226890Sdim union pdu pdu; 3233226890Sdim 3234226890Sdim pdu.sscop_null = MBUF_STRIP32(msg->m); 3235226890Sdim 3236207619Srdivacky if(m_detect_retransmission(sscop, msg)) { 3237207619Srdivacky MAAL_ERROR(sscop, 'B', 0); 3238207619Srdivacky SSCOP_MSG_FREE(msg); 3239252723Sdim return; 3240252723Sdim } 3241207619Srdivacky (void)MBUF_STRIP32(msg->m); 3242207619Srdivacky 3243207619Srdivacky sscop->vt_ms = pdu.sscop_ns; 3244207619Srdivacky AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0); 3245207619Srdivacky AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0); 3246226890Sdim 3247226890Sdim sscop_set_state(sscop, SSCOP_IN_PEND); 3248226890Sdim} 3249207619Srdivacky 3250210299Sed/* 3251212904Sdim * p 55: REC_PEND && STAT PDU 3252252723Sdim * arg is pdu (freed) 3253252723Sdim */ 3254252723Sdimstatic void 3255252723Sdimsscop_rec_stat(struct sscop *sscop, struct sscop_msg *msg) 3256218893Sdim{ 3257212904Sdim MAAL_ERROR(sscop, 'H', 0); 3258212904Sdim FREE_UU(uu_end); 3259207619Srdivacky send_end(sscop, 1, NULL); 3260226890Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 3261226890Sdim sscop_set_state(sscop, SSCOP_IDLE); 3262226890Sdim SSCOP_MSG_FREE(msg); 3263226890Sdim} 3264226890Sdim 3265226890Sdim/* 3266226890Sdim * p 55: REC_PEND && USTAT PDU 3267226890Sdim * arg is pdu (freed) 3268226890Sdim */ 3269226890Sdimstatic void 3270226890Sdimsscop_rec_ustat(struct sscop *sscop, struct sscop_msg *msg) 3271207619Srdivacky{ 3272207619Srdivacky MAAL_ERROR(sscop, 'I', 0); 3273207619Srdivacky FREE_UU(uu_end); 3274223017Sdim send_end(sscop, 1, NULL); 3275223017Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 3276223017Sdim sscop_set_state(sscop, SSCOP_IDLE); 3277223017Sdim SSCOP_MSG_FREE(msg); 3278223017Sdim} 3279223017Sdim 3280223017Sdim/* 3281223017Sdim * p 56: IN_REC_PEND && AA-RECOVER.response 3282223017Sdim * no arg 3283223017Sdim */ 3284207619Srdivackystatic void 3285223017Sdimsscop_inrec_recover(struct sscop *sscop, struct sscop_msg *unused __unused) 3286223017Sdim{ 3287223017Sdim if(!sscop->clear_buffers) { 3288223017Sdim MSGQ_CLEAR(&sscop->xbuf); 3289223017Sdim } 3290223017Sdim m_initialize_mr(sscop); 3291223017Sdim send_erak(sscop); 3292223017Sdim m_initialize_state(sscop); 3293223017Sdim m_set_data_xfer_timers(sscop); 3294207619Srdivacky 3295207619Srdivacky sscop_set_state(sscop, SSCOP_READY); 3296235633Sdim} 3297224145Sdim 3298224145Sdim/* 3299224145Sdim * p 56: IN_REC_PEND && SD PDU queued 3300245431Sdim * no arg 3301224145Sdim */ 3302224145Sdimstatic void 3303224145Sdimsscop_inrec_pduq(struct sscop *sscop, struct sscop_msg *msg) 3304224145Sdim{ 3305224145Sdim sscop_save_signal(sscop, SIG_PDU_Q, msg); 3306224145Sdim} 3307224145Sdim 3308224145Sdim/* 3309224145Sdim * p 56: IN_REC_PEND && AA-RELEASE.request 3310207619Srdivacky * arg is UU 3311207619Srdivacky */ 3312207619Srdivackystatic void 3313207619Srdivackysscop_inrec_release_req(struct sscop *sscop, struct sscop_msg *uu) 3314208600Srdivacky{ 3315208600Srdivacky SET_UU(uu_end, uu); 3316208600Srdivacky 3317208600Srdivacky sscop->vt_cc = 1; 3318208600Srdivacky send_end(sscop, 0, sscop->uu_end); 3319208600Srdivacky TIMER_RESTART(sscop, cc); 3320208600Srdivacky 3321218893Sdim sscop_set_state(sscop, SSCOP_OUT_DIS_PEND); 3322226890Sdim} 3323208600Srdivacky 3324208600Srdivacky/* 3325208600Srdivacky * p 56: IN_REC_PEND && END PDU 3326226890Sdim * arg is pdu (freed). 3327226890Sdim * no uui 3328208600Srdivacky */ 3329226890Sdimstatic void 3330226890Sdimsscop_inrec_end(struct sscop *sscop, struct sscop_msg *msg) 3331252723Sdim{ 3332252723Sdim union pdu pdu; 3333208600Srdivacky 3334208600Srdivacky pdu.sscop_null = MBUF_STRIP32(msg->m); 3335208600Srdivacky (void)MBUF_STRIP32(msg->m); 3336235633Sdim 3337235633Sdim send_endak(sscop); 3338235633Sdim AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication, 3339235633Sdim msg, pdu.sscop_pl, (u_int)pdu.sscop_s); 3340235633Sdim 3341235633Sdim sscop_set_state(sscop, SSCOP_IDLE); 3342235633Sdim} 3343235633Sdim 3344252723Sdim/* 3345235633Sdim * p 56: IN_REC_PEND && RESYNC_REQ 3346235633Sdim */ 3347235633Sdimstatic void 3348235633Sdimsscop_inrec_sync_req(struct sscop *sscop, struct sscop_msg *uu) 3349235633Sdim{ 3350245431Sdim SET_UU(uu_rs, uu); 3351245431Sdim 3352245431Sdim m_clear_transmitter(sscop); 3353245431Sdim sscop->vt_cc = 1; 3354245431Sdim sscop->vt_sq++; 3355252723Sdim m_initialize_mr(sscop); 3356245431Sdim send_rs(sscop, 0, sscop->uu_rs); 3357245431Sdim TIMER_RESTART(sscop, cc); 3358245431Sdim 3359245431Sdim sscop_set_state(sscop, SSCOP_OUT_RESYNC_PEND); 3360208600Srdivacky} 3361208600Srdivacky 3362208600Srdivacky 3363226890Sdim/* 3364226890Sdim * p 57: IN_REC_PEND && ENDAK PDU 3365226890Sdim * arg is pdu (freed) 3366226890Sdim */ 3367226890Sdimstatic void 3368226890Sdimsscop_inrec_endak(struct sscop *sscop, struct sscop_msg *msg) 3369226890Sdim{ 3370226890Sdim MAAL_ERROR(sscop, 'F', 0); 3371226890Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 3372226890Sdim SSCOP_MSG_FREE(msg); 3373226890Sdim sscop_set_state(sscop, SSCOP_IDLE); 3374226890Sdim} 3375226890Sdim 3376235633Sdim/* 3377235633Sdim * p 57: IN_REC_PEND && BGREJ PDU 3378235633Sdim * arg is pdu (freed) 3379235633Sdim */ 3380235633Sdimstatic void 3381235633Sdimsscop_inrec_bgrej(struct sscop *sscop, struct sscop_msg *msg) 3382235633Sdim{ 3383235633Sdim MAAL_ERROR(sscop, 'D', 0); 3384235633Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 3385235633Sdim SSCOP_MSG_FREE(msg); 3386235633Sdim sscop_set_state(sscop, SSCOP_IDLE); 3387235633Sdim} 3388235633Sdim 3389235633Sdim/* 3390235633Sdim * p 57: IN_REC_PEND && USTAT PDU 3391235633Sdim * arg is pdu (freed) 3392223017Sdim */ 3393226890Sdimstatic void 3394226890Sdimsscop_inrec_ustat(struct sscop *sscop, struct sscop_msg *msg) 3395263509Sdim{ 3396263509Sdim MAAL_ERROR(sscop, 'I', 0); 3397208600Srdivacky FREE_UU(uu_end); 3398210299Sed send_end(sscop, 1, NULL); 3399245431Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 3400245431Sdim SSCOP_MSG_FREE(msg); 3401208600Srdivacky sscop_set_state(sscop, SSCOP_IDLE); 3402245431Sdim} 3403223017Sdim 3404223017Sdim/* 3405235633Sdim * p 57: IN_REC_PEND && STAT PDU 3406252723Sdim * arg is pdu (freed) 3407252723Sdim */ 3408226890Sdimstatic void 3409226890Sdimsscop_inrec_stat(struct sscop *sscop, struct sscop_msg *msg) 3410226890Sdim{ 3411226890Sdim MAAL_ERROR(sscop, 'H', 0); 3412252723Sdim FREE_UU(uu_end); 3413226890Sdim send_end(sscop, 1, NULL); 3414226890Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 3415226890Sdim SSCOP_MSG_FREE(msg); 3416226890Sdim sscop_set_state(sscop, SSCOP_IDLE); 3417252723Sdim} 3418226890Sdim 3419245431Sdim/* 3420223017Sdim * p 57: IN_REC_PEND && POLL PDU 3421223017Sdim * arg is pdu (freed) 3422226890Sdim */ 3423226890Sdimstatic void 3424226890Sdimsscop_inrec_poll(struct sscop *sscop, struct sscop_msg *msg) 3425226890Sdim{ 3426226890Sdim MAAL_ERROR(sscop, 'G', 0); 3427208600Srdivacky FREE_UU(uu_end); 3428235633Sdim send_end(sscop, 1, NULL); 3429235633Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 3430235633Sdim SSCOP_MSG_FREE(msg); 3431235633Sdim sscop_set_state(sscop, SSCOP_IDLE); 3432208600Srdivacky} 3433208600Srdivacky 3434208600Srdivacky/* 3435263509Sdim * p 57: IN_REC_PEND && SD PDU 3436208600Srdivacky * arg is pdu (freed) 3437208600Srdivacky */ 3438218893Sdimstatic void 3439226890Sdimsscop_inrec_sd(struct sscop *sscop, struct sscop_msg *msg) 3440226890Sdim{ 3441208600Srdivacky MAAL_ERROR(sscop, 'A', 0); 3442208600Srdivacky FREE_UU(uu_end); 3443245431Sdim send_end(sscop, 1, NULL); 3444245431Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 3445218893Sdim SSCOP_MSG_FREE(msg); 3446245431Sdim sscop_set_state(sscop, SSCOP_IDLE); 3447208600Srdivacky} 3448221345Sdim 3449221345Sdim/* 3450221345Sdim * p 58: IN_REC_PEND && RSAK PDU 3451221345Sdim * arg is pdu (freed). 3452223017Sdim */ 3453221345Sdimstatic void 3454221345Sdimsscop_inrec_rsak(struct sscop *sscop, struct sscop_msg *msg) 3455221345Sdim{ 3456221345Sdim SSCOP_MSG_FREE(msg); 3457221345Sdim MAAL_ERROR(sscop, 'K', 0); 3458221345Sdim} 3459223017Sdim 3460235633Sdim/* 3461223017Sdim * p 58: IN_REC_PEND && RS PDU 3462221345Sdim * arg is pdu (freed). 3463221345Sdim */ 3464223017Sdimstatic void 3465223017Sdimsscop_inrec_rs(struct sscop *sscop, struct sscop_msg *msg) 3466221345Sdim{ 3467221345Sdim union pdu pdu; 3468226890Sdim 3469252723Sdim pdu.sscop_null = MBUF_STRIP32(msg->m); 3470252723Sdim 3471226890Sdim if(m_detect_retransmission(sscop, msg)) { 3472206084Srdivacky SSCOP_MSG_FREE(msg); 3473206084Srdivacky MAAL_ERROR(sscop, 'J', 0); 3474252723Sdim return; 3475252723Sdim } 3476218893Sdim (void)MBUF_STRIP32(msg->m); 3477252723Sdim 3478252723Sdim sscop->vt_ms = pdu.sscop_ns; 3479252723Sdim AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_indication, msg, pdu.sscop_pl, 0); 3480218893Sdim 3481206084Srdivacky sscop_set_state(sscop, SSCOP_IN_RESYNC_PEND); 3482245431Sdim} 3483245431Sdim 3484245431Sdim/* 3485245431Sdim * p 59: IN_REC_PEND && ER PDU 3486245431Sdim * arg is pdu (freed) 3487206084Srdivacky */ 3488206084Srdivackystatic void 3489206084Srdivackysscop_inrec_er(struct sscop *sscop, struct sscop_msg *msg) 3490208600Srdivacky{ 3491207619Srdivacky union pdu pdu; 3492198092Srdivacky 3493198092Srdivacky pdu.sscop_null = MBUF_STRIP32(msg->m); 3494206084Srdivacky 3495206084Srdivacky if(!m_detect_retransmission(sscop, msg)) { 3496206084Srdivacky MAAL_ERROR(sscop, 'L', 0); 3497206084Srdivacky } 3498199482Srdivacky 3499198092Srdivacky SSCOP_MSG_FREE(msg); 3500252723Sdim} 3501218893Sdim 3502263509Sdim/* 3503206084Srdivacky * p 59: IN_REC_PEND && BGN PDU 3504208600Srdivacky * arg is pdu (freed). 3505206084Srdivacky * no uui 3506218893Sdim */ 3507198092Srdivackystatic void 3508198092Srdivackysscop_inrec_bgn(struct sscop *sscop, struct sscop_msg *msg) 3509207619Srdivacky{ 3510207619Srdivacky union pdu pdu; 3511207619Srdivacky 3512207619Srdivacky pdu.sscop_null = MBUF_STRIP32(msg->m); 3513207619Srdivacky 3514207619Srdivacky if(m_detect_retransmission(sscop, msg)) { 3515207619Srdivacky MAAL_ERROR(sscop, 'B', 0); 3516198092Srdivacky SSCOP_MSG_FREE(msg); 3517206084Srdivacky return; 3518206084Srdivacky } 3519206084Srdivacky (void)MBUF_STRIP32(msg->m); 3520206084Srdivacky 3521218893Sdim sscop->vt_ms = pdu.sscop_ns; 3522208600Srdivacky AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0); 3523263509Sdim AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0); 3524263509Sdim 3525263509Sdim sscop_set_state(sscop, SSCOP_IN_PEND); 3526263509Sdim} 3527263509Sdim 3528263509Sdim/* 3529263509Sdim * p 59: IN_REC_PEND && BGAK PDU 3530263509Sdim * arg is pdu (freed) 3531263509Sdim * no uui 3532263509Sdim */ 3533263509Sdimstatic void 3534263509Sdimsscop_inrec_bgak(struct sscop *sscop, struct sscop_msg *msg) 3535208600Srdivacky{ 3536263509Sdim MAAL_ERROR(sscop, 'C', 0); 3537263509Sdim SSCOP_MSG_FREE(msg); 3538263509Sdim} 3539263509Sdim 3540263509Sdim/* 3541207619Srdivacky * p 59: IN_REC_PEND && ERAK PDU 3542218893Sdim * arg is pdu (freed) 3543208600Srdivacky * no uui 3544263509Sdim */ 3545207619Srdivackystatic void 3546206084Srdivackysscop_inrec_erak(struct sscop *sscop, struct sscop_msg *msg) 3547198092Srdivacky{ 3548206084Srdivacky MAAL_ERROR(sscop, 'M', 0); 3549207619Srdivacky SSCOP_MSG_FREE(msg); 3550208600Srdivacky} 3551198092Srdivacky 3552206084Srdivacky/* 3553198092Srdivacky * p 60: READY && RESYNC request 3554208600Srdivacky * arg is UU 3555206084Srdivacky */ 3556206084Srdivackystatic void 3557206084Srdivackysscop_ready_sync_req(struct sscop *sscop, struct sscop_msg *uu) 3558206084Srdivacky{ 3559206084Srdivacky SET_UU(uu_rs, uu); 3560206084Srdivacky 3561218893Sdim m_reset_data_xfer_timers(sscop); 3562208600Srdivacky sscop->vt_cc = 1; 3563208600Srdivacky sscop->vt_sq++; 3564206084Srdivacky m_initialize_mr(sscop); 3565218893Sdim send_rs(sscop, 0, sscop->uu_rs); 3566208600Srdivacky m_release_buffers(sscop); 3567207619Srdivacky TIMER_RESTART(sscop, cc); 3568207619Srdivacky 3569206084Srdivacky sscop_set_state(sscop, SSCOP_OUT_RESYNC_PEND); 3570198092Srdivacky} 3571198092Srdivacky 3572206084Srdivacky 3573208600Srdivacky/* 3574198092Srdivacky * p 60: READY && AA-RELEASE.request 3575198092Srdivacky * arg is uu. 3576198092Srdivacky */ 3577208600Srdivackystatic void 3578226890Sdimsscop_ready_release_req(struct sscop *sscop, struct sscop_msg *uu) 3579226890Sdim{ 3580226890Sdim SET_UU(uu_end, uu); 3581226890Sdim 3582226890Sdim m_reset_data_xfer_timers(sscop); 3583226890Sdim sscop->vt_cc = 1; 3584226890Sdim send_end(sscop, 0, sscop->uu_end); 3585226890Sdim m_prepare_retrieval(sscop); 3586226890Sdim TIMER_RESTART(sscop, cc); 3587226890Sdim 3588235633Sdim sscop_set_state(sscop, SSCOP_OUT_DIS_PEND); 3589226890Sdim} 3590226890Sdim 3591226890Sdim/* 3592252723Sdim * p 61: READY && ER PDU 3593226890Sdim * arg is pdu (freed). 3594226890Sdim */ 3595226890Sdimstatic void 3596226890Sdimsscop_ready_er(struct sscop *sscop, struct sscop_msg *msg) 3597198092Srdivacky{ 3598198092Srdivacky union pdu pdu; 3599226890Sdim 3600226890Sdim pdu.sscop_null = MBUF_STRIP32(msg->m); 3601252723Sdim 3602226890Sdim if(m_detect_retransmission(sscop, msg)) { 3603226890Sdim TIMER_RESTART(sscop, nr); 3604226890Sdim send_erak(sscop); 3605226890Sdim } else { 3606226890Sdim m_reset_data_xfer_timers(sscop); 3607226890Sdim sscop->vt_ms = pdu.sscop_ns; 3608226890Sdim m_prepare_recovery(sscop); 3609226890Sdim m_deliver_data(sscop); 3610226890Sdim 3611226890Sdim AAL_SIG(sscop, SSCOP_RECOVER_indication); 3612226890Sdim 3613226890Sdim sscop_set_state(sscop, SSCOP_IN_REC_PEND); 3614226890Sdim } 3615226890Sdim 3616226890Sdim SSCOP_MSG_FREE(msg); 3617198092Srdivacky} 3618198092Srdivacky 3619252723Sdim/* 3620198092Srdivacky * p 61: READY && BGN PDU 3621218893Sdim * arg is pdu (freed) 3622218893Sdim */ 3623218893Sdimstatic void 3624208600Srdivackysscop_ready_bgn(struct sscop *sscop, struct sscop_msg *msg) 3625218893Sdim{ 3626218893Sdim union pdu pdu; 3627205219Srdivacky 3628205408Srdivacky pdu.sscop_null = MBUF_STRIP32(msg->m); 3629205408Srdivacky 3630205408Srdivacky if(m_detect_retransmission(sscop, msg)) { 3631205408Srdivacky TIMER_RESTART(sscop, nr); 3632198092Srdivacky send_bgak(sscop, sscop->uu_bgak); 3633198092Srdivacky SSCOP_MSG_FREE(msg); 3634199482Srdivacky return; 3635198092Srdivacky } 3636198092Srdivacky (void)MBUF_STRIP32(msg->m); 3637252723Sdim 3638198092Srdivacky m_reset_data_xfer_timers(sscop); 3639252723Sdim sscop->vt_ms = pdu.sscop_ns; 3640252723Sdim 3641252723Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0); 3642252723Sdim AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0); 3643252723Sdim 3644252723Sdim m_prepare_retrieval(sscop); 3645252723Sdim 3646198092Srdivacky sscop_set_state(sscop, SSCOP_IN_PEND); 3647252723Sdim} 3648198092Srdivacky 3649198092Srdivacky/* 3650263509Sdim * p 62: READY && ENDAK PDU 3651263509Sdim * arg is pdu (freed) 3652198092Srdivacky */ 3653198092Srdivackystatic void 3654263509Sdimsscop_ready_endak(struct sscop *sscop, struct sscop_msg *msg) 3655263509Sdim{ 3656218893Sdim m_reset_data_xfer_timers(sscop); 3657206084Srdivacky MAAL_ERROR(sscop, 'F', 0); 3658206084Srdivacky AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 3659252723Sdim m_prepare_retrieval(sscop); 3660198092Srdivacky SSCOP_MSG_FREE(msg); 3661198092Srdivacky sscop_set_state(sscop, SSCOP_IDLE); 3662252723Sdim} 3663252723Sdim 3664252723Sdim/* 3665207619Srdivacky * p 62: READY && BGREJ PDU 3666198092Srdivacky * arg is pdu (freed) 3667198092Srdivacky */ 3668218893Sdimstatic void 3669218893Sdimsscop_ready_bgrej(struct sscop *sscop, struct sscop_msg *msg) 3670218893Sdim{ 3671252723Sdim m_reset_data_xfer_timers(sscop); 3672218893Sdim MAAL_ERROR(sscop, 'D', 0); 3673218893Sdim AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 3674218893Sdim m_prepare_retrieval(sscop); 3675226890Sdim SSCOP_MSG_FREE(msg); 3676218893Sdim sscop_set_state(sscop, SSCOP_IDLE); 3677218893Sdim} 3678218893Sdim 3679218893Sdim/* 3680218893Sdim * p 62: READY && RS PDU 3681198092Srdivacky * arg is pdu (freed) 3682206084Srdivacky */ 3683207619Srdivackystatic void 3684207619Srdivackysscop_ready_rs(struct sscop *sscop, struct sscop_msg *msg) 3685207619Srdivacky{ 3686226890Sdim union pdu pdu; 3687198092Srdivacky 3688206084Srdivacky pdu.sscop_null = MBUF_STRIP32(msg->m); 3689206084Srdivacky 3690207619Srdivacky if(m_detect_retransmission(sscop, msg)) { 3691206084Srdivacky SSCOP_MSG_FREE(msg); 3692198092Srdivacky TIMER_RESTART(sscop, nr); 3693198092Srdivacky send_rsak(sscop); 3694207619Srdivacky return; 3695198092Srdivacky } 3696207619Srdivacky (void)MBUF_STRIP32(msg->m); 3697206084Srdivacky 3698198092Srdivacky m_reset_data_xfer_timers(sscop); 3699198092Srdivacky sscop->vt_ms = pdu.sscop_ns; 3700198092Srdivacky AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_indication, msg, pdu.sscop_pl, 0); 3701207619Srdivacky m_prepare_retrieval(sscop); 3702198092Srdivacky 3703198092Srdivacky sscop_set_state(sscop, SSCOP_IN_RESYNC_PEND); 3704207619Srdivacky} 3705198092Srdivacky 3706226890Sdim/* 3707226890Sdim * p 62: READY && END PDU 3708226890Sdim * arg is pdu (freed) 3709226890Sdim */ 3710252723Sdimstatic void 3711226890Sdimsscop_ready_end(struct sscop *sscop, struct sscop_msg *msg) 3712226890Sdim{ 3713207619Srdivacky union pdu pdu; 3714207619Srdivacky 3715198092Srdivacky pdu.sscop_null = MBUF_STRIP32(msg->m); 3716218893Sdim (void)MBUF_STRIP32(msg->m); 3717252723Sdim 3718218893Sdim m_reset_data_xfer_timers(sscop); 3719263509Sdim send_endak(sscop); 3720207619Srdivacky AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication, 3721207619Srdivacky msg, pdu.sscop_pl, (u_int)pdu.sscop_s); 3722207619Srdivacky m_prepare_retrieval(sscop); 3723207619Srdivacky 3724207619Srdivacky sscop_set_state(sscop, SSCOP_IDLE); 3725198092Srdivacky} 3726207619Srdivacky 3727207619Srdivacky/* 3728207619Srdivacky * p 63: READY && POLL expiry 3729207619Srdivacky */ 3730208600Srdivackystatic void 3731207619Srdivackysscop_ready_tpoll(struct sscop *sscop, struct sscop_msg *unused __unused) 3732207619Srdivacky{ 3733207619Srdivacky sscop->vt_ps++; 3734207619Srdivacky send_poll(sscop); 3735218893Sdim sscop->vt_pd = 0; 3736218893Sdim m_set_poll_timer(sscop); 3737207619Srdivacky} 3738235633Sdim 3739207619Srdivacky/* 3740218893Sdim * p 63: READY && KEEP_ALIVE expiry 3741218893Sdim */ 3742207619Srdivackystatic void 3743235633Sdimsscop_ready_tka(struct sscop *sscop, struct sscop_msg *unused __unused) 3744207619Srdivacky{ 3745207619Srdivacky sscop->vt_ps++; 3746207619Srdivacky send_poll(sscop); 3747207619Srdivacky sscop->vt_pd = 0; 3748198092Srdivacky m_set_poll_timer(sscop); 3749207619Srdivacky} 3750207619Srdivacky 3751207619Srdivacky/* 3752198092Srdivacky * p 63: READY && IDLE expiry 3753207619Srdivacky */ 3754207619Srdivackystatic void 3755198092Srdivackysscop_ready_tidle(struct sscop *sscop, struct sscop_msg *unused __unused) 3756198092Srdivacky{ 3757198092Srdivacky TIMER_RESTART(sscop, nr); 3758207619Srdivacky sscop->vt_ps++; 3759207619Srdivacky send_poll(sscop); 3760218893Sdim sscop->vt_pd = 0; 3761218893Sdim m_set_poll_timer(sscop); 3762207619Srdivacky} 3763207619Srdivacky 3764207619Srdivacky/* 3765207619Srdivacky * p 63: READY && NO_RESPONSE expiry 3766207619Srdivacky * no arg 3767252723Sdim */ 3768207619Srdivackystatic void 3769207619Srdivackysscop_ready_nr(struct sscop *sscop, struct sscop_msg *unused __unused) 3770207619Srdivacky{ 3771207619Srdivacky m_reset_data_xfer_timers(sscop); 3772207619Srdivacky MAAL_ERROR(sscop, 'P', 0); 3773218893Sdim FREE_UU(uu_end); 3774207619Srdivacky send_end(sscop, 1, NULL); 3775207619Srdivacky AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1); 3776207619Srdivacky m_prepare_retrieval(sscop); 3777207619Srdivacky sscop_set_state(sscop, SSCOP_IDLE); 3778207619Srdivacky} 3779207619Srdivacky 3780207619Srdivacky/* 3781207619Srdivacky * p 63: READY && AA-DATA.request 3782207619Srdivacky * arg is message (queued). 3783207619Srdivacky */ 3784207619Srdivackystatic void 3785207619Srdivackysscop_ready_userdata(struct sscop *sscop, struct sscop_msg *msg) 3786218893Sdim{ 3787207619Srdivacky MSGQ_APPEND(&sscop->xq, msg); 3788207619Srdivacky 3789207619Srdivacky sscop_signal(sscop, SIG_PDU_Q, msg); 3790218893Sdim} 3791207619Srdivacky 3792218893Sdim/* 3793207619Srdivacky * p 64: READY && SD PDU queued up 3794235633Sdim * arg is unused. 3795207619Srdivacky */ 3796235633Sdimstatic void 3797207619Srdivackysscop_ready_pduq(struct sscop *sscop, struct sscop_msg *unused __unused) 3798207619Srdivacky{ 3799207619Srdivacky struct sscop_msg *msg; 3800207619Srdivacky 3801207619Srdivacky if(sscop->rxq != 0) { 3802207619Srdivacky TAILQ_FOREACH(msg, &sscop->xbuf, link) 3803207619Srdivacky if(msg->rexmit) 3804207619Srdivacky break; 3805207619Srdivacky ASSERT(msg != NULL); 3806207619Srdivacky msg->rexmit = 0; 3807235633Sdim sscop->rxq--; 3808235633Sdim send_sd(sscop, msg->m, msg->seqno); 3809207619Srdivacky msg->poll_seqno = sscop->vt_ps; 3810207619Srdivacky if(sscop->poll_after_rex && sscop->rxq == 0) 3811207619Srdivacky goto poll; /* -> A */ 3812235633Sdim else 3813235633Sdim goto maybe_poll; /* -> B */ 3814207619Srdivacky 3815207619Srdivacky } 3816207619Srdivacky if(MSGQ_EMPTY(&sscop->xq)) 3817207619Srdivacky return; 3818235633Sdim 3819207619Srdivacky if(sscop->vt_s >= sscop->vt_ms) { 3820207619Srdivacky /* Send windows closed */ 3821207619Srdivacky TIMER_STOP(sscop, idle); 3822207619Srdivacky TIMER_RESTART(sscop, nr); 3823207619Srdivacky goto poll; /* -> A */ 3824206084Srdivacky 3825212904Sdim } else { 3826206084Srdivacky msg = MSGQ_GET(&sscop->xq); 3827252723Sdim msg->seqno = sscop->vt_s; 3828206084Srdivacky send_sd(sscop, msg->m, msg->seqno); 3829206084Srdivacky msg->poll_seqno = sscop->vt_ps; 3830206084Srdivacky sscop->vt_s++; 3831206084Srdivacky MSGQ_APPEND(&sscop->xbuf, msg); 3832206084Srdivacky goto maybe_poll; /* -> B */ 3833206084Srdivacky } 3834206084Srdivacky 3835212904Sdim /* 3836206084Srdivacky * p 65: Poll handling 3837206084Srdivacky */ 3838206084Srdivacky maybe_poll: /* label B */ 3839206084Srdivacky sscop->vt_pd++; 3840206084Srdivacky if(TIMER_ISACT(sscop, poll)) { 3841206084Srdivacky if(sscop->vt_pd < sscop->maxpd) 3842207619Srdivacky return; 3843207619Srdivacky } else { 3844207619Srdivacky if(TIMER_ISACT(sscop, idle)) { 3845263509Sdim TIMER_STOP(sscop, idle); 3846207619Srdivacky TIMER_RESTART(sscop, nr); 3847207619Srdivacky } else { 3848207619Srdivacky TIMER_STOP(sscop, ka); 3849207619Srdivacky } 3850206084Srdivacky if(sscop->vt_pd < sscop->maxpd) { 3851252723Sdim TIMER_RESTART(sscop, poll); 3852218893Sdim return; 3853206084Srdivacky } 3854208600Srdivacky } 3855208600Srdivacky poll: /* label A */ 3856208600Srdivacky sscop->vt_ps++; 3857218893Sdim send_poll(sscop); 3858218893Sdim sscop->vt_pd = 0; 3859207619Srdivacky TIMER_RESTART(sscop, poll); 3860207619Srdivacky} 3861207619Srdivacky 3862221345Sdim/* 3863263509Sdim * p 67: common recovery start 3864263509Sdim */ 3865207619Srdivackystatic void 3866207619Srdivackysscop_recover(struct sscop *sscop) 3867221345Sdim{ 3868221345Sdim sscop->vt_cc = 1; 3869221345Sdim sscop->vt_sq++; 3870252723Sdim 3871245431Sdim m_initialize_mr(sscop); 3872221345Sdim send_er(sscop); 3873245431Sdim m_prepare_recovery(sscop); 3874221345Sdim 3875221345Sdim TIMER_RESTART(sscop, cc); 3876223017Sdim 3877221345Sdim sscop_set_state(sscop, SSCOP_OUT_REC_PEND); 3878221345Sdim} 3879206084Srdivacky 3880206084Srdivacky/* 3881206084Srdivacky * p 66: READY && SD PDU 3882206084Srdivacky * arg is received message. 3883206084Srdivacky */ 3884206084Srdivackystatic void 3885252723Sdimsscop_ready_sd(struct sscop *sscop, struct sscop_msg *msg) 3886206084Srdivacky{ 3887252723Sdim union pdu pdu; 3888263509Sdim u_int sn; 3889263509Sdim 3890206084Srdivacky pdu.sscop_null = MBUF_STRIP32(msg->m); 3891206084Srdivacky msg->seqno = pdu.sscop_ns; 3892198092Srdivacky 3893205408Srdivacky /* Fix padding */ 3894205408Srdivacky MBUF_UNPAD(msg->m, pdu.sscop_pl); 3895226890Sdim 3896226890Sdim if(msg->seqno >= sscop->vr_mr) { 3897226890Sdim /* message outside window */ 3898199482Srdivacky if(sscop->vr_h < sscop->vr_mr) { 3899205219Srdivacky send_ustat(sscop, sscop->vr_h, sscop->vr_mr, -1); 3900205219Srdivacky sscop->vr_h = sscop->vr_mr; 3901205219Srdivacky } 3902205219Srdivacky SSCOP_MSG_FREE(msg); 3903205219Srdivacky return; 3904199482Srdivacky } 3905199482Srdivacky 3906199482Srdivacky if(msg->seqno == sscop->vr_r) { 3907199482Srdivacky if(msg->seqno == sscop->vr_h) { 3908199482Srdivacky sscop->vr_r = msg->seqno + 1; 3909208600Srdivacky sscop->vr_h = msg->seqno + 1; 3910208600Srdivacky 3911235633Sdim AAL_DATA(sscop, SSCOP_DATA_indication, 3912235633Sdim msg->m, msg->seqno); 3913235633Sdim msg->m = NULL; 3914235633Sdim SSCOP_MSG_FREE(msg); 3915235633Sdim 3916199482Srdivacky return; 3917199482Srdivacky } 3918199482Srdivacky for(;;) { 3919199482Srdivacky AAL_DATA(sscop, SSCOP_DATA_indication, 3920195341Sed msg->m, msg->seqno); 3921199482Srdivacky msg->m = NULL; 3922199482Srdivacky SSCOP_MSG_FREE(msg); 3923221345Sdim 3924221345Sdim sscop->vr_r++; 3925235633Sdim if((msg = MSGQ_PEEK(&sscop->rbuf)) == NULL) 3926198092Srdivacky break; 3927235633Sdim sn = msg->seqno; 3928235633Sdim ASSERT(sn >= sscop->vr_r); 3929235633Sdim if(sn != sscop->vr_r) 3930198092Srdivacky break; 3931210299Sed msg = MSGQ_GET(&sscop->rbuf); 3932221345Sdim } 3933205219Srdivacky return; 3934206084Srdivacky } 3935205219Srdivacky 3936205219Srdivacky /* Messages were lost */ 3937205219Srdivacky 3938263509Sdim /* XXX Flow control */ 3939235633Sdim if(msg->seqno == sscop->vr_h) { 3940198092Srdivacky QINSERT(&sscop->rbuf, msg); 3941199482Srdivacky sscop->vr_h++; 3942205219Srdivacky return; 3943205219Srdivacky } 3944199482Srdivacky if(sscop->vr_h < msg->seqno) { 3945199482Srdivacky QINSERT(&sscop->rbuf, msg); 3946198092Srdivacky send_ustat(sscop, sscop->vr_h, msg->seqno, -1); 3947205219Srdivacky sscop->vr_h = msg->seqno + 1; 3948205219Srdivacky return; 3949205219Srdivacky } 3950205219Srdivacky 3951198092Srdivacky if(QFIND(&sscop->rbuf, msg->seqno) == NULL) { 3952205219Srdivacky QINSERT(&sscop->rbuf, msg); 3953199482Srdivacky return; 3954221345Sdim } 3955221345Sdim 3956221345Sdim /* error: start recovery */ 3957221345Sdim SSCOP_MSG_FREE(msg); 3958235633Sdim m_reset_data_xfer_timers(sscop); 3959198092Srdivacky MAAL_ERROR(sscop, 'Q', 0); 3960205219Srdivacky sscop_recover(sscop); 3961210299Sed} 3962221345Sdim 3963205219Srdivacky/* 3964205219Srdivacky * p 67: READY && POLL PDU 3965235633Sdim */ 3966206084Srdivackystatic void 3967205219Srdivackysscop_ready_poll(struct sscop *sscop, struct sscop_msg *msg) 3968235633Sdim{ 3969235633Sdim union pdu pdu; 3970199482Srdivacky union seqno seqno; 3971263509Sdim u_int sn, nps; 3972235633Sdim struct SSCOP_MBUF_T *m; 3973199482Srdivacky 3974199482Srdivacky pdu.sscop_null = MBUF_STRIP32(msg->m); 3975199482Srdivacky seqno.sscop_null = MBUF_STRIP32(msg->m); 3976199482Srdivacky 3977199482Srdivacky if((u_int)pdu.sscop_ns < sscop->vr_h) { 3978205219Srdivacky SSCOP_MSG_FREE(msg); 3979205219Srdivacky m_reset_data_xfer_timers(sscop); 3980235633Sdim MAAL_ERROR(sscop, 'Q', 0); 3981205219Srdivacky sscop_recover(sscop); 3982205219Srdivacky return; 3983205219Srdivacky } 3984205219Srdivacky nps = seqno.sscop_n; 3985205219Srdivacky 3986221345Sdim if((u_int)pdu.sscop_ns > sscop->vr_mr) 3987221345Sdim sscop->vr_h = sscop->vr_mr; 3988221345Sdim else 3989221345Sdim sscop->vr_h = pdu.sscop_ns; 3990235633Sdim 3991198092Srdivacky SSCOP_MSG_FREE(msg); 3992205219Srdivacky 3993210299Sed /* build stat pdu */ 3994221345Sdim if((m = MBUF_ALLOC(sscop->maxstat * 4 + 12)) == NULL) { 3995263509Sdim FAILURE("sscop: cannot allocate STAT"); 3996263509Sdim return; 3997263509Sdim } 3998263509Sdim sn = sscop->vr_r; 3999263509Sdim 4000263509Sdim while(sn != sscop->vr_h) { 4001263509Sdim /* loop through burst we already have */ 4002263509Sdim for(;;) { 4003263509Sdim if(sn >= sscop->vr_h) { 4004263509Sdim seqno.sscop_null = 0; 4005263509Sdim seqno.sscop_n = sn; 4006205219Srdivacky MBUF_APPEND32(m, seqno.sscop_null); 4007263509Sdim goto out; 4008235633Sdim } 4009198092Srdivacky if(QFIND(&sscop->rbuf, sn) == NULL) 4010193326Sed break; 4011193326Sed sn++; 4012212904Sdim } 4013198092Srdivacky 4014198092Srdivacky /* start of a hole */ 4015198092Srdivacky seqno.sscop_null = 0; 4016198092Srdivacky seqno.sscop_n = sn; 4017263509Sdim MBUF_APPEND32(m, seqno.sscop_null); 4018252723Sdim if(MBUF_LEN(m)/4 >= sscop->maxstat) { 4019263509Sdim send_stat(sscop, nps, m); 4020263509Sdim if((m = MBUF_ALLOC(sscop->maxstat * 4 + 12)) == NULL) { 4021198092Srdivacky FAILURE("sscop: cannot allocate STAT"); 4022198092Srdivacky return; 4023198092Srdivacky } 4024212904Sdim seqno.sscop_null = 0; 4025245431Sdim seqno.sscop_n = sn; 4026245431Sdim MBUF_APPEND32(m, seqno.sscop_null); 4027245431Sdim } 4028245431Sdim do { 4029245431Sdim sn++; 4030245431Sdim } while(sn < sscop->vr_h && !QFIND(&sscop->rbuf, sn)); 4031245431Sdim seqno.sscop_null = 0; 4032263509Sdim seqno.sscop_n = sn; 4033263509Sdim MBUF_APPEND32(m, seqno.sscop_null); 4034245431Sdim } 4035245431Sdim out: 4036245431Sdim send_stat(sscop, nps, m); 4037245431Sdim} 4038245431Sdim 4039245431Sdim/* 4040245431Sdim * p 69: READY && USTAT PDU 4041245431Sdim * arg is msg (freed) 4042245431Sdim */ 4043198092Srdivackystatic void 4044198092Srdivackysscop_ready_ustat(struct sscop *sscop, struct sscop_msg *msg) 4045198092Srdivacky{ 4046245431Sdim union pdu pdu; 4047235633Sdim union seqno nmr, sq1, sq2; 4048193326Sed u_int cnt; 4049198092Srdivacky 4050193326Sed pdu.sscop_null = MBUF_STRIP32(msg->m); 4051245431Sdim nmr.sscop_null = MBUF_STRIP32(msg->m); 4052198092Srdivacky sq2.sscop_null = MBUF_STRIP32(msg->m); 4053198092Srdivacky sq1.sscop_null = MBUF_STRIP32(msg->m); 4054193326Sed 4055198092Srdivacky SSCOP_MSG_FREE(msg); 4056193326Sed 4057198092Srdivacky cnt = sq1.sscop_n - sq2.sscop_n; 4058193326Sed 4059245431Sdim if((u_int)pdu.sscop_ns < sscop->vt_a || (u_int)pdu.sscop_ns >= sscop->vt_s) { 4060193326Sed VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg, 4061198092Srdivacky "USTAT: N(R) outside VT(A)...VT(S)-1: N(R)=%u VT(A)=%u " 4062198092Srdivacky "VT(S)=%u", (u_int)pdu.sscop_ns, sscop->vt_a, sscop->vt_s)); 4063193326Sed goto err_f; 4064193326Sed } 4065198092Srdivacky 4066203955Srdivacky /* Acknowledge all messages between VT(A) and N(R)-1. N(R) is the new 4067193326Sed * next in sequence-SD-number of the receiver and means, it has all 4068212904Sdim * messages below N(R). Remove all message below N(R) from the 4069212904Sdim * transmission buffer. It may already be removed because of an 4070212904Sdim * earlier selective ACK in a STAT message. 4071212904Sdim */ 4072212904Sdim while((msg = MSGQ_PEEK(&sscop->xbuf)) != NULL && msg->seqno < (u_int)pdu.sscop_ns) { 4073193326Sed ASSERT(msg->seqno >= sscop->vt_a); 4074198092Srdivacky MSGQ_REMOVE(&sscop->xbuf, msg); 4075193326Sed SSCOP_MSG_FREE(msg); 4076193326Sed } 4077198092Srdivacky 4078245431Sdim /* Update the in-sequence acknowledge and the send window */ 4079212904Sdim sscop->vt_a = pdu.sscop_ns; 4080198092Srdivacky sscop->vt_ms = nmr.sscop_n; 4081212904Sdim 4082212904Sdim /* check, that the range of requested re-transmissions is between 4083212904Sdim * the in-sequence-ack and the highest up-to-now transmitted SD 4084212904Sdim */ 4085212904Sdim if(sq1.sscop_n >= sq2.sscop_n 4086212904Sdim || (u_int)sq1.sscop_n < sscop->vt_a 4087193326Sed || (u_int)sq2.sscop_n >= sscop->vt_s) { 4088212904Sdim VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg, 4089198092Srdivacky "USTAT: seq1 or seq2 outside VT(A)...VT(S)-1 or seq1>=seq2:" 4090263509Sdim " seq1=%u seq2=%u VT(A)=%u VT(S)=%u", 4091263509Sdim sq1.sscop_n, sq2.sscop_n, sscop->vt_a, sscop->vt_s)); 4092263509Sdim goto err_f; 4093263509Sdim } 4094263509Sdim 4095263509Sdim /* 4096206084Srdivacky * Retransmit all messages from seq1 to seq2-1 4097206084Srdivacky */ 4098198092Srdivacky do { 4099210299Sed /* 4100210299Sed * The message may not be in the transmit buffer if it was 4101210299Sed * already acked by a STAT. This means, the receiver is 4102210299Sed * confused. 4103206084Srdivacky */ 4104206084Srdivacky if((msg = QFIND(&sscop->xbuf, sq1.sscop_n)) == NULL) { 4105206084Srdivacky VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg, 4106206084Srdivacky "USTAT: message %u not found in xmit buffer", 4107206084Srdivacky sq1.sscop_n)); 4108206084Srdivacky goto err_f; 4109206084Srdivacky } 4110206084Srdivacky 4111206084Srdivacky /* 4112206084Srdivacky * If it is not yet in the re-transmission queue, put it there 4113206084Srdivacky */ 4114198092Srdivacky if(!msg->rexmit) { 4115206084Srdivacky msg->rexmit = 1; 4116206084Srdivacky sscop->rxq++; 4117206084Srdivacky sscop_signal(sscop, SIG_PDU_Q, msg); 4118206084Srdivacky } 4119206084Srdivacky sq1.sscop_n++; 4120206084Srdivacky } while(sq1.sscop_n != sq2.sscop_n); 4121206084Srdivacky 4122210299Sed /* 4123210299Sed * report the re-transmission to the management 4124210299Sed */ 4125206084Srdivacky MAAL_ERROR(sscop, 'V', cnt); 4126206084Srdivacky return; 4127218893Sdim 4128206084Srdivacky err_f: 4129193326Sed m_reset_data_xfer_timers(sscop); 4130193326Sed MAAL_ERROR(sscop, 'T', 0); 4131193326Sed sscop_recover(sscop); 4132193326Sed} 4133193326Sed 4134193326Sed/* 4135193326Sed * p 70: READY && STAT PDU 4136193326Sed * arg is msg (freed). 4137212904Sdim */ 4138212904Sdimstatic void 4139212904Sdimsscop_ready_stat(struct sscop *sscop, struct sscop_msg *msg) 4140212904Sdim{ 4141212904Sdim union pdu pdu; 4142198092Srdivacky union seqno nps, nmr; 4143212904Sdim u_int len, seq1, seq2, cnt; 4144212904Sdim struct sscop_msg *m; 4145212904Sdim 4146212904Sdim pdu.sscop_null = MBUF_STRIP32(msg->m); 4147212904Sdim nmr.sscop_null = MBUF_STRIP32(msg->m); 4148193326Sed nps.sscop_null = MBUF_STRIP32(msg->m); 4149212904Sdim 4150212904Sdim len = MBUF_LEN(msg->m) / 4; 4151212904Sdim 4152212904Sdim if((u_int)nps.sscop_n < sscop->vt_pa 4153212904Sdim || (u_int)nps.sscop_n > sscop->vt_ps) { 4154193326Sed SSCOP_MSG_FREE(msg); 4155212904Sdim m_reset_data_xfer_timers(sscop); 4156212904Sdim MAAL_ERROR(sscop, 'R', 0); 4157212904Sdim sscop_recover(sscop); 4158212904Sdim return; 4159212904Sdim } 4160212904Sdim 4161212904Sdim if((u_int)pdu.sscop_ns < sscop->vt_a 4162212904Sdim || (u_int)pdu.sscop_ns > sscop->vt_s) { 4163212904Sdim /* 4164212904Sdim * The in-sequence acknowledge, i.e. the receivers's next 4165212904Sdim * expected in-sequence msg is outside the window between 4166212904Sdim * the transmitters in-sequence ack and highest seqno - 4167212904Sdim * the receiver seems to be confused. 4168212904Sdim */ 4169252723Sdim VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg, 4170212904Sdim "STAT: N(R) outside VT(A)...VT(S)-1: N(R)=%u VT(A)=%u " 4171193326Sed "VT(S)=%u", (u_int)pdu.sscop_ns, sscop->vt_a, sscop->vt_s)); 4172212904Sdim err_H: 4173198092Srdivacky SSCOP_MSG_FREE(msg); 4174212904Sdim m_reset_data_xfer_timers(sscop); 4175212904Sdim MAAL_ERROR(sscop, 'S', 0); 4176212904Sdim sscop_recover(sscop); 4177219077Sdim return; 4178219077Sdim } 4179219077Sdim 4180212904Sdim /* Acknowledge all messages between VT(A) and N(R)-1. N(R) is the new 4181212904Sdim * next in sequence-SD-number of the receiver and means, it has all 4182193326Sed * messages below N(R). Remove all message below N(R) from the 4183212904Sdim * transmission buffer. It may already be removed because of an 4184193326Sed * earlier selective ACK in a STAT message. 4185212904Sdim */ 4186212904Sdim while((m = MSGQ_PEEK(&sscop->xbuf)) != NULL 4187212904Sdim && m->seqno < (u_int)pdu.sscop_ns) { 4188198092Srdivacky ASSERT(m->seqno >= sscop->vt_a); 4189212904Sdim MSGQ_REMOVE(&sscop->xbuf, m); 4190212904Sdim SSCOP_MSG_FREE(m); 4191212904Sdim } 4192212904Sdim 4193212904Sdim /* 4194212904Sdim * Update in-sequence ack, poll-ack and send window. 4195212904Sdim */ 4196212904Sdim sscop->vt_a = pdu.sscop_ns; 4197212904Sdim sscop->vt_pa = nps.sscop_n; 4198212904Sdim sscop->vt_ms = nmr.sscop_n; 4199193326Sed 4200212904Sdim cnt = 0; 4201212904Sdim if(len > 1) { 4202212904Sdim seq1 = MBUF_GET32(msg->m); 4203212904Sdim len--; 4204212904Sdim if(seq1 >= sscop->vt_s) { 4205212904Sdim VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg, 4206212904Sdim "STAT: seq1 >= VT(S): seq1=%u VT(S)=%u", 4207212904Sdim seq1, sscop->vt_s)); 4208212904Sdim goto err_H; 4209226890Sdim } 4210193326Sed 4211212904Sdim for(;;) { 4212212904Sdim seq2 = MBUF_GET32(msg->m); 4213212904Sdim len--; 4214212904Sdim if(seq1 >= seq2 || seq2 > sscop->vt_s) { 4215212904Sdim VERBERR(sscop, SSCOP_DBG_ERR, (sscop, 4216212904Sdim sscop->aarg, "STAT: seq1 >= seq2 or " 4217212904Sdim "seq2 > VT(S): seq1=%u seq2=%u VT(S)=%u", 4218212904Sdim seq1, seq2, sscop->vt_s)); 4219212904Sdim goto err_H; 4220212904Sdim } 4221212904Sdim 4222212904Sdim do { 4223212904Sdim /* 4224212904Sdim * The receiver requests the re-transmission 4225212904Sdim * of some message, but has acknowledged it 4226212904Sdim * already in an earlier STAT (it isn't in the 4227212904Sdim * transmitt buffer anymore). 4228212904Sdim */ 4229193326Sed if((m = QFIND(&sscop->xbuf, seq1)) == NULL) { 4230212904Sdim VERBERR(sscop, SSCOP_DBG_ERR, 4231212904Sdim (sscop, sscop->aarg, "STAT: message" 4232198092Srdivacky " %u not found in xmit buffer", 4233212904Sdim seq1)); 4234212904Sdim goto err_H; 4235212904Sdim } 4236212904Sdim if(m->poll_seqno < (u_int)nps.sscop_n 4237212904Sdim && (u_int)nps.sscop_n <= sscop->vt_ps) 4238212904Sdim if(!m->rexmit) { 4239212904Sdim m->rexmit = 1; 4240212904Sdim sscop->rxq++; 4241212904Sdim cnt++; 4242212904Sdim sscop_signal(sscop, SIG_PDU_Q, msg); 4243212904Sdim } 4244198092Srdivacky } while(++seq1 < seq2); 4245212904Sdim 4246212904Sdim if(len == 0) 4247212904Sdim break; 4248212904Sdim 4249212904Sdim seq2 = MBUF_GET32(msg->m); 4250212904Sdim len--; 4251212904Sdim 4252212904Sdim if(seq1 >= seq2 || seq2 > sscop->vt_s) { 4253212904Sdim VERBERR(sscop, SSCOP_DBG_ERR, (sscop, 4254212904Sdim sscop->aarg, "STAT: seq1 >= seq2 or " 4255212904Sdim "seq2 > VT(S): seq1=%u seq2=%u VT(S)=%u", 4256212904Sdim seq1, seq2, sscop->vt_s)); 4257223017Sdim goto err_H; 4258212904Sdim } 4259212904Sdim 4260212904Sdim /* OK now the sucessful transmitted messages. Note, that 4261212904Sdim * some messages may already be out of the buffer because 4262212904Sdim * of earlier STATS */ 4263212904Sdim do { 4264212904Sdim if(sscop->clear_buffers) { 4265212904Sdim if((m = QFIND(&sscop->xbuf, seq1)) != NULL) { 4266212904Sdim MSGQ_REMOVE(&sscop->xbuf, m); 4267212904Sdim SSCOP_MSG_FREE(m); 4268212904Sdim } 4269212904Sdim } 4270212904Sdim } while(++seq1 != seq2); 4271212904Sdim 4272212904Sdim if(len == 0) 4273212904Sdim break; 4274212904Sdim } 4275212904Sdim MAAL_ERROR(sscop, 'V', cnt); 4276212904Sdim } 4277212904Sdim SSCOP_MSG_FREE(msg); 4278212904Sdim 4279212904Sdim /* label L: */ 4280212904Sdim if(sscop->vt_s >= sscop->vt_ms) { 4281212904Sdim /* 4282212904Sdim * The receiver has closed the window: report to management 4283212904Sdim */ 4284212904Sdim if(sscop->credit) { 4285212904Sdim sscop->credit = 0; 4286212904Sdim MAAL_ERROR(sscop, 'W', 0); 4287212904Sdim } 4288212904Sdim } else if(!sscop->credit) { 4289212904Sdim /* 4290212904Sdim * The window was forcefully closed above, but 4291212904Sdim * now re-opened. Report to management. 4292212904Sdim */ 4293212904Sdim sscop->credit = 1; 4294212904Sdim MAAL_ERROR(sscop, 'X', 0); 4295212904Sdim } 4296212904Sdim 4297212904Sdim if(TIMER_ISACT(sscop, poll)) { 4298193326Sed TIMER_RESTART(sscop, nr); 4299212904Sdim } else if(!TIMER_ISACT(sscop, idle)) { 4300193326Sed TIMER_STOP(sscop, ka); 4301193326Sed TIMER_STOP(sscop, nr); 4302200583Srdivacky TIMER_RESTART(sscop, idle); 4303200583Srdivacky } 4304200583Srdivacky} 4305210299Sed 4306218893Sdim/* 4307200583Srdivacky * P. 73: any state & UDATA_REQUEST 4308200583Srdivacky * arg is pdu (queued) 4309212904Sdim */ 4310212904Sdimstatic void 4311212904Sdimsscop_udata_req(struct sscop *sscop, struct sscop_msg *msg) 4312212904Sdim{ 4313207619Srdivacky MSGQ_APPEND(&sscop->uxq, msg); 4314207619Srdivacky sscop_signal(sscop, SIG_UPDU_Q, msg); 4315207619Srdivacky} 4316207619Srdivacky 4317207619Srdivacky/* 4318235633Sdim * P. 73: any state & MDATA_REQUEST 4319235633Sdim * arg is pdu (queued) 4320207619Srdivacky */ 4321207619Srdivackystatic void 4322207619Srdivackysscop_mdata_req(struct sscop *sscop, struct sscop_msg *msg) 4323207619Srdivacky{ 4324226890Sdim MSGQ_APPEND(&sscop->mxq, msg); 4325223017Sdim sscop_signal(sscop, SIG_MPDU_Q, msg); 4326223017Sdim} 4327207619Srdivacky 4328207619Srdivacky/* 4329207619Srdivacky * P. 74: any state & UDATA queued 4330207619Srdivacky * no arg. 4331207619Srdivacky */ 4332207619Srdivackystatic void 4333207619Srdivackysscop_upduq(struct sscop *sscop, struct sscop_msg *unused __unused) 4334207619Srdivacky{ 4335207619Srdivacky struct sscop_msg *msg; 4336207619Srdivacky 4337207619Srdivacky if(sscop->ll_busy) 4338207619Srdivacky return; 4339207619Srdivacky while((msg = MSGQ_GET(&sscop->uxq)) != NULL) { 4340207619Srdivacky send_ud(sscop, msg->m); 4341208600Srdivacky msg->m = NULL; 4342218893Sdim SSCOP_MSG_FREE(msg); 4343208600Srdivacky } 4344218893Sdim} 4345218893Sdim 4346218893Sdim/* 4347218893Sdim * P. 74: any state & MDATA queued 4348218893Sdim * no arg. 4349218893Sdim */ 4350218893Sdimstatic void 4351218893Sdimsscop_mpduq(struct sscop *sscop, struct sscop_msg *unused __unused) 4352218893Sdim{ 4353218893Sdim struct sscop_msg *msg; 4354252723Sdim 4355252723Sdim if(sscop->ll_busy) 4356252723Sdim return; 4357252723Sdim while((msg = MSGQ_GET(&sscop->mxq)) != NULL) { 4358218893Sdim send_md(sscop, msg->m); 4359218893Sdim msg->m = NULL; 4360218893Sdim SSCOP_MSG_FREE(msg); 4361218893Sdim } 4362218893Sdim} 4363218893Sdim 4364218893Sdim/* 4365218893Sdim * p 73: MD PDU 4366218893Sdim * arg is PDU 4367218893Sdim */ 4368218893Sdimstatic void 4369218893Sdimsscop_md(struct sscop *sscop, struct sscop_msg *msg) 4370218893Sdim{ 4371218893Sdim union pdu pdu; 4372218893Sdim 4373218893Sdim pdu.sscop_null = MBUF_STRIP32(msg->m); 4374218893Sdim 4375263509Sdim MBUF_UNPAD(msg->m, pdu.sscop_pl); 4376263509Sdim 4377263509Sdim MAAL_DATA(sscop, msg->m); 4378263509Sdim msg->m = NULL; 4379263509Sdim SSCOP_MSG_FREE(msg); 4380263509Sdim} 4381245431Sdim 4382245431Sdim/* 4383218893Sdim * p 73: UD PDU 4384218893Sdim * arg is PDU 4385218893Sdim */ 4386218893Sdimstatic void 4387252723Sdimsscop_ud(struct sscop *sscop, struct sscop_msg *msg) 4388252723Sdim{ 4389245431Sdim union pdu pdu; 4390263509Sdim 4391252723Sdim pdu.sscop_null = MBUF_STRIP32(msg->m); 4392252723Sdim 4393252723Sdim MBUF_UNPAD(msg->m, pdu.sscop_pl); 4394252723Sdim 4395252723Sdim AAL_DATA(sscop, SSCOP_UDATA_indication, msg->m, 0); 4396252723Sdim msg->m = NULL; 4397252723Sdim SSCOP_MSG_FREE(msg); 4398252723Sdim} 4399252723Sdim 4400252723Sdim 4401252723Sdim/* 4402252723Sdim * p 33: IDLE & RETRIEVE 4403252723Sdim * p 39: IN_PEND & RETRIEVE 4404252723Sdim * p 42: OUT_DIS_PEND & RETRIEVE 4405252723Sdim * p 48: IN_RESYNC_PEND & RETRIEVE 4406252723Sdim * p 53: REC_PEND & RETRIEVE 4407218893Sdim * p 58: IN_REC_PEND & RETRIEVE 4408218893Sdim */ 4409218893Sdimstatic void 4410252723Sdimsscop_retrieve(struct sscop *sscop, struct sscop_msg *msg) 4411226890Sdim{ 4412226890Sdim m_data_retrieval(sscop, msg->rexmit); 4413226890Sdim SSCOP_MSG_FREE(msg); 4414226890Sdim} 4415226890Sdim 4416226890Sdim/************************************************************/ 4417226890Sdim/* 4418252723Sdim * GENERAL EVENT HANDLING 4419252723Sdim */ 4420252723Sdim 4421252723Sdim/* 4422226890Sdim * State/event matrix. 4423226890Sdim * 4424226890Sdim * Entries marked with Z are not specified in Q.2110, but are added for 4425226890Sdim * the sake of stability. 4426235633Sdim */ 4427226890Sdimstatic struct { 4428226890Sdim void (*func)(struct sscop *, struct sscop_msg *); 4429226890Sdim int (*cond)(struct sscop *); 4430226890Sdim} state_matrix[SSCOP_NSTATES][SIG_NUM] = { 4431226890Sdim /* SSCOP_IDLE */ { 4432226890Sdim /* SIG_BGN */ { sscop_idle_bgn, NULL }, 4433235633Sdim /* SIG_BGAK */ { sscop_idle_bgak, NULL }, 4434226890Sdim /* SIG_END */ { sscop_idle_end, NULL }, 4435226890Sdim /* SIG_ENDAK */ { sscop_ignore_pdu, NULL }, 4436226890Sdim /* SIG_RS */ { sscop_idle_rs, NULL }, 4437226890Sdim /* SIG_RSAK */ { sscop_idle_rsak, NULL }, 4438245431Sdim /* SIG_BGREJ */ { sscop_idle_bgrej, NULL }, 4439245431Sdim /* SIG_SD */ { sscop_idle_sd, NULL }, 4440226890Sdim /* SIG_ER */ { sscop_idle_er, NULL }, 4441226890Sdim /* SIG_POLL */ { sscop_idle_poll, NULL }, 4442226890Sdim /* SIG_STAT */ { sscop_idle_stat, NULL }, 4443226890Sdim /* SIG_USTAT */ { sscop_idle_ustat, NULL }, 4444226890Sdim /* SIG_UD */ { sscop_ud, NULL }, 4445226890Sdim /* SIG_MD */ { sscop_md, NULL }, 4446226890Sdim /* SIG_ERAK */ { sscop_idle_erak, NULL }, 4447226890Sdim /* SIG_T_CC */ { NULL, NULL }, 4448226890Sdim /* SIG_T_POLL */ { NULL, NULL }, 4449263509Sdim /* SIG_T_KA */ { NULL, NULL }, 4450263509Sdim /* SIG_T_NR */ { NULL, NULL }, 4451263509Sdim /* SIG_T_IDLE */ { NULL, NULL }, 4452263509Sdim /* SIG_PDU_Q */ { sscop_flush_pduq, NULL }, 4453263509Sdim /* SIG_USER_DATA */ { NULL, NULL }, 4454263509Sdim /* SIG_ESTAB_REQ */ { sscop_idle_establish_req, NULL }, 4455263509Sdim /* SIG_ESTAB_RESP */ { NULL, NULL }, 4456252723Sdim /* SIG_RELEASE_REQ */ { NULL, NULL }, 4457252723Sdim /* SIG_RECOVER */ { NULL, NULL }, 4458218893Sdim /* SIG_SYNC_REQ */ { NULL, NULL }, 4459218893Sdim /* SIG_SYNC_RESP */ { NULL, NULL }, 4460218893Sdim /* SIG_UDATA */ { sscop_udata_req, NULL }, 4461218893Sdim /* SIG_MDATA */ { sscop_mdata_req, NULL }, 4462252723Sdim /* SIG_UPDU_Q */ { sscop_upduq, NULL }, 4463252723Sdim /* SIG_MPDU_Q */ { sscop_mpduq, NULL }, 4464200583Srdivacky /* SIG_RETRIEVE */ { sscop_retrieve, NULL }, 4465200583Srdivacky }, 4466245431Sdim /* SSCOP_OUT_PEND */ { 4467245431Sdim /* SIG_BGN */ { sscop_outpend_bgn, NULL }, 4468245431Sdim /* SIG_BGAK */ { sscop_outpend_bgak, NULL }, 4469245431Sdim /* SIG_END */ { sscop_ignore_pdu, NULL }, 4470245431Sdim /* SIG_ENDAK */ { sscop_ignore_pdu, NULL }, 4471245431Sdim /* SIG_RS */ { sscop_ignore_pdu, NULL }, 4472245431Sdim /* SIG_RSAK */ { sscop_ignore_pdu, NULL }, 4473245431Sdim /* SIG_BGREJ */ { sscop_outpend_bgrej, NULL }, 4474245431Sdim /* SIG_SD */ { sscop_ignore_pdu, NULL }, 4475245431Sdim /* SIG_ER */ { sscop_ignore_pdu, NULL }, 4476245431Sdim /* SIG_POLL */ { sscop_ignore_pdu, NULL }, 4477245431Sdim /* SIG_STAT */ { sscop_ignore_pdu, NULL }, 4478245431Sdim /* SIG_USTAT */ { sscop_ignore_pdu, NULL }, 4479245431Sdim /* SIG_UD */ { sscop_ud, NULL }, 4480223017Sdim /* SIG_MD */ { sscop_md, NULL }, 4481245431Sdim /* SIG_ERAK */ { sscop_ignore_pdu, NULL }, 4482245431Sdim /* SIG_T_CC */ { sscop_outpend_tcc, NULL }, 4483245431Sdim /* SIG_T_POLL */ { NULL, NULL }, 4484245431Sdim /* SIG_T_KA */ { NULL, NULL }, 4485245431Sdim /* SIG_T_NR */ { NULL, NULL }, 4486252723Sdim /* SIG_T_IDLE */ { NULL, NULL }, 4487245431Sdim /* SIG_PDU_Q */ { sscop_flush_pduq, NULL }, 4488223017Sdim /* SIG_USER_DATA */ { NULL, NULL }, 4489245431Sdim /* SIG_ESTAB_REQ */ { NULL, NULL }, 4490245431Sdim /* SIG_ESTAB_RESP */ { NULL, NULL }, 4491263509Sdim /* SIG_RELEASE_REQ */ { sscop_outpend_release_req, NULL }, 4492245431Sdim /* SIG_RECOVER */ { NULL, NULL }, 4493245431Sdim /* SIG_SYNC_REQ */ { NULL, NULL }, 4494245431Sdim /* SIG_SYNC_RESP */ { NULL, NULL }, 4495245431Sdim /* SIG_UDATA */ { sscop_udata_req, NULL }, 4496245431Sdim /* SIG_MDATA */ { sscop_mdata_req, NULL }, 4497245431Sdim /* SIG_UPDU_Q */ { sscop_upduq, NULL }, 4498245431Sdim /* SIG_MPDU_Q */ { sscop_mpduq, NULL }, 4499245431Sdim /* SIG_RETRIEVE */ { NULL, NULL }, 4500245431Sdim }, 4501223017Sdim /* SSCOP_IN_PEND */ { 4502245431Sdim /* SIG_BGN */ { sscop_inpend_bgn, NULL }, 4503245431Sdim /* SIG_BGAK */ { sscop_inpend_bgak, NULL }, 4504245431Sdim /* SIG_END */ { sscop_inpend_end, NULL }, 4505245431Sdim /* SIG_ENDAK */ { sscop_inpend_endak, NULL }, 4506226890Sdim /* SIG_RS */ { sscop_inpend_rs, NULL }, 4507245431Sdim /* SIG_RSAK */ { sscop_inpend_rsak, NULL }, 4508245431Sdim /* SIG_BGREJ */ { sscop_inpend_bgrej, NULL }, 4509263509Sdim /* SIG_SD */ { sscop_inpend_sd, NULL }, 4510263509Sdim /* SIG_ER */ { sscop_inpend_er, NULL }, 4511263509Sdim /* SIG_POLL */ { sscop_inpend_poll, NULL }, 4512263509Sdim /* SIG_STAT */ { sscop_inpend_stat, NULL }, 4513263509Sdim /* SIG_USTAT */ { sscop_inpend_ustat, NULL }, 4514263509Sdim /* SIG_UD */ { sscop_ud, NULL }, 4515245431Sdim /* SIG_MD */ { sscop_md, NULL }, 4516245431Sdim /* SIG_ERAK */ { sscop_inpend_erak, NULL }, 4517245431Sdim /* SIG_T_CC */ { NULL, NULL }, 4518223017Sdim /* SIG_T_POLL */ { NULL, NULL }, 4519223017Sdim /* SIG_T_KA */ { NULL, NULL }, 4520245431Sdim /* SIG_T_NR */ { NULL, NULL }, 4521245431Sdim /* SIG_T_IDLE */ { NULL, NULL }, 4522245431Sdim /* SIG_PDU_Q */ { sscop_flush_pduq, NULL }, 4523245431Sdim /* SIG_USER_DATA */ { NULL, NULL }, 4524245431Sdim /* SIG_ESTAB_REQ */ { NULL, NULL }, 4525245431Sdim /* SIG_ESTAB_RESP */ { sscop_inpend_establish_resp, NULL }, 4526245431Sdim /* SIG_RELEASE_REQ */ { sscop_inpend_release_req, NULL }, 4527263509Sdim /* SIG_RECOVER */ { NULL, NULL }, 4528245431Sdim /* SIG_SYNC_REQ */ { NULL, NULL }, 4529223017Sdim /* SIG_SYNC_RESP */ { NULL, NULL }, 4530245431Sdim /* SIG_UDATA */ { sscop_udata_req, NULL }, 4531263509Sdim /* SIG_MDATA */ { sscop_mdata_req, NULL }, 4532245431Sdim /* SIG_UPDU_Q */ { sscop_upduq, NULL }, 4533223017Sdim /* SIG_MPDU_Q */ { sscop_mpduq, NULL }, 4534263509Sdim /* SIG_RETRIEVE */ { sscop_retrieve, NULL }, 4535263509Sdim }, 4536263509Sdim /* SSCOP_OUT_DIS_PEND */ { 4537263509Sdim /* SIG_BGN */ { sscop_outdis_bgn, NULL }, 4538263509Sdim /* SIG_BGAK */ { sscop_ignore_pdu, NULL }, 4539245431Sdim /* SIG_END */ { sscop_outdis_end, NULL }, 4540245431Sdim /* SIG_ENDAK */ { sscop_outdis_endak, NULL }, 4541263509Sdim /* SIG_RS */ { sscop_ignore_pdu, NULL }, 4542263509Sdim /* SIG_RSAK */ { sscop_ignore_pdu, NULL }, 4543245431Sdim /* SIG_BGREJ */ { sscop_outdis_endak, NULL }, 4544245431Sdim /* SIG_SD */ { sscop_ignore_pdu, NULL }, 4545245431Sdim /* SIG_ER */ { sscop_ignore_pdu, NULL }, 4546245431Sdim /* SIG_POLL */ { sscop_ignore_pdu, NULL }, 4547245431Sdim /* SIG_STAT */ { sscop_ignore_pdu, NULL }, 4548223017Sdim /* SIG_USTAT */ { sscop_ignore_pdu, NULL }, 4549245431Sdim /* SIG_UD */ { sscop_ud, NULL }, 4550245431Sdim /* SIG_MD */ { sscop_md, NULL }, 4551245431Sdim /* SIG_ERAK */ { sscop_ignore_pdu, NULL }, 4552223017Sdim /* SIG_T_CC */ { sscop_outdis_cc, NULL }, 4553223017Sdim /* SIG_T_POLL */ { NULL, NULL }, 4554245431Sdim /* SIG_T_KA */ { NULL, NULL }, 4555245431Sdim /* SIG_T_NR */ { NULL, NULL }, 4556245431Sdim /* SIG_T_IDLE */ { NULL, NULL }, 4557245431Sdim /* SIG_PDU_Q */ { sscop_flush_pduq, NULL }, 4558263509Sdim /* SIG_USER_DATA */ { NULL, NULL }, 4559263509Sdim /* SIG_ESTAB_REQ */ { sscop_outdis_establish_req, NULL }, 4560263509Sdim /* SIG_ESTAB_RESP */ { NULL, NULL }, 4561245431Sdim /* SIG_RELEASE_REQ */ { NULL, NULL }, 4562245431Sdim /* SIG_RECOVER */ { NULL, NULL }, 4563245431Sdim /* SIG_SYNC_REQ */ { NULL, NULL }, 4564245431Sdim /* SIG_SYNC_RESP */ { NULL, NULL }, 4565245431Sdim /* SIG_UDATA */ { sscop_udata_req, NULL }, 4566245431Sdim /* SIG_MDATA */ { sscop_mdata_req, NULL }, 4567245431Sdim /* SIG_UPDU_Q */ { sscop_upduq, NULL }, 4568245431Sdim /* SIG_MPDU_Q */ { sscop_mpduq, NULL }, 4569245431Sdim /* SIG_RETRIEVE */ { sscop_retrieve, NULL }, 4570245431Sdim }, 4571235633Sdim /* SSCOP_OUT_RESYNC_PEND */ { 4572235633Sdim /* SIG_BGN */ { sscop_outsync_bgn, NULL }, 4573235633Sdim /* SIG_BGAK */ { sscop_ignore_pdu, NULL }, 4574245431Sdim /* SIG_END */ { sscop_outsync_end, NULL }, 4575245431Sdim /* SIG_ENDAK */ { sscop_outsync_endak, NULL }, 4576245431Sdim /* SIG_RS */ { sscop_outsync_rs, NULL }, 4577235633Sdim /* SIG_RSAK */ { sscop_outsync_rsak, NULL }, 4578245431Sdim /* SIG_BGREJ */ { sscop_outsync_bgrej, NULL }, 4579245431Sdim /* SIG_SD */ { sscop_ignore_pdu, NULL }, 4580245431Sdim /* SIG_ER */ { sscop_ignore_pdu, NULL }, 4581245431Sdim /* SIG_POLL */ { sscop_ignore_pdu, NULL }, 4582245431Sdim /* SIG_STAT */ { sscop_ignore_pdu, NULL }, 4583245431Sdim /* SIG_USTAT */ { sscop_ignore_pdu, NULL }, 4584245431Sdim /* SIG_UD */ { sscop_ud, NULL }, 4585245431Sdim /* SIG_MD */ { sscop_md, NULL }, 4586245431Sdim /* SIG_ERAK */ { sscop_ignore_pdu, NULL }, 4587245431Sdim /* SIG_T_CC */ { sscop_outsync_cc, NULL }, 4588245431Sdim /* SIG_T_POLL */ { NULL, NULL }, 4589245431Sdim /* SIG_T_KA */ { NULL, NULL }, 4590245431Sdim /* SIG_T_NR */ { NULL, NULL }, 4591245431Sdim /* SIG_T_IDLE */ { NULL, NULL }, 4592245431Sdim /* SIG_PDU_Q */ { sscop_flush_pduq, NULL }, 4593245431Sdim /* SIG_USER_DATA */ { NULL, NULL }, 4594245431Sdim /* SIG_ESTAB_REQ */ { NULL, NULL }, 4595223017Sdim /* SIG_ESTAB_RESP */ { NULL, NULL }, 4596252723Sdim /* SIG_RELEASE_REQ */ { sscop_outsync_release_req, NULL }, 4597252723Sdim /* SIG_RECOVER */ { NULL, NULL }, 4598252723Sdim /* SIG_SYNC_REQ */ { NULL, NULL }, 4599245431Sdim /* SIG_SYNC_RESP */ { NULL, NULL }, 4600223017Sdim /* SIG_UDATA */ { sscop_udata_req, NULL }, 4601245431Sdim /* SIG_MDATA */ { sscop_mdata_req, NULL }, 4602245431Sdim /* SIG_UPDU_Q */ { sscop_upduq, NULL }, 4603245431Sdim /* SIG_MPDU_Q */ { sscop_mpduq, NULL }, 4604245431Sdim /* SIG_RETRIEVE */ { NULL, NULL }, 4605245431Sdim }, 4606252723Sdim /* SSCOP_IN_RESYNC_PEND */ { 4607252723Sdim /* SIG_BGN */ { sscop_insync_bgn, NULL }, 4608223017Sdim /* SIG_BGAK */ { sscop_insync_bgak, NULL }, 4609223017Sdim /* SIG_END */ { sscop_insync_end, NULL }, 4610263509Sdim /* SIG_ENDAK */ { sscop_insync_endak, NULL }, 4611263509Sdim /* SIG_RS */ { sscop_insync_rs, NULL }, 4612263509Sdim /* SIG_RSAK */ { sscop_insync_rsak, NULL }, 4613263509Sdim /* SIG_BGREJ */ { sscop_insync_bgrej, NULL }, 4614263509Sdim /* SIG_SD */ { sscop_insync_sd, NULL }, 4615263509Sdim /* SIG_ER */ { sscop_insync_er, NULL }, 4616263509Sdim /* SIG_POLL */ { sscop_insync_poll, NULL }, 4617263509Sdim /* SIG_STAT */ { sscop_insync_stat, NULL }, 4618263509Sdim /* SIG_USTAT */ { sscop_insync_ustat, NULL }, 4619263509Sdim /* SIG_UD */ { sscop_ud, NULL }, 4620263509Sdim /* SIG_MD */ { sscop_md, NULL }, 4621263509Sdim /* SIG_ERAK */ { sscop_insync_erak, NULL }, 4622263509Sdim /* SIG_T_CC */ { NULL, NULL }, 4623263509Sdim /* SIG_T_POLL */ { NULL, NULL }, 4624263509Sdim /* SIG_T_KA */ { NULL, NULL }, 4625245431Sdim /* SIG_T_NR */ { NULL, NULL }, 4626245431Sdim /* SIG_T_IDLE */ { NULL, NULL }, 4627245431Sdim /* SIG_PDU_Q */ { sscop_flush_pduq, NULL }, 4628245431Sdim /* SIG_USER_DATA */ { NULL, NULL }, 4629223017Sdim /* SIG_ESTAB_REQ */ { NULL, NULL }, 4630245431Sdim /* SIG_ESTAB_RESP */ { NULL, NULL }, 4631245431Sdim /* SIG_RELEASE_REQ */ { sscop_insync_release_req, NULL }, 4632245431Sdim /* SIG_RECOVER */ { NULL, NULL }, 4633223017Sdim /* SIG_SYNC_REQ */ { NULL, NULL }, 4634245431Sdim /* SIG_SYNC_RESP */ { sscop_insync_sync_resp, NULL }, 4635245431Sdim /* SIG_UDATA */ { sscop_udata_req, NULL }, 4636223017Sdim /* SIG_MDATA */ { sscop_mdata_req, NULL }, 4637245431Sdim /* SIG_UPDU_Q */ { sscop_upduq, NULL }, 4638245431Sdim /* SIG_MPDU_Q */ { sscop_mpduq, NULL }, 4639245431Sdim /* SIG_RETRIEVE */ { sscop_retrieve, NULL }, 4640245431Sdim }, 4641245431Sdim /* SSCOP_OUT_REC_PEND */ { 4642245431Sdim /* SIG_BGN */ { sscop_outrec_bgn, NULL }, 4643245431Sdim /* SIG_BGAK */ { sscop_outrec_bgak, NULL }, 4644245431Sdim /* SIG_END */ { sscop_outrec_end, NULL }, 4645245431Sdim /* SIG_ENDAK */ { sscop_outrec_endak, NULL }, 4646223017Sdim /* SIG_RS */ { sscop_outrec_rs, NULL }, 4647245431Sdim /* SIG_RSAK */ { sscop_outrec_rsak, NULL }, 4648245431Sdim /* SIG_BGREJ */ { sscop_outrec_bgrej, NULL }, 4649245431Sdim /* SIG_SD */ { sscop_ignore_pdu, NULL }, 4650235633Sdim /* SIG_ER */ { sscop_outrec_er, NULL }, 4651245431Sdim /* SIG_POLL */ { sscop_ignore_pdu, NULL }, 4652245431Sdim /* SIG_STAT */ { sscop_ignore_pdu, NULL }, 4653235633Sdim /* SIG_USTAT */ { sscop_ignore_pdu, NULL }, 4654245431Sdim /* SIG_UD */ { sscop_ud, NULL }, 4655245431Sdim /* SIG_MD */ { sscop_md, NULL }, 4656223017Sdim /* SIG_ERAK */ { sscop_outrec_erak, NULL }, 4657223017Sdim /* SIG_T_CC */ { sscop_outrec_cc, NULL }, 4658223017Sdim /* SIG_T_POLL */ { NULL, NULL }, 4659245431Sdim /* SIG_T_KA */ { NULL, NULL }, 4660245431Sdim /* SIG_T_NR */ { NULL, NULL }, 4661245431Sdim /* SIG_T_IDLE */ { NULL, NULL }, 4662245431Sdim /* SIG_PDU_Q */ { sscop_outrec_pduq, NULL }, 4663245431Sdim /* SIG_USER_DATA */ { sscop_outrec_userdata, NULL }, 4664245431Sdim /* SIG_ESTAB_REQ */ { NULL, NULL }, 4665245431Sdim /* SIG_ESTAB_RESP */ { NULL, NULL }, 4666245431Sdim /* SIG_RELEASE_REQ */ { sscop_outrec_release_req, NULL }, 4667245431Sdim /* SIG_RECOVER */ { NULL, NULL }, 4668245431Sdim /* SIG_SYNC_REQ */ { sscop_outrec_sync_req, NULL }, 4669245431Sdim /* SIG_SYNC_RESP */ { NULL, NULL }, 4670245431Sdim /* SIG_UDATA */ { sscop_udata_req, NULL }, 4671245431Sdim /* SIG_MDATA */ { sscop_mdata_req, NULL }, 4672245431Sdim /* SIG_UPDU_Q */ { sscop_upduq, NULL }, 4673245431Sdim /* SIG_MPDU_Q */ { sscop_mpduq, NULL }, 4674245431Sdim /* SIG_RETRIEVE */ { NULL, NULL }, 4675245431Sdim }, 4676223017Sdim /* SSCOP_REC_PEND */ { 4677252723Sdim /* SIG_BGN */ { sscop_rec_bgn, NULL }, 4678252723Sdim /* SIG_BGAK */ { sscop_rec_bgak, NULL }, 4679252723Sdim /* SIG_END */ { sscop_rec_end, NULL }, 4680252723Sdim /* SIG_ENDAK */ { sscop_rec_endak, NULL }, 4681223017Sdim /* SIG_RS */ { sscop_rec_rs, NULL }, 4682223017Sdim /* SIG_RSAK */ { sscop_rec_rsak, NULL }, 4683245431Sdim /* SIG_BGREJ */ { sscop_rec_bgrej, NULL }, 4684245431Sdim /* SIG_SD */ { sscop_ignore_pdu, NULL }, 4685245431Sdim /* SIG_ER */ { sscop_rec_er, NULL }, 4686252723Sdim /* SIG_POLL */ { sscop_ignore_pdu, NULL }, 4687252723Sdim /* SIG_STAT */ { sscop_rec_stat, NULL }, 4688252723Sdim /* SIG_USTAT */ { sscop_rec_ustat, NULL }, 4689252723Sdim /* SIG_UD */ { sscop_ud, NULL }, 4690223017Sdim /* SIG_MD */ { sscop_md, NULL }, 4691245431Sdim /* SIG_ERAK */ { sscop_ignore_pdu, NULL }, 4692245431Sdim /* SIG_T_CC */ { NULL, NULL }, 4693245431Sdim /* SIG_T_POLL */ { NULL, NULL }, 4694245431Sdim /* SIG_T_KA */ { NULL, NULL }, 4695245431Sdim /* SIG_T_NR */ { NULL, NULL }, 4696245431Sdim /* SIG_T_IDLE */ { NULL, NULL }, 4697245431Sdim /* SIG_PDU_Q */ { sscop_rec_pduq, NULL }, 4698245431Sdim /* SIG_USER_DATA */ { NULL, NULL }, 4699245431Sdim /* SIG_ESTAB_REQ */ { NULL, NULL }, 4700223017Sdim /* SIG_ESTAB_RESP */ { NULL, NULL }, 4701223017Sdim /* SIG_RELEASE_REQ */ { sscop_rec_release_req, NULL }, 4702245431Sdim /* SIG_RECOVER */ { sscop_rec_recover, NULL }, 4703245431Sdim /* SIG_SYNC_REQ */ { sscop_rec_sync_req, NULL }, 4704245431Sdim /* SIG_SYNC_RESP */ { NULL, NULL }, 4705245431Sdim /* SIG_UDATA */ { sscop_udata_req, NULL }, 4706263509Sdim /* SIG_MDATA */ { sscop_mdata_req, NULL }, 4707223017Sdim /* SIG_UPDU_Q */ { sscop_upduq, NULL }, 4708223017Sdim /* SIG_MPDU_Q */ { sscop_mpduq, NULL }, 4709223017Sdim /* SIG_RETRIEVE */ { sscop_retrieve, NULL }, 4710223017Sdim }, 4711245431Sdim /* SSCOP_IN_REC_PEND */ { 4712245431Sdim /* SIG_BGN */ { sscop_inrec_bgn, NULL }, 4713245431Sdim /* SIG_BGAK */ { sscop_inrec_bgak, NULL }, 4714245431Sdim /* SIG_END */ { sscop_inrec_end, NULL }, 4715245431Sdim /* SIG_ENDAK */ { sscop_inrec_endak, NULL }, 4716245431Sdim /* SIG_RS */ { sscop_inrec_rs, NULL }, 4717245431Sdim /* SIG_RSAK */ { sscop_inrec_rsak, NULL }, 4718223017Sdim /* SIG_BGREJ */ { sscop_inrec_bgrej, NULL }, 4719245431Sdim /* SIG_SD */ { sscop_inrec_sd, NULL }, 4720245431Sdim /* SIG_ER */ { sscop_inrec_er, NULL }, 4721245431Sdim /* SIG_POLL */ { sscop_inrec_poll, NULL }, 4722223017Sdim /* SIG_STAT */ { sscop_inrec_stat, NULL }, 4723223017Sdim /* SIG_USTAT */ { sscop_inrec_ustat, NULL }, 4724235633Sdim /* SIG_UD */ { sscop_ud, NULL }, 4725245431Sdim /* SIG_MD */ { sscop_md, NULL }, 4726245431Sdim /* SIG_ERAK */ { sscop_inrec_erak, NULL }, 4727245431Sdim /* SIG_T_CC */ { NULL, NULL }, 4728245431Sdim /* SIG_T_POLL */ { NULL, NULL }, 4729245431Sdim /* SIG_T_KA */ { NULL, NULL }, 4730245431Sdim /* SIG_T_NR */ { NULL, NULL }, 4731245431Sdim /* SIG_T_IDLE */ { NULL, NULL }, 4732245431Sdim /* SIG_PDU_Q */ { sscop_inrec_pduq, NULL }, 4733245431Sdim /* SIG_USER_DATA */ { NULL, NULL }, 4734245431Sdim /* SIG_ESTAB_REQ */ { NULL, NULL }, 4735245431Sdim /* SIG_ESTAB_RESP */ { NULL, NULL }, 4736245431Sdim /* SIG_RELEASE_REQ */ { sscop_inrec_release_req, NULL }, 4737223017Sdim /* SIG_RECOVER */ { sscop_inrec_recover, NULL }, 4738245431Sdim /* SIG_SYNC_REQ */ { sscop_inrec_sync_req, NULL }, 4739245431Sdim /* SIG_SYNC_RESP */ { NULL, NULL }, 4740245431Sdim /* SIG_UDATA */ { sscop_udata_req, NULL }, 4741245431Sdim /* SIG_MDATA */ { sscop_mdata_req, NULL }, 4742245431Sdim /* SIG_UPDU_Q */ { sscop_upduq, NULL }, 4743226890Sdim /* SIG_MPDU_Q */ { sscop_mpduq, NULL }, 4744226890Sdim /* SIG_RETRIEVE */ { sscop_retrieve, NULL }, 4745226890Sdim }, 4746235633Sdim /* SSCOP_READY */ { 4747235633Sdim /* SIG_BGN */ { sscop_ready_bgn, NULL }, 4748235633Sdim /* SIG_BGAK */ { sscop_ignore_pdu, NULL }, 4749245431Sdim /* SIG_END */ { sscop_ready_end, NULL }, 4750245431Sdim /* SIG_ENDAK */ { sscop_ready_endak, NULL }, 4751263509Sdim /* SIG_RS */ { sscop_ready_rs, NULL }, 4752263509Sdim /* SIG_RSAK */ { sscop_ignore_pdu, NULL }, 4753245431Sdim /* SIG_BGREJ */ { sscop_ready_bgrej, NULL }, 4754245431Sdim /* SIG_SD */ { sscop_ready_sd, NULL }, 4755263509Sdim /* SIG_ER */ { sscop_ready_er, NULL }, 4756263509Sdim /* SIG_POLL */ { sscop_ready_poll, NULL }, 4757263509Sdim /* SIG_STAT */ { sscop_ready_stat, NULL }, 4758245431Sdim /* SIG_USTAT */ { sscop_ready_ustat, NULL }, 4759245431Sdim /* SIG_UD */ { sscop_ud, NULL }, 4760263509Sdim /* SIG_MD */ { sscop_md, NULL }, 4761245431Sdim /* SIG_ERAK */ { sscop_ignore_pdu, NULL }, 4762235633Sdim /* SIG_T_CC */ { NULL, NULL }, 4763252723Sdim /* SIG_T_POLL */ { sscop_ready_tpoll, NULL }, 4764235633Sdim /* SIG_T_KA */ { sscop_ready_tka, NULL }, 4765235633Sdim /* SIG_T_NR */ { sscop_ready_nr, NULL }, 4766252723Sdim /* SIG_T_IDLE */ { sscop_ready_tidle, NULL }, 4767252723Sdim /* SIG_PDU_Q */ { sscop_ready_pduq, c_ready_pduq }, 4768252723Sdim /* SIG_USER_DATA */ { sscop_ready_userdata, NULL }, 4769252723Sdim /* SIG_ESTAB_REQ */ { NULL, NULL }, 4770252723Sdim /* SIG_ESTAB_RESP */ { NULL, NULL }, 4771252723Sdim /* SIG_RELEASE_REQ */ { sscop_ready_release_req, NULL }, 4772252723Sdim /* SIG_RECOVER */ { NULL, NULL }, 4773252723Sdim /* SIG_SYNC_REQ */ { sscop_ready_sync_req, NULL }, 4774252723Sdim /* SIG_SYNC_RESP */ { NULL, NULL }, 4775252723Sdim /* SIG_UDATA */ { sscop_udata_req, NULL }, 4776252723Sdim /* SIG_MDATA */ { sscop_mdata_req, NULL }, 4777252723Sdim /* SIG_UPDU_Q */ { sscop_upduq, NULL }, 4778252723Sdim /* SIG_MPDU_Q */ { sscop_mpduq, NULL }, 4779252723Sdim /* SIG_RETRIEVE */ { NULL, NULL }, 4780235633Sdim } 4781235633Sdim}; 4782235633Sdim 4783235633Sdim/* 4784235633Sdim * Try to execute a signal. It is executed if 4785245431Sdim * - it is illegal (in this case it is effectively ignored) 4786235633Sdim * - it has no condition 4787245431Sdim * - its condition is true 4788245431Sdim * If it has a condition and that is false, the function does nothing and 4789252723Sdim * returns 0. 4790252723Sdim * If the signal gets executed, the signal function is responsible to release 4791252723Sdim * the message (if any). 4792252723Sdim */ 4793252723Sdimstatic int 4794252723Sdimsig_exec(struct sscop *sscop, u_int sig, struct sscop_msg *msg) 4795252723Sdim{ 4796226890Sdim void (*func)(struct sscop *, struct sscop_msg *); 4797226890Sdim int (*cond)(struct sscop *); 4798245431Sdim 4799226890Sdim func = state_matrix[sscop->state][sig].func; 4800252723Sdim cond = state_matrix[sscop->state][sig].cond; 4801226890Sdim 4802245431Sdim if(func == NULL) { 4803245431Sdim VERBOSE(sscop, SSCOP_DBG_BUG, (sscop, sscop->aarg, 4804245431Sdim "no handler for %s in state %s - ignored", 4805245431Sdim events[sig], states[sscop->state])); 4806226890Sdim SSCOP_MSG_FREE(msg); 4807226890Sdim return 1; 4808226890Sdim } 4809226890Sdim if(cond == NULL || (*cond)(sscop)) { 4810245431Sdim VERBOSE(sscop, SSCOP_DBG_EXEC, (sscop, sscop->aarg, 4811226890Sdim "executing %s in %s", events[sig], 4812226890Sdim states[sscop->state])); 4813226890Sdim (*func)(sscop, msg); 4814252723Sdim return 1; 4815252723Sdim } 4816252723Sdim VERBOSE(sscop, SSCOP_DBG_EXEC, (sscop, sscop->aarg, 4817252723Sdim "delaying %s in %s", events[sig], 4818252723Sdim states[sscop->state])); 4819252723Sdim 4820252723Sdim return 0; 4821263509Sdim} 4822263509Sdim 4823263509Sdim/* 4824252723Sdim * Deliver a signal to the given sscop 4825252723Sdim * If it is delivered from inside a signal handler - queue it. If not, 4826252723Sdim * execute it. After execution loop through the queue and execute all 4827252723Sdim * pending signals. Signals, that cannot be executed because of entry 4828252723Sdim * conditions are skipped. 4829252723Sdim */ 4830252723Sdimstatic void 4831252723Sdimsscop_signal(struct sscop *sscop, u_int sig, struct sscop_msg *msg) 4832252723Sdim{ 4833252723Sdim struct sscop_sig *s; 4834252723Sdim 4835252723Sdim VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg, 4836263509Sdim "got signal %s in state %s%s", events[sig], 4837263509Sdim states[sscop->state], sscop->in_sig ? " -- queuing" : "")); 4838263509Sdim 4839263509Sdim SIG_ALLOC(s); 4840252723Sdim if(s == NULL) { 4841263509Sdim FAILURE("sscop: cannot allocate signal"); 4842263509Sdim SSCOP_MSG_FREE(msg); 4843263509Sdim return; 4844263509Sdim } 4845263509Sdim s->sig = sig; 4846263509Sdim s->msg = msg; 4847263509Sdim SIGQ_APPEND(&sscop->sigs, s); 4848263509Sdim 4849263509Sdim if(!sscop->in_sig) 4850263509Sdim handle_sigs(sscop); 4851263509Sdim} 4852263509Sdim 4853263509Sdim/* 4854263509Sdim * Loop through the signal queue until we can't execute any signals. 4855263509Sdim */ 4856263509Sdimstatic void 4857263509Sdimhandle_sigs(struct sscop *sscop) 4858252723Sdim{ 4859252723Sdim struct sscop_sig *s; 4860235633Sdim sscop_sigq_head_t dsigs, q; 4861235633Sdim int exec; 4862235633Sdim 4863235633Sdim sscop->in_sig++; 4864235633Sdim 4865235633Sdim /* 4866223017Sdim * Copy the current signal queue to the local one and empty 4867235633Sdim * the signal queue. Then loop through the signals. After one 4868235633Sdim * pass we have a list of delayed signals because of entry 4869235633Sdim * conditions and a new list of signals. Merge them. Repeat until 4870223017Sdim * the signal queue is either empty or contains only delayed signals. 4871235633Sdim */ 4872223017Sdim SIGQ_INIT(&q); 4873235633Sdim SIGQ_INIT(&dsigs); 4874235633Sdim do { 4875235633Sdim exec = 0; 4876235633Sdim 4877235633Sdim /* 4878235633Sdim * Copy signal list and make sscop list empty 4879235633Sdim */ 4880235633Sdim SIGQ_MOVE(&sscop->sigs, &q); 4881235633Sdim 4882235633Sdim /* 4883235633Sdim * Loop through the list 4884235633Sdim */ 4885235633Sdim while((s = SIGQ_GET(&q)) != NULL) { 4886235633Sdim if(sig_exec(sscop, s->sig, s->msg)) { 4887235633Sdim exec = 1; 4888235633Sdim SIG_FREE(s); 4889235633Sdim } else { 4890235633Sdim SIGQ_APPEND(&dsigs, s); 4891235633Sdim } 4892235633Sdim } 4893235633Sdim 4894235633Sdim /* 4895235633Sdim * Merge lists by inserting delayed signals in front of 4896235633Sdim * the signal list. preserving the order. 4897235633Sdim */ 4898235633Sdim SIGQ_PREPEND(&dsigs, &sscop->sigs); 4899226890Sdim } while(exec); 4900223017Sdim sscop->in_sig--; 4901235633Sdim} 4902235633Sdim 4903235633Sdim/* 4904226890Sdim * Save a signal that should be executed only if state changes. 4905223017Sdim */ 4906223017Sdimstatic void 4907235633Sdimsscop_save_signal(struct sscop *sscop, u_int sig, struct sscop_msg *msg) 4908223017Sdim{ 4909235633Sdim struct sscop_sig *s; 4910245431Sdim 4911245431Sdim SIG_ALLOC(s); 4912235633Sdim if(s == NULL) { 4913245431Sdim FAILURE("sscop: cannot allocate signal"); 4914245431Sdim SSCOP_MSG_FREE(msg); 4915245431Sdim return; 4916263509Sdim } 4917263509Sdim s->sig = sig; 4918263509Sdim s->msg = msg; 4919263509Sdim SIGQ_APPEND(&sscop->saved_sigs, s); 4920245431Sdim} 4921245431Sdim 4922245431Sdim/* 4923235633Sdim * Set a new state. If signals are waiting for a state change - append them to 4924235633Sdim * the signal queue, so they get executed. 4925235633Sdim */ 4926223017Sdimstatic void 4927223017Sdimsscop_set_state(struct sscop *sscop, u_int nstate) 4928235633Sdim{ 4929223017Sdim VERBOSE(sscop, SSCOP_DBG_STATE, (sscop, sscop->aarg, 4930235633Sdim "changing state from %s to %s", 4931235633Sdim states[sscop->state], states[nstate])); 4932235633Sdim 4933223017Sdim sscop->state = nstate; 4934245431Sdim SIGQ_MOVE(&sscop->saved_sigs, &sscop->sigs); 4935245431Sdim} 4936235633Sdim 4937235633Sdimvoid 4938235633Sdimsscop_setdebug(struct sscop *sscop, u_int n) 4939223017Sdim{ 4940235633Sdim sscop->debug = n; 4941235633Sdim} 4942235633Sdim 4943223017Sdimu_int 4944235633Sdimsscop_getdebug(const struct sscop *sscop) 4945235633Sdim{ 4946235633Sdim return (sscop->debug); 4947235633Sdim} 4948235633Sdim