1/* 2 * Copyright (c) 1996-2003 3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * Author: Hartmut Brandt <harti@freebsd.org> 28 * 29 * $Begemot: libunimsg/netnatm/sig/sig_uni.c,v 1.11 2004/08/05 07:11:03 brandt Exp $ 30 * 31 * Instance handling 32 */ 33 34#include <netnatm/unimsg.h> 35#include <netnatm/saal/sscopdef.h> 36#include <netnatm/saal/sscfudef.h> 37#include <netnatm/msg/unistruct.h> 38#include <netnatm/msg/unimsglib.h> 39#include <netnatm/sig/uni.h> 40#include <netnatm/sig/unisig.h> 41 42#include <netnatm/sig/unipriv.h> 43 44#ifdef UNICORE 45UNICORE 46#endif 47 48#define STR(S) [S] = #S 49static const char *custat_names[] = { 50 STR(CU_STAT0), 51 STR(CU_STAT1), 52 STR(CU_STAT2), 53 STR(CU_STAT3), 54}; 55static const char *globstat_names[] = { 56 STR(UNI_CALLSTATE_REST0), 57 STR(UNI_CALLSTATE_REST1), 58 STR(UNI_CALLSTATE_REST2), 59}; 60 61static const char *sig_names[] = { 62 STR(UNIAPI_ERROR), 63 STR(UNIAPI_CALL_CREATED), 64 STR(UNIAPI_CALL_DESTROYED), 65 STR(UNIAPI_PARTY_CREATED), 66 STR(UNIAPI_PARTY_DESTROYED), 67 STR(UNIAPI_LINK_ESTABLISH_request), 68 STR(UNIAPI_LINK_ESTABLISH_confirm), 69 STR(UNIAPI_LINK_RELEASE_request), 70 STR(UNIAPI_LINK_RELEASE_confirm), 71 STR(UNIAPI_RESET_request), 72 STR(UNIAPI_RESET_confirm), 73 STR(UNIAPI_RESET_indication), 74 STR(UNIAPI_RESET_ERROR_indication), 75 STR(UNIAPI_RESET_response), 76 STR(UNIAPI_RESET_ERROR_response), 77 STR(UNIAPI_RESET_STATUS_indication), 78 STR(UNIAPI_SETUP_request), 79 STR(UNIAPI_SETUP_indication), 80 STR(UNIAPI_SETUP_response), 81 STR(UNIAPI_SETUP_confirm), 82 STR(UNIAPI_SETUP_COMPLETE_indication), 83 STR(UNIAPI_SETUP_COMPLETE_request), 84 STR(UNIAPI_ALERTING_request), 85 STR(UNIAPI_ALERTING_indication), 86 STR(UNIAPI_PROCEEDING_request), 87 STR(UNIAPI_PROCEEDING_indication), 88 STR(UNIAPI_RELEASE_request), 89 STR(UNIAPI_RELEASE_indication), 90 STR(UNIAPI_RELEASE_response), 91 STR(UNIAPI_RELEASE_confirm), 92 STR(UNIAPI_NOTIFY_request), 93 STR(UNIAPI_NOTIFY_indication), 94 STR(UNIAPI_STATUS_indication), 95 STR(UNIAPI_STATUS_ENQUIRY_request), 96 STR(UNIAPI_ADD_PARTY_request), 97 STR(UNIAPI_ADD_PARTY_indication), 98 STR(UNIAPI_PARTY_ALERTING_request), 99 STR(UNIAPI_PARTY_ALERTING_indication), 100 STR(UNIAPI_ADD_PARTY_ACK_request), 101 STR(UNIAPI_ADD_PARTY_ACK_indication), 102 STR(UNIAPI_ADD_PARTY_REJ_request), 103 STR(UNIAPI_ADD_PARTY_REJ_indication), 104 STR(UNIAPI_DROP_PARTY_request), 105 STR(UNIAPI_DROP_PARTY_indication), 106 STR(UNIAPI_DROP_PARTY_ACK_request), 107 STR(UNIAPI_DROP_PARTY_ACK_indication), 108 STR(UNIAPI_ABORT_CALL_request), 109}; 110 111static const char *verb_names[] = { 112# define UNI_DEBUG_DEFINE(D) [UNI_FAC_##D] = #D, 113 UNI_DEBUG_FACILITIES 114# undef UNI_DEBUG_DEFINE 115}; 116 117const char * 118uni_facname(enum uni_verb fac) 119{ 120 static char buf[40]; 121 122 if (fac >= UNI_MAXFACILITY) { 123 sprintf(buf, "FAC%u", fac); 124 return (buf); 125 } 126 return (verb_names[fac]); 127} 128 129const char * 130uni_signame(enum uni_sig sig) 131{ 132 static char buf[40]; 133 134 if (sig >= UNIAPI_MAXSIG) { 135 sprintf(buf, "UNIAPI_SIG%u", sig); 136 return (buf); 137 } 138 return (sig_names[sig]); 139} 140 141struct unicx * 142uni_context(struct uni *uni) 143{ 144 return (&uni->cx); 145} 146 147static void 148uni_init(struct uni *uni) 149{ 150 uni->working = 0; 151 uni->cref_alloc = 12; 152 uni->custat = CU_STAT0; 153 uni->glob_start = UNI_CALLSTATE_REST0; 154 uni->glob_respond = UNI_CALLSTATE_REST0; 155} 156 157static void 158uni_stop(struct uni *uni) 159{ 160 struct call *c; 161 162 while ((c = TAILQ_FIRST(&uni->calls)) != NULL) { 163 TAILQ_REMOVE(&uni->calls, c, link); 164 uni_destroy_call(c, 1); 165 } 166 167 SIGQ_CLEAR(&uni->workq); 168 SIGQ_CLEAR(&uni->delq); 169} 170 171/* 172 * INSTANCE HANDLING 173 */ 174struct uni * 175uni_create(void *arg, const struct uni_funcs *funcs) 176{ 177 struct uni *uni; 178 179 if ((uni = INS_ALLOC()) == NULL) 180 return (NULL); 181 182 uni_init(uni); 183 184 uni->funcs = funcs; 185 uni->arg = arg; 186 uni->proto = UNIPROTO_UNI40U; 187 uni->sb_tb = 0; 188 TAILQ_INIT(&uni->workq); 189 TAILQ_INIT(&uni->delq); 190 TIMER_INIT_UNI(uni, t309); 191 uni->timer309 = UNI_T309_DEFAULT; 192 TAILQ_INIT(&uni->calls); 193 uni_initcx(&uni->cx); 194 TIMER_INIT_UNI(uni, t317); 195 TIMER_INIT_UNI(uni, t316); 196 197 uni->timer301 = UNI_T301_DEFAULT; 198 uni->init303 = UNI_T303_CNT_DEFAULT; 199 uni->timer303 = UNI_T303_DEFAULT; 200 uni->init308 = UNI_T308_CNT_DEFAULT; 201 uni->timer308 = UNI_T308_DEFAULT; 202 uni->timer310 = UNI_T310U_DEFAULT; 203 uni->timer313 = UNI_T313_DEFAULT; 204 uni->init316 = UNI_T316_CNT_DEFAULT; 205 uni->timer316 = UNI_T316_DEFAULT; 206 uni->timer317 = UNI_T317_DEFAULT; 207 uni->timer322 = UNI_T322_DEFAULT; 208 uni->init322 = UNI_T322_CNT_DEFAULT; 209 uni->timer397 = UNI_T397_DEFAULT; 210 uni->timer398 = UNI_T398_DEFAULT; 211 uni->timer399 = UNI_T399U_DEFAULT; 212 213 return (uni); 214} 215 216void 217uni_destroy(struct uni *uni) 218{ 219 uni_stop(uni); 220 221 TIMER_DESTROY_UNI(uni, t309); 222 TIMER_DESTROY_UNI(uni, t316); 223 TIMER_DESTROY_UNI(uni, t317); 224 225 INS_FREE(uni); 226} 227 228void 229uni_reset(struct uni *uni) 230{ 231 uni_stop(uni); 232 uni_init(uni); 233} 234 235 236/* 237 * DISPATCH SSCOP SIGNAL 238 */ 239void 240uni_saal_input(struct uni *uni, enum saal_sig sig, struct uni_msg *m) 241{ 242 switch (sig) { 243 244 case SAAL_ESTABLISH_indication: 245 if (m != NULL) 246 uni_msg_destroy(m); 247 uni_enq_coord(uni, SIGO_SAAL_ESTABLISH_indication, 0, NULL); 248 break; 249 250 case SAAL_ESTABLISH_confirm: 251 if (m != NULL) 252 uni_msg_destroy(m); 253 uni_enq_coord(uni, SIGO_SAAL_ESTABLISH_confirm, 0, NULL); 254 break; 255 256 case SAAL_RELEASE_confirm: 257 if (m != NULL) 258 uni_msg_destroy(m); 259 uni_enq_coord(uni, SIGO_SAAL_RELEASE_confirm, 0, NULL); 260 break; 261 262 case SAAL_RELEASE_indication: 263 if (m != NULL) 264 uni_msg_destroy(m); 265 uni_enq_coord(uni, SIGO_SAAL_RELEASE_indication, 0, NULL); 266 break; 267 268 case SAAL_DATA_indication: 269 uni_enq_coord(uni, SIGO_SAAL_DATA_indication, 0, m); 270 break; 271 272 case SAAL_UDATA_indication: 273 uni_enq_coord(uni, SIGO_SAAL_UDATA_indication, 0, m); 274 break; 275 276 default: 277 VERBOSE(uni, UNI_FAC_ERR, 1, "bogus saal signal %u", sig); 278 if (m != NULL) 279 uni_msg_destroy(m); 280 break; 281 } 282} 283 284static struct { 285 const char *name; 286 enum uni_sig sig; 287 size_t arglen; 288 u_int coord_sig; 289 u_int proto; 290#define UNIU 0x01 291#define UNIN 0x02 292#define PNNI 0x04 293} maptab[] = { 294 { "LINK-ESTABLISH.request", UNIAPI_LINK_ESTABLISH_request, 295 0, 296 SIGO_LINK_ESTABLISH_request, UNIU | UNIN }, 297 { "LINK-RELEASE.request", UNIAPI_LINK_RELEASE_request, 298 0, 299 SIGO_LINK_RELEASE_request, UNIU | UNIN }, 300 301 { "RESET.request", UNIAPI_RESET_request, 302 sizeof(struct uniapi_reset_request), 303 SIGO_RESET_request, UNIU | UNIN }, 304 { "RESET-ERROR.response", UNIAPI_RESET_ERROR_response, 305 sizeof(struct uniapi_reset_error_response), 306 SIGO_RESET_ERROR_response, UNIU | UNIN }, 307 { "RESET.response", UNIAPI_RESET_response, 308 sizeof(struct uniapi_reset_response), 309 SIGO_RESET_response, UNIU | UNIN }, 310 311 { "SETUP.request", UNIAPI_SETUP_request, 312 sizeof(struct uniapi_setup_request), 313 SIGO_SETUP_request, UNIU | UNIN }, 314 { "SETUP.response", UNIAPI_SETUP_response, 315 sizeof(struct uniapi_setup_response), 316 SIGO_SETUP_response, UNIU | UNIN }, 317 { "SETUP-COMPLETE.request", UNIAPI_SETUP_COMPLETE_request, 318 sizeof(struct uniapi_setup_complete_request), 319 SIGO_SETUP_COMPLETE_request, UNIN }, 320 { "PROCEEDING.request", UNIAPI_PROCEEDING_request, 321 sizeof(struct uniapi_proceeding_request), 322 SIGO_PROCEEDING_request, UNIU | UNIN }, 323 { "ALERTING.request", UNIAPI_ALERTING_request, 324 sizeof(struct uniapi_alerting_request), 325 SIGO_ALERTING_request, UNIU | UNIN }, 326 { "RELEASE.request", UNIAPI_RELEASE_request, 327 sizeof(struct uniapi_release_request), 328 SIGO_RELEASE_request, UNIU | UNIN }, 329 { "RELEASE.response", UNIAPI_RELEASE_response, 330 sizeof(struct uniapi_release_response), 331 SIGO_RELEASE_response, UNIU | UNIN }, 332 { "NOTIFY.request", UNIAPI_NOTIFY_request, 333 sizeof(struct uniapi_notify_request), 334 SIGO_NOTIFY_request, UNIU | UNIN }, 335 { "STATUS-ENQUIRY.request", UNIAPI_STATUS_ENQUIRY_request, 336 sizeof(struct uniapi_status_enquiry_request), 337 SIGO_STATUS_ENQUIRY_request, UNIU | UNIN }, 338 339 { "ADD-PARTY.request", UNIAPI_ADD_PARTY_request, 340 sizeof(struct uniapi_add_party_request), 341 SIGO_ADD_PARTY_request, UNIU | UNIN }, 342 { "ADD-PARTY-ACK.request", UNIAPI_ADD_PARTY_ACK_request, 343 sizeof(struct uniapi_add_party_ack_request), 344 SIGO_ADD_PARTY_ACK_request, UNIU | UNIN }, 345 { "ADD-PARTY-REJ.request", UNIAPI_ADD_PARTY_REJ_request, 346 sizeof(struct uniapi_add_party_rej_request), 347 SIGO_ADD_PARTY_REJ_request, UNIU | UNIN }, 348 { "PARTY-ALERTING.request", UNIAPI_PARTY_ALERTING_request, 349 sizeof(struct uniapi_party_alerting_request), 350 SIGO_PARTY_ALERTING_request, UNIU | UNIN }, 351 { "DROP-PARTY.request", UNIAPI_DROP_PARTY_request, 352 sizeof(struct uniapi_drop_party_request), 353 SIGO_DROP_PARTY_request, UNIU | UNIN }, 354 { "DROP-PARTY-ACK.request", UNIAPI_DROP_PARTY_ACK_request, 355 sizeof(struct uniapi_drop_party_ack_request), 356 SIGO_DROP_PARTY_ACK_request, UNIU | UNIN }, 357 358 { "ABORT-CALL.request", UNIAPI_ABORT_CALL_request, 359 sizeof(struct uniapi_abort_call_request), 360 SIGO_ABORT_CALL_request, UNIU | UNIN }, 361 362 { NULL, 0, 0, 0, 0 } 363}; 364 365void 366uni_uni_input(struct uni *uni, enum uni_sig sig, uint32_t cookie, 367 struct uni_msg *m) 368{ 369 u_int i; 370 371 for (i = 0; maptab[i].name != NULL; i++) { 372 if (maptab[i].sig == sig) { 373 if (uni->proto == UNIPROTO_UNI40U) { 374 if (!(maptab[i].proto & UNIU)) 375 uniapi_uni_error(uni, 376 UNIAPI_ERROR_BAD_SIGNAL, cookie, 0); 377 } else if(uni->proto == UNIPROTO_UNI40N) { 378 if (!(maptab[i].proto & UNIN)) 379 uniapi_uni_error(uni, 380 UNIAPI_ERROR_BAD_SIGNAL, cookie, 0); 381 } else if(uni->proto == UNIPROTO_PNNI10) { 382 if (!(maptab[i].proto & PNNI)) 383 uniapi_uni_error(uni, 384 UNIAPI_ERROR_BAD_SIGNAL, cookie, 0); 385 } else { 386 uniapi_uni_error(uni, 387 UNIAPI_ERROR_BAD_SIGNAL, cookie, 0); 388 } 389 if (uni_msg_len(m) != maptab[i].arglen) { 390 VERBOSE(uni, UNI_FAC_ERR, 1, "bogus data in %s" 391 " (expecting %zu, got %zu)", maptab[i].name, 392 maptab[i].arglen, uni_msg_len(m)); 393 uni_msg_destroy(m); 394 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_ARG, 395 cookie, 0); 396 return; 397 } 398 if (maptab[i].arglen == 0) { 399 uni_msg_destroy(m); 400 m = NULL; 401 } 402 VERBOSE(uni, UNI_FAC_API, 1, "got signal %s - " 403 "delivering to Coord", maptab[i].name); 404 uni_enq_coord(uni, maptab[i].coord_sig, cookie, m); 405 return; 406 } 407 } 408 VERBOSE(uni, UNI_FAC_ERR, 1, "bogus uni signal %u", sig); 409 uni_msg_destroy(m); 410 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_SIGNAL, cookie, 0); 411} 412#undef UNIU 413#undef UNIN 414#undef PNNI 415 416/**************************************************************/ 417 418void 419uni_work(struct uni *uni) 420{ 421 struct sig *s; 422 423 if (uni->working) 424 return; 425 uni->working = 1; 426 427 while ((s = TAILQ_FIRST(&uni->workq)) != NULL) { 428 TAILQ_REMOVE(&uni->workq, s, link); 429 switch (s->type) { 430 431 case SIG_COORD: 432 uni_sig_coord(uni, s->sig, s->cookie, s->msg); 433 break; 434 435 case SIG_RESET_START: 436 uni_sig_start(uni, s->sig, s->cookie, s->msg, s->u); 437 break; 438 439 case SIG_RESET_RESP: 440 uni_sig_respond(uni, s->sig, s->cookie, s->msg, s->u); 441 break; 442 443 case SIG_CALL: 444 uni_sig_call(s->call, s->sig, s->cookie, s->msg, s->u); 445 break; 446 447 case SIG_PARTY: 448 uni_sig_party(s->party, s->sig, s->cookie, s->msg, s->u); 449 break; 450 451 default: 452 ASSERT(0, ("bad signal type")); 453 } 454 SIG_FREE(s); 455 } 456 457 uni->working = 0; 458} 459 460/* 461 * Enqueue a signal in the working queue 462 */ 463void 464uni_enq_sig(struct uni *uni, u_int type, struct call *call, 465 struct party *party, uint32_t sig, uint32_t cookie, 466 struct uni_msg *msg, struct uni_all *u) 467{ 468 struct sig *s; 469 470 if ((s = SIG_ALLOC()) != NULL) { 471 s->type = type; 472 s->sig = sig; 473 s->cookie = cookie; 474 s->msg = msg; 475 s->call = call; 476 s->party = party; 477 s->u = u; 478 TAILQ_INSERT_TAIL(&uni->workq, s, link); 479 } 480} 481 482/* 483 * Enqueue a signal in the delayed queue 484 */ 485void 486uni_delenq_sig(struct uni *uni, u_int type, struct call *call, 487 struct party *party, uint32_t sig, uint32_t cookie, 488 struct uni_msg *msg, struct uni_all *u) 489{ 490 struct sig *s; 491 492 if ((s = SIG_ALLOC()) != NULL) { 493 s->type = type; 494 s->sig = sig; 495 s->cookie = cookie; 496 s->msg = msg; 497 s->call = call; 498 s->party = party; 499 s->u = u; 500 TAILQ_INSERT_TAIL(&uni->delq, s, link); 501 } 502} 503 504/**************************************************************/ 505 506void 507uniapi_uni_error(struct uni *uni, uint32_t reason, uint32_t cookie, 508 uint32_t state) 509{ 510 struct uni_msg *resp; 511 struct uniapi_error *err; 512 513 if (cookie == 0) 514 return; 515 516 resp = uni_msg_alloc(sizeof(struct uniapi_error)); 517 err = uni_msg_wptr(resp, struct uniapi_error *); 518 resp->b_wptr += sizeof(struct uniapi_error); 519 520 err->reason = reason; 521 err->state = state; 522 523 uni->funcs->uni_output(uni, uni->arg, UNIAPI_ERROR, cookie, resp); 524} 525 526void 527uniapi_call_error(struct call *c, uint32_t reason, uint32_t cookie) 528{ 529 uniapi_uni_error(c->uni, reason, cookie, callstates[c->cstate].ext); 530} 531void 532uniapi_party_error(struct party *p, uint32_t reason, uint32_t cookie) 533{ 534 uniapi_uni_error(p->call->uni, reason, cookie, 535 callstates[p->call->cstate].ext); 536} 537 538/**************************************************************/ 539void 540uni_status(struct uni *uni, void *arg) 541{ 542 uni->funcs->status(uni, uni->arg, arg, 543 "working: %s\n", uni->working ? "yes" : "no"); 544 uni->funcs->status(uni, uni->arg, arg, 545 "work queue: %sempty\n", TAILQ_EMPTY(&uni->workq)? "" : "not "); 546 uni->funcs->status(uni, uni->arg, arg, 547 "delayed work queue: %sempty\n", 548 TAILQ_EMPTY(&uni->delq)? "" : "not "); 549 uni->funcs->status(uni, uni->arg, arg, 550 "coordinator: %s\n", custat_names[uni->custat]); 551 uni->funcs->status(uni, uni->arg, arg, 552 "reset-start: %s\n", globstat_names[uni->glob_start]); 553 uni->funcs->status(uni, uni->arg, arg, 554 "reset-respond: %s\n", globstat_names[uni->glob_respond]); 555} 556 557void 558uni_undel(struct uni *uni, int (*filter)(struct sig *, void *), void *arg) 559{ 560 struct sigqueue newq; 561 struct sig *s, *s1; 562 563 if (TAILQ_EMPTY(&uni->delq)) 564 return; 565 566 TAILQ_INIT(&newq); 567 568 s = TAILQ_FIRST(&uni->delq); 569 while (s != NULL) { 570 s1 = TAILQ_NEXT(s, link); 571 if ((*filter)(s, arg)) { 572 TAILQ_REMOVE(&uni->delq, s, link); 573 TAILQ_INSERT_TAIL(&uni->workq, s, link); 574 } 575 s = s1; 576 } 577} 578 579void 580uni_delsig(struct uni *uni, u_int type, struct call *c, struct party *p) 581{ 582 struct sig *s, *s1; 583 584 s = TAILQ_FIRST(&uni->workq); 585 while (s != NULL) { 586 s1 = TAILQ_NEXT(s, link); 587 if ((type == SIG_CALL && s->type == SIG_CALL && 588 s->call == c) || 589 (type == SIG_PARTY && s->type == SIG_PARTY && 590 s->call == c && s->party == p)) { 591 TAILQ_REMOVE(&uni->workq, s, link); 592 if (s->msg) 593 uni_msg_destroy(s->msg); 594 if (s->u) 595 UNI_FREE(s->u); 596 SIG_FREE(s); 597 } 598 s = s1; 599 } 600 601 s = TAILQ_FIRST(&uni->delq); 602 while (s != NULL) { 603 s1 = TAILQ_NEXT(s, link); 604 if ((type == SIG_CALL && s->type == SIG_CALL && 605 s->call == c) || 606 (type == SIG_PARTY && s->type == SIG_PARTY && 607 s->call == c && s->party == p)) { 608 TAILQ_REMOVE(&uni->delq, s, link); 609 if (s->msg) 610 uni_msg_destroy(s->msg); 611 if (s->u) 612 UNI_FREE(s->u); 613 SIG_FREE(s); \ 614 } 615 s = s1; 616 } 617} 618 619/**************************************************************/ 620 621void 622uni_get_config(const struct uni *uni, struct uni_config *config) 623{ 624 config->proto = uni->proto; 625 626 config->popt = 0; 627 if (uni->cx.q2932) 628 config->popt |= UNIPROTO_GFP; 629 630 config->option = 0; 631 if (uni->cx.git_hard) 632 config->option |= UNIOPT_GIT_HARD; 633 if (uni->cx.bearer_hard) 634 config->option |= UNIOPT_BEARER_HARD; 635 if (uni->cx.cause_hard) 636 config->option |= UNIOPT_CAUSE_HARD; 637 if (uni->sb_tb) 638 config->popt |= UNIPROTO_SB_TB; 639 640 config->timer301 = uni->timer301; 641 config->timer303 = uni->timer303; 642 config->init303 = uni->init303; 643 config->timer308 = uni->timer308; 644 config->init308 = uni->init308; 645 config->timer309 = uni->timer309; 646 config->timer310 = uni->timer310; 647 config->timer313 = uni->timer313; 648 config->timer316 = uni->timer316; 649 config->init316 = uni->init316; 650 config->timer317 = uni->timer317; 651 config->timer322 = uni->timer322; 652 config->init322 = uni->init322; 653 config->timer397 = uni->timer397; 654 config->timer398 = uni->timer398; 655 config->timer399 = uni->timer399; 656} 657 658void 659uni_set_config(struct uni *uni, const struct uni_config *config, 660 uint32_t *mask, uint32_t *popt_mask, uint32_t *opt_mask) 661{ 662 int idle; 663 664 idle = TAILQ_EMPTY(&uni->calls) && 665 TAILQ_EMPTY(&uni->workq) && 666 TAILQ_EMPTY(&uni->delq); 667 668 if ((*mask & UNICFG_PROTO) && idle) { 669 switch (config->proto) { 670 671 case UNIPROTO_UNI40U: 672 case UNIPROTO_UNI40N: 673 /* case UNIPROTO_PNNI10: XXX */ 674 uni->proto = config->proto; 675 *mask &= ~UNICFG_PROTO; 676 break; 677 } 678 } 679 if (*popt_mask & UNIPROTO_GFP) { 680 if (config->popt & UNIPROTO_GFP) { 681 uni->cx.q2932 = 1; 682 *popt_mask &= ~UNIPROTO_GFP; 683 } else { 684 if (!uni->cx.q2932 || idle) { 685 uni->cx.q2932 = 0; 686 *popt_mask &= ~UNIPROTO_GFP; 687 } 688 } 689 } 690 if (*popt_mask & UNIPROTO_SB_TB) { 691 uni->sb_tb = ((config->popt & UNIPROTO_SB_TB) != 0); 692 *popt_mask &= ~UNIPROTO_SB_TB; 693 } 694 if (*opt_mask & UNIOPT_GIT_HARD) { 695 uni->cx.git_hard = ((config->option & UNIOPT_GIT_HARD) != 0); 696 *opt_mask &= ~UNIOPT_GIT_HARD; 697 } 698 if (*opt_mask & UNIOPT_BEARER_HARD) { 699 uni->cx.bearer_hard = ((config->option & UNIOPT_BEARER_HARD) != 0); 700 *opt_mask &= ~UNIOPT_BEARER_HARD; 701 } 702 if (*opt_mask & UNIOPT_CAUSE_HARD) { 703 uni->cx.cause_hard = ((config->option & UNIOPT_CAUSE_HARD) != 0); 704 *opt_mask &= ~UNIOPT_CAUSE_HARD; 705 } 706 707#define SET_TIMER(NAME,name) \ 708 if (*mask & UNICFG_##NAME) { \ 709 uni->name = config->name; \ 710 *mask &= ~UNICFG_##NAME; \ 711 } 712 713 SET_TIMER(TIMER301, timer301); 714 SET_TIMER(TIMER303, timer303); 715 SET_TIMER(INIT303, init303); 716 SET_TIMER(TIMER308, timer308); 717 SET_TIMER(INIT308, init308); 718 SET_TIMER(TIMER309, timer309); 719 SET_TIMER(TIMER310, timer310); 720 SET_TIMER(TIMER313, timer313); 721 SET_TIMER(TIMER316, timer316); 722 SET_TIMER(INIT316, init316); 723 SET_TIMER(TIMER317, timer317); 724 SET_TIMER(TIMER322, timer322); 725 SET_TIMER(INIT322, init322); 726 SET_TIMER(TIMER397, timer397); 727 SET_TIMER(TIMER398, timer398); 728 SET_TIMER(TIMER399, timer399); 729 730#undef SET_TIMER 731} 732 733void 734uni_set_debug(struct uni *uni, enum uni_verb fac, u_int level) 735{ 736 uni->debug[fac] = level; 737} 738 739u_int 740uni_get_debug(const struct uni *uni, enum uni_verb fac) 741{ 742 return (uni->debug[fac]); 743} 744 745u_int 746uni_getcustate(const struct uni *uni) 747{ 748 return (uni->custat); 749} 750