1 /****************************************************************************** 2 * 3 * (C)Copyright 1998,1999 SysKonnect, 4 * a business unit of Schneider & Koch & Co. Datensysteme GmbH. 5 * 6 * See the file "skfddi.c" for further information. 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * The information in this file is provided "AS IS" without warranty. 14 * 15 ******************************************************************************/ 16 17 /* 18 SMT RMT 19 Ring Management 20 */ 21 22 /* 23 * Hardware independent state machine implemantation 24 * The following external SMT functions are referenced : 25 * 26 * queue_event() 27 * smt_timer_start() 28 * smt_timer_stop() 29 * 30 * The following external HW dependent functions are referenced : 31 * sm_ma_control() 32 * sm_mac_check_beacon_claim() 33 * 34 * The following HW dependent events are required : 35 * RM_RING_OP 36 * RM_RING_NON_OP 37 * RM_MY_BEACON 38 * RM_OTHER_BEACON 39 * RM_MY_CLAIM 40 * RM_TRT_EXP 41 * RM_VALID_CLAIM 42 * 43 */ 44 45 #include "h/types.h" 46 #include "h/fddi.h" 47 #include "h/smc.h" 48 49 #define KERNEL 50 #include "h/smtstate.h" 51 52 #ifndef lint 53 static const char ID_sccs[] = "@(#)rmt.c 2.13 99/07/02 (C) SK " ; 54 #endif 55 56 /* 57 * FSM Macros 58 */ 59 #define AFLAG 0x10 60 #define GO_STATE(x) (smc->mib.m[MAC0].fddiMACRMTState = (x)|AFLAG) 61 #define ACTIONS_DONE() (smc->mib.m[MAC0].fddiMACRMTState &= ~AFLAG) 62 #define ACTIONS(x) (x|AFLAG) 63 64 #define RM0_ISOLATED 0 65 #define RM1_NON_OP 1 /* not operational */ 66 #define RM2_RING_OP 2 /* ring operational */ 67 #define RM3_DETECT 3 /* detect dupl addresses */ 68 #define RM4_NON_OP_DUP 4 /* dupl. addr detected */ 69 #define RM5_RING_OP_DUP 5 /* ring oper. with dupl. addr */ 70 #define RM6_DIRECTED 6 /* sending directed beacons */ 71 #define RM7_TRACE 7 /* trace initiated */ 72 73 #ifdef DEBUG 74 /* 75 * symbolic state names 76 */ 77 static const char * const rmt_states[] = { 78 "RM0_ISOLATED","RM1_NON_OP","RM2_RING_OP","RM3_DETECT", 79 "RM4_NON_OP_DUP","RM5_RING_OP_DUP","RM6_DIRECTED", 80 "RM7_TRACE" 81 } ; 82 83 /* 84 * symbolic event names 85 */ 86 static const char * const rmt_events[] = { 87 "NONE","RM_RING_OP","RM_RING_NON_OP","RM_MY_BEACON", 88 "RM_OTHER_BEACON","RM_MY_CLAIM","RM_TRT_EXP","RM_VALID_CLAIM", 89 "RM_JOIN","RM_LOOP","RM_DUP_ADDR","RM_ENABLE_FLAG", 90 "RM_TIMEOUT_NON_OP","RM_TIMEOUT_T_STUCK", 91 "RM_TIMEOUT_ANNOUNCE","RM_TIMEOUT_T_DIRECT", 92 "RM_TIMEOUT_D_MAX","RM_TIMEOUT_POLL","RM_TX_STATE_CHANGE" 93 } ; 94 #endif 95 96 /* 97 * Globals 98 * in struct s_rmt 99 */ 100 101 102 /* 103 * function declarations 104 */ 105 static void rmt_fsm(struct s_smc *smc, int cmd); 106 static void start_rmt_timer0(struct s_smc *smc, u_long value, int event); 107 static void start_rmt_timer1(struct s_smc *smc, u_long value, int event); 108 static void start_rmt_timer2(struct s_smc *smc, u_long value, int event); 109 static void stop_rmt_timer0(struct s_smc *smc); 110 static void stop_rmt_timer1(struct s_smc *smc); 111 static void stop_rmt_timer2(struct s_smc *smc); 112 static void rmt_dup_actions(struct s_smc *smc); 113 static void rmt_reinsert_actions(struct s_smc *smc); 114 static void rmt_leave_actions(struct s_smc *smc); 115 static void rmt_new_dup_actions(struct s_smc *smc); 116 117 #ifndef SUPERNET_3 118 extern void restart_trt_for_dbcn() ; 119 #endif /*SUPERNET_3*/ 120 121 /* 122 init RMT state machine 123 clear all RMT vars and flags 124 */ 125 void rmt_init(struct s_smc *smc) 126 { 127 smc->mib.m[MAC0].fddiMACRMTState = ACTIONS(RM0_ISOLATED) ; 128 smc->r.dup_addr_test = DA_NONE ; 129 smc->r.da_flag = 0 ; 130 smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ; 131 smc->r.sm_ma_avail = FALSE ; 132 smc->r.loop_avail = 0 ; 133 smc->r.bn_flag = 0 ; 134 smc->r.jm_flag = 0 ; 135 smc->r.no_flag = TRUE ; 136 } 137 138 /* 139 RMT state machine 140 called by dispatcher 141 142 do 143 display state change 144 process event 145 until SM is stable 146 */ 147 void rmt(struct s_smc *smc, int event) 148 { 149 int state ; 150 151 do { 152 DB_RMT("RMT : state %s%s", 153 (smc->mib.m[MAC0].fddiMACRMTState & AFLAG) ? "ACTIONS " : "", 154 rmt_states[smc->mib.m[MAC0].fddiMACRMTState & ~AFLAG]) ; 155 DB_RMT(" event %s\n",rmt_events[event],0) ; 156 state = smc->mib.m[MAC0].fddiMACRMTState ; 157 rmt_fsm(smc,event) ; 158 event = 0 ; 159 } while (state != smc->mib.m[MAC0].fddiMACRMTState) ; 160 rmt_state_change(smc,(int)smc->mib.m[MAC0].fddiMACRMTState) ; 161 } 162 163 /* 164 process RMT event 165 */ 166 static void rmt_fsm(struct s_smc *smc, int cmd) 167 { 168 /* 169 * RM00-RM70 : from all states 170 */ 171 if (!smc->r.rm_join && !smc->r.rm_loop && 172 smc->mib.m[MAC0].fddiMACRMTState != ACTIONS(RM0_ISOLATED) && 173 smc->mib.m[MAC0].fddiMACRMTState != RM0_ISOLATED) { 174 RS_SET(smc,RS_NORINGOP) ; 175 rmt_indication(smc,0) ; 176 GO_STATE(RM0_ISOLATED) ; 177 return ; 178 } 179 180 switch(smc->mib.m[MAC0].fddiMACRMTState) { 181 case ACTIONS(RM0_ISOLATED) : 182 stop_rmt_timer0(smc) ; 183 stop_rmt_timer1(smc) ; 184 stop_rmt_timer2(smc) ; 185 186 /* 187 * Disable MAC. 188 */ 189 sm_ma_control(smc,MA_OFFLINE) ; 190 smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ; 191 smc->r.loop_avail = FALSE ; 192 smc->r.sm_ma_avail = FALSE ; 193 smc->r.no_flag = TRUE ; 194 DB_RMTN(1,"RMT : ISOLATED\n",0,0) ; 195 ACTIONS_DONE() ; 196 break ; 197 case RM0_ISOLATED : 198 /*RM01*/ 199 if (smc->r.rm_join || smc->r.rm_loop) { 200 /* 201 * According to the standard the MAC must be reset 202 * here. The FORMAC will be initialized and Claim 203 * and Beacon Frames will be uploaded to the MAC. 204 * So any change of Treq will take effect NOW. 205 */ 206 sm_ma_control(smc,MA_RESET) ; 207 GO_STATE(RM1_NON_OP) ; 208 break ; 209 } 210 break ; 211 case ACTIONS(RM1_NON_OP) : 212 start_rmt_timer0(smc,smc->s.rmt_t_non_op,RM_TIMEOUT_NON_OP) ; 213 stop_rmt_timer1(smc) ; 214 stop_rmt_timer2(smc) ; 215 sm_ma_control(smc,MA_BEACON) ; 216 DB_RMTN(1,"RMT : RING DOWN\n",0,0) ; 217 RS_SET(smc,RS_NORINGOP) ; 218 smc->r.sm_ma_avail = FALSE ; 219 rmt_indication(smc,0) ; 220 ACTIONS_DONE() ; 221 break ; 222 case RM1_NON_OP : 223 /*RM12*/ 224 if (cmd == RM_RING_OP) { 225 RS_SET(smc,RS_RINGOPCHANGE) ; 226 GO_STATE(RM2_RING_OP) ; 227 break ; 228 } 229 /*RM13*/ 230 else if (cmd == RM_TIMEOUT_NON_OP) { 231 smc->r.bn_flag = FALSE ; 232 smc->r.no_flag = TRUE ; 233 GO_STATE(RM3_DETECT) ; 234 break ; 235 } 236 break ; 237 case ACTIONS(RM2_RING_OP) : 238 stop_rmt_timer0(smc) ; 239 stop_rmt_timer1(smc) ; 240 stop_rmt_timer2(smc) ; 241 smc->r.no_flag = FALSE ; 242 if (smc->r.rm_loop) 243 smc->r.loop_avail = TRUE ; 244 if (smc->r.rm_join) { 245 smc->r.sm_ma_avail = TRUE ; 246 if (smc->mib.m[MAC0].fddiMACMA_UnitdataEnable) 247 smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = TRUE ; 248 else 249 smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ; 250 } 251 DB_RMTN(1,"RMT : RING UP\n",0,0) ; 252 RS_CLEAR(smc,RS_NORINGOP) ; 253 RS_SET(smc,RS_RINGOPCHANGE) ; 254 rmt_indication(smc,1) ; 255 smt_stat_counter(smc,0) ; 256 ACTIONS_DONE() ; 257 break ; 258 case RM2_RING_OP : 259 /*RM21*/ 260 if (cmd == RM_RING_NON_OP) { 261 smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ; 262 smc->r.loop_avail = FALSE ; 263 RS_SET(smc,RS_RINGOPCHANGE) ; 264 GO_STATE(RM1_NON_OP) ; 265 break ; 266 } 267 /*RM22a*/ 268 else if (cmd == RM_ENABLE_FLAG) { 269 if (smc->mib.m[MAC0].fddiMACMA_UnitdataEnable) 270 smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = TRUE ; 271 else 272 smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ; 273 } 274 /*RM25*/ 275 else if (smc->r.dup_addr_test == DA_FAILED) { 276 smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ; 277 smc->r.loop_avail = FALSE ; 278 smc->r.da_flag = TRUE ; 279 GO_STATE(RM5_RING_OP_DUP) ; 280 break ; 281 } 282 break ; 283 case ACTIONS(RM3_DETECT) : 284 start_rmt_timer0(smc,smc->s.mac_d_max*2,RM_TIMEOUT_D_MAX) ; 285 start_rmt_timer1(smc,smc->s.rmt_t_stuck,RM_TIMEOUT_T_STUCK) ; 286 start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ; 287 sm_mac_check_beacon_claim(smc) ; 288 DB_RMTN(1,"RMT : RM3_DETECT\n",0,0) ; 289 ACTIONS_DONE() ; 290 break ; 291 case RM3_DETECT : 292 if (cmd == RM_TIMEOUT_POLL) { 293 start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL); 294 sm_mac_check_beacon_claim(smc) ; 295 break ; 296 } 297 if (cmd == RM_TIMEOUT_D_MAX) { 298 smc->r.timer0_exp = TRUE ; 299 } 300 /* 301 *jd(22-Feb-1999) 302 * We need a time ">= 2*mac_d_max" since we had finished 303 * Claim or Beacon state. So we will restart timer0 at 304 * every state change. 305 */ 306 if (cmd == RM_TX_STATE_CHANGE) { 307 start_rmt_timer0(smc, 308 smc->s.mac_d_max*2, 309 RM_TIMEOUT_D_MAX) ; 310 } 311 /*RM32*/ 312 if (cmd == RM_RING_OP) { 313 GO_STATE(RM2_RING_OP) ; 314 break ; 315 } 316 /*RM33a*/ 317 else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) 318 && smc->r.bn_flag) { 319 smc->r.bn_flag = FALSE ; 320 } 321 /*RM33b*/ 322 else if (cmd == RM_TRT_EXP && !smc->r.bn_flag) { 323 int tx ; 324 /* 325 * set bn_flag only if in state T4 or T5: 326 * only if we're the beaconer should we start the 327 * trace ! 328 */ 329 if ((tx = sm_mac_get_tx_state(smc)) == 4 || tx == 5) { 330 DB_RMTN(2,"RMT : DETECT && TRT_EXPIRED && T4/T5\n",0,0); 331 smc->r.bn_flag = TRUE ; 332 /* 333 * If one of the upstream stations beaconed 334 * and the link to the upstream neighbor is 335 * lost we need to restart the stuck timer to 336 * check the "stuck beacon" condition. 337 */ 338 start_rmt_timer1(smc,smc->s.rmt_t_stuck, 339 RM_TIMEOUT_T_STUCK) ; 340 } 341 /* 342 * We do NOT need to clear smc->r.bn_flag in case of 343 * not being in state T4 or T5, because the flag 344 * must be cleared in order to get in this condition. 345 */ 346 347 DB_RMTN(2, 348 "RMT : sm_mac_get_tx_state() = %d (bn_flag = %d)\n", 349 tx,smc->r.bn_flag) ; 350 } 351 /*RM34a*/ 352 else if (cmd == RM_MY_CLAIM && smc->r.timer0_exp) { 353 rmt_new_dup_actions(smc) ; 354 GO_STATE(RM4_NON_OP_DUP) ; 355 break ; 356 } 357 /*RM34b*/ 358 else if (cmd == RM_MY_BEACON && smc->r.timer0_exp) { 359 rmt_new_dup_actions(smc) ; 360 GO_STATE(RM4_NON_OP_DUP) ; 361 break ; 362 } 363 /*RM34c*/ 364 else if (cmd == RM_VALID_CLAIM) { 365 rmt_new_dup_actions(smc) ; 366 GO_STATE(RM4_NON_OP_DUP) ; 367 break ; 368 } 369 /*RM36*/ 370 else if (cmd == RM_TIMEOUT_T_STUCK && 371 smc->r.rm_join && smc->r.bn_flag) { 372 GO_STATE(RM6_DIRECTED) ; 373 break ; 374 } 375 break ; 376 case ACTIONS(RM4_NON_OP_DUP) : 377 start_rmt_timer0(smc,smc->s.rmt_t_announce,RM_TIMEOUT_ANNOUNCE); 378 start_rmt_timer1(smc,smc->s.rmt_t_stuck,RM_TIMEOUT_T_STUCK) ; 379 start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ; 380 sm_mac_check_beacon_claim(smc) ; 381 DB_RMTN(1,"RMT : RM4_NON_OP_DUP\n",0,0) ; 382 ACTIONS_DONE() ; 383 break ; 384 case RM4_NON_OP_DUP : 385 if (cmd == RM_TIMEOUT_POLL) { 386 start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL); 387 sm_mac_check_beacon_claim(smc) ; 388 break ; 389 } 390 /*RM41*/ 391 if (!smc->r.da_flag) { 392 GO_STATE(RM1_NON_OP) ; 393 break ; 394 } 395 /*RM44a*/ 396 else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) && 397 smc->r.bn_flag) { 398 smc->r.bn_flag = FALSE ; 399 } 400 /*RM44b*/ 401 else if (cmd == RM_TRT_EXP && !smc->r.bn_flag) { 402 int tx ; 403 /* 404 * set bn_flag only if in state T4 or T5: 405 * only if we're the beaconer should we start the 406 * trace ! 407 */ 408 if ((tx = sm_mac_get_tx_state(smc)) == 4 || tx == 5) { 409 DB_RMTN(2,"RMT : NOPDUP && TRT_EXPIRED && T4/T5\n",0,0); 410 smc->r.bn_flag = TRUE ; 411 /* 412 * If one of the upstream stations beaconed 413 * and the link to the upstream neighbor is 414 * lost we need to restart the stuck timer to 415 * check the "stuck beacon" condition. 416 */ 417 start_rmt_timer1(smc,smc->s.rmt_t_stuck, 418 RM_TIMEOUT_T_STUCK) ; 419 } 420 /* 421 * We do NOT need to clear smc->r.bn_flag in case of 422 * not being in state T4 or T5, because the flag 423 * must be cleared in order to get in this condition. 424 */ 425 426 DB_RMTN(2, 427 "RMT : sm_mac_get_tx_state() = %d (bn_flag = %d)\n", 428 tx,smc->r.bn_flag) ; 429 } 430 /*RM44c*/ 431 else if (cmd == RM_TIMEOUT_ANNOUNCE && !smc->r.bn_flag) { 432 rmt_dup_actions(smc) ; 433 } 434 /*RM45*/ 435 else if (cmd == RM_RING_OP) { 436 smc->r.no_flag = FALSE ; 437 GO_STATE(RM5_RING_OP_DUP) ; 438 break ; 439 } 440 /*RM46*/ 441 else if (cmd == RM_TIMEOUT_T_STUCK && 442 smc->r.rm_join && smc->r.bn_flag) { 443 GO_STATE(RM6_DIRECTED) ; 444 break ; 445 } 446 break ; 447 case ACTIONS(RM5_RING_OP_DUP) : 448 stop_rmt_timer0(smc) ; 449 stop_rmt_timer1(smc) ; 450 stop_rmt_timer2(smc) ; 451 DB_RMTN(1,"RMT : RM5_RING_OP_DUP\n",0,0) ; 452 ACTIONS_DONE() ; 453 break; 454 case RM5_RING_OP_DUP : 455 /*RM52*/ 456 if (smc->r.dup_addr_test == DA_PASSED) { 457 smc->r.da_flag = FALSE ; 458 GO_STATE(RM2_RING_OP) ; 459 break ; 460 } 461 /*RM54*/ 462 else if (cmd == RM_RING_NON_OP) { 463 smc->r.jm_flag = FALSE ; 464 smc->r.bn_flag = FALSE ; 465 GO_STATE(RM4_NON_OP_DUP) ; 466 break ; 467 } 468 break ; 469 case ACTIONS(RM6_DIRECTED) : 470 start_rmt_timer0(smc,smc->s.rmt_t_direct,RM_TIMEOUT_T_DIRECT) ; 471 stop_rmt_timer1(smc) ; 472 start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ; 473 sm_ma_control(smc,MA_DIRECTED) ; 474 RS_SET(smc,RS_BEACON) ; 475 DB_RMTN(1,"RMT : RM6_DIRECTED\n",0,0) ; 476 ACTIONS_DONE() ; 477 break ; 478 case RM6_DIRECTED : 479 /*RM63*/ 480 if (cmd == RM_TIMEOUT_POLL) { 481 start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL); 482 sm_mac_check_beacon_claim(smc) ; 483 #ifndef SUPERNET_3 484 /* Because of problems with the Supernet II chip set 485 * sending of Directed Beacon will stop after 165ms 486 * therefore restart_trt_for_dbcn(smc) will be called 487 * to prevent this. 488 */ 489 restart_trt_for_dbcn(smc) ; 490 #endif /*SUPERNET_3*/ 491 break ; 492 } 493 if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) && 494 !smc->r.da_flag) { 495 smc->r.bn_flag = FALSE ; 496 GO_STATE(RM3_DETECT) ; 497 break ; 498 } 499 /*RM64*/ 500 else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) && 501 smc->r.da_flag) { 502 smc->r.bn_flag = FALSE ; 503 GO_STATE(RM4_NON_OP_DUP) ; 504 break ; 505 } 506 /*RM67*/ 507 else if (cmd == RM_TIMEOUT_T_DIRECT) { 508 GO_STATE(RM7_TRACE) ; 509 break ; 510 } 511 break ; 512 case ACTIONS(RM7_TRACE) : 513 stop_rmt_timer0(smc) ; 514 stop_rmt_timer1(smc) ; 515 stop_rmt_timer2(smc) ; 516 smc->e.trace_prop |= ENTITY_BIT(ENTITY_MAC) ; 517 queue_event(smc,EVENT_ECM,EC_TRACE_PROP) ; 518 DB_RMTN(1,"RMT : RM7_TRACE\n",0,0) ; 519 ACTIONS_DONE() ; 520 break ; 521 case RM7_TRACE : 522 break ; 523 default: 524 SMT_PANIC(smc,SMT_E0122, SMT_E0122_MSG) ; 525 break; 526 } 527 } 528 529 /* 530 * (jd) RMT duplicate address actions 531 * leave the ring or reinsert just as configured 532 */ 533 static void rmt_dup_actions(struct s_smc *smc) 534 { 535 if (smc->r.jm_flag) { 536 } 537 else { 538 if (smc->s.rmt_dup_mac_behavior) { 539 SMT_ERR_LOG(smc,SMT_E0138, SMT_E0138_MSG) ; 540 rmt_reinsert_actions(smc) ; 541 } 542 else { 543 SMT_ERR_LOG(smc,SMT_E0135, SMT_E0135_MSG) ; 544 rmt_leave_actions(smc) ; 545 } 546 } 547 } 548 549 /* 550 * Reconnect to the Ring 551 */ 552 static void rmt_reinsert_actions(struct s_smc *smc) 553 { 554 queue_event(smc,EVENT_ECM,EC_DISCONNECT) ; 555 queue_event(smc,EVENT_ECM,EC_CONNECT) ; 556 } 557 558 /* 559 * duplicate address detected 560 */ 561 static void rmt_new_dup_actions(struct s_smc *smc) 562 { 563 smc->r.da_flag = TRUE ; 564 smc->r.bn_flag = FALSE ; 565 smc->r.jm_flag = FALSE ; 566 /* 567 * we have three options : change address, jam or leave 568 * we leave the ring as default 569 * Optionally it's possible to reinsert after leaving the Ring 570 * but this will not conform with SMT Spec. 571 */ 572 if (smc->s.rmt_dup_mac_behavior) { 573 SMT_ERR_LOG(smc,SMT_E0138, SMT_E0138_MSG) ; 574 rmt_reinsert_actions(smc) ; 575 } 576 else { 577 SMT_ERR_LOG(smc,SMT_E0135, SMT_E0135_MSG) ; 578 rmt_leave_actions(smc) ; 579 } 580 } 581 582 583 /* 584 * leave the ring 585 */ 586 static void rmt_leave_actions(struct s_smc *smc) 587 { 588 queue_event(smc,EVENT_ECM,EC_DISCONNECT) ; 589 /* 590 * Note: Do NOT try again later. (with please reconnect) 591 * The station must be left from the ring! 592 */ 593 } 594 595 /* 596 * SMT timer interface 597 * start RMT timer 0 598 */ 599 static void start_rmt_timer0(struct s_smc *smc, u_long value, int event) 600 { 601 smc->r.timer0_exp = FALSE ; /* clear timer event flag */ 602 smt_timer_start(smc,&smc->r.rmt_timer0,value,EV_TOKEN(EVENT_RMT,event)); 603 } 604 605 /* 606 * SMT timer interface 607 * start RMT timer 1 608 */ 609 static void start_rmt_timer1(struct s_smc *smc, u_long value, int event) 610 { 611 smc->r.timer1_exp = FALSE ; /* clear timer event flag */ 612 smt_timer_start(smc,&smc->r.rmt_timer1,value,EV_TOKEN(EVENT_RMT,event)); 613 } 614 615 /* 616 * SMT timer interface 617 * start RMT timer 2 618 */ 619 static void start_rmt_timer2(struct s_smc *smc, u_long value, int event) 620 { 621 smc->r.timer2_exp = FALSE ; /* clear timer event flag */ 622 smt_timer_start(smc,&smc->r.rmt_timer2,value,EV_TOKEN(EVENT_RMT,event)); 623 } 624 625 /* 626 * SMT timer interface 627 * stop RMT timer 0 628 */ 629 static void stop_rmt_timer0(struct s_smc *smc) 630 { 631 if (smc->r.rmt_timer0.tm_active) 632 smt_timer_stop(smc,&smc->r.rmt_timer0) ; 633 } 634 635 /* 636 * SMT timer interface 637 * stop RMT timer 1 638 */ 639 static void stop_rmt_timer1(struct s_smc *smc) 640 { 641 if (smc->r.rmt_timer1.tm_active) 642 smt_timer_stop(smc,&smc->r.rmt_timer1) ; 643 } 644 645 /* 646 * SMT timer interface 647 * stop RMT timer 2 648 */ 649 static void stop_rmt_timer2(struct s_smc *smc) 650 { 651 if (smc->r.rmt_timer2.tm_active) 652 smt_timer_stop(smc,&smc->r.rmt_timer2) ; 653 } 654 655