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