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