GNU Linux-libre 4.14.332-gnu1
[releases.git] / drivers / net / fddi / skfp / srf.c
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 7.2 Status Response Frame Implementation
19         SRF state machine and frame generation
20 */
21
22 #include "h/types.h"
23 #include "h/fddi.h"
24 #include "h/smc.h"
25 #include "h/smt_p.h"
26
27 #define KERNEL
28 #include "h/smtstate.h"
29
30 #ifndef SLIM_SMT
31 #ifndef BOOT
32
33 #ifndef lint
34 static const char ID_sccs[] = "@(#)srf.c        1.18 97/08/04 (C) SK " ;
35 #endif
36
37
38 /*
39  * function declarations
40  */
41 static void clear_all_rep(struct s_smc *smc);
42 static void clear_reported(struct s_smc *smc);
43 static void smt_send_srf(struct s_smc *smc);
44 static struct s_srf_evc *smt_get_evc(struct s_smc *smc, int code, int index);
45
46 #define MAX_EVCS        ARRAY_SIZE(smc->evcs)
47
48 struct evc_init {
49         u_char code ;
50         u_char index ;
51         u_char n ;
52         u_short para ;
53 }  ;
54
55 static const struct evc_init evc_inits[] = {
56         { SMT_COND_SMT_PEER_WRAP,               0,1,SMT_P1048   } ,
57
58         { SMT_COND_MAC_DUP_ADDR,                INDEX_MAC, NUMMACS,SMT_P208C } ,
59         { SMT_COND_MAC_FRAME_ERROR,             INDEX_MAC, NUMMACS,SMT_P208D } ,
60         { SMT_COND_MAC_NOT_COPIED,              INDEX_MAC, NUMMACS,SMT_P208E } ,
61         { SMT_EVENT_MAC_NEIGHBOR_CHANGE,        INDEX_MAC, NUMMACS,SMT_P208F } ,
62         { SMT_EVENT_MAC_PATH_CHANGE,            INDEX_MAC, NUMMACS,SMT_P2090 } ,
63
64         { SMT_COND_PORT_LER,                    INDEX_PORT,NUMPHYS,SMT_P4050 } ,
65         { SMT_COND_PORT_EB_ERROR,               INDEX_PORT,NUMPHYS,SMT_P4052 } ,
66         { SMT_EVENT_PORT_CONNECTION,            INDEX_PORT,NUMPHYS,SMT_P4051 } ,
67         { SMT_EVENT_PORT_PATH_CHANGE,           INDEX_PORT,NUMPHYS,SMT_P4053 } ,
68 } ;
69
70 #define MAX_INIT_EVC    ARRAY_SIZE(evc_inits)
71
72 void smt_init_evc(struct s_smc *smc)
73 {
74         struct s_srf_evc        *evc ;
75         const struct evc_init   *init ;
76         unsigned int            i ;
77         int                     index ;
78         int                     offset ;
79
80         static u_char           fail_safe = FALSE ;
81
82         memset((char *)smc->evcs,0,sizeof(smc->evcs)) ;
83
84         evc = smc->evcs ;
85         init = evc_inits ;
86
87         for (i = 0 ; i < MAX_INIT_EVC ; i++) {
88                 for (index = 0 ; index < init->n ; index++) {
89                         evc->evc_code = init->code ;
90                         evc->evc_para = init->para ;
91                         evc->evc_index = init->index + index ;
92 #ifndef DEBUG
93                         evc->evc_multiple = &fail_safe ;
94                         evc->evc_cond_state = &fail_safe ;
95 #endif
96                         evc++ ;
97                 }
98                 init++ ;
99         }
100
101         if ((unsigned int) (evc - smc->evcs) > MAX_EVCS) {
102                 SMT_PANIC(smc,SMT_E0127, SMT_E0127_MSG) ;
103         }
104
105         /*
106          * conditions
107          */
108         smc->evcs[0].evc_cond_state = &smc->mib.fddiSMTPeerWrapFlag ;
109         smc->evcs[1].evc_cond_state =
110                 &smc->mib.m[MAC0].fddiMACDuplicateAddressCond ;
111         smc->evcs[2].evc_cond_state =
112                 &smc->mib.m[MAC0].fddiMACFrameErrorFlag ;
113         smc->evcs[3].evc_cond_state =
114                 &smc->mib.m[MAC0].fddiMACNotCopiedFlag ;
115
116         /*
117          * events
118          */
119         smc->evcs[4].evc_multiple = &smc->mib.m[MAC0].fddiMACMultiple_N ;
120         smc->evcs[5].evc_multiple = &smc->mib.m[MAC0].fddiMACMultiple_P ;
121
122         offset = 6 ;
123         for (i = 0 ; i < NUMPHYS ; i++) {
124                 /*
125                  * conditions
126                  */
127                 smc->evcs[offset + 0*NUMPHYS].evc_cond_state =
128                         &smc->mib.p[i].fddiPORTLerFlag ;
129                 smc->evcs[offset + 1*NUMPHYS].evc_cond_state =
130                         &smc->mib.p[i].fddiPORTEB_Condition ;
131
132                 /*
133                  * events
134                  */
135                 smc->evcs[offset + 2*NUMPHYS].evc_multiple =
136                         &smc->mib.p[i].fddiPORTMultiple_U ;
137                 smc->evcs[offset + 3*NUMPHYS].evc_multiple =
138                         &smc->mib.p[i].fddiPORTMultiple_P ;
139                 offset++ ;
140         }
141 #ifdef  DEBUG
142         for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) {
143                 if (SMT_IS_CONDITION(evc->evc_code)) {
144                         if (!evc->evc_cond_state) {
145                                 SMT_PANIC(smc,SMT_E0128, SMT_E0128_MSG) ;
146                         }
147                         evc->evc_multiple = &fail_safe ;
148                 }
149                 else {
150                         if (!evc->evc_multiple) {
151                                 SMT_PANIC(smc,SMT_E0129, SMT_E0129_MSG) ;
152                         }
153                         evc->evc_cond_state = &fail_safe ;
154                 }
155         }
156 #endif
157         smc->srf.TSR = smt_get_time() ;
158         smc->srf.sr_state = SR0_WAIT ;
159 }
160
161 static struct s_srf_evc *smt_get_evc(struct s_smc *smc, int code, int index)
162 {
163         unsigned int            i ;
164         struct s_srf_evc        *evc ;
165
166         for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) {
167                 if (evc->evc_code == code && evc->evc_index == index)
168                         return evc;
169         }
170         return NULL;
171 }
172
173 #define THRESHOLD_2     (2*TICKS_PER_SECOND)
174 #define THRESHOLD_32    (32*TICKS_PER_SECOND)
175
176 static const char * const srf_names[] = {
177         "None","MACPathChangeEvent",    "MACNeighborChangeEvent",
178         "PORTPathChangeEvent",          "PORTUndesiredConnectionAttemptEvent",
179         "SMTPeerWrapCondition",         "SMTHoldCondition",
180         "MACFrameErrorCondition",       "MACDuplicateAddressCondition",
181         "MACNotCopiedCondition",        "PORTEBErrorCondition",
182         "PORTLerCondition"
183 } ;
184
185 void smt_srf_event(struct s_smc *smc, int code, int index, int cond)
186 {
187         struct s_srf_evc        *evc ;
188         int                     cond_asserted = 0 ;
189         int                     cond_deasserted = 0 ;
190         int                     event_occurred = 0 ;
191         int                     tsr ;
192         int                     T_Limit = 2*TICKS_PER_SECOND ;
193
194         if (code == SMT_COND_MAC_DUP_ADDR && cond) {
195                 RS_SET(smc,RS_DUPADDR) ;
196         }
197
198         if (code) {
199                 DB_SMT("SRF: %s index %d", srf_names[code], index);
200
201                 if (!(evc = smt_get_evc(smc,code,index))) {
202                         DB_SMT("SRF : smt_get_evc() failed");
203                         return ;
204                 }
205                 /*
206                  * ignore condition if no change
207                  */
208                 if (SMT_IS_CONDITION(code)) {
209                         if (*evc->evc_cond_state == cond)
210                                 return ;
211                 }
212
213                 /*
214                  * set transition time stamp
215                  */
216                 smt_set_timestamp(smc,smc->mib.fddiSMTTransitionTimeStamp) ;
217                 if (SMT_IS_CONDITION(code)) {
218                         DB_SMT("SRF: condition is %s", cond ? "ON" : "OFF");
219                         if (cond) {
220                                 *evc->evc_cond_state = TRUE ;
221                                 evc->evc_rep_required = TRUE ;
222                                 smc->srf.any_report = TRUE ;
223                                 cond_asserted = TRUE ;
224                         }
225                         else {
226                                 *evc->evc_cond_state = FALSE ;
227                                 cond_deasserted = TRUE ;
228                         }
229                 }
230                 else {
231                         if (evc->evc_rep_required) {
232                                 *evc->evc_multiple  = TRUE ;
233                         }
234                         else {
235                                 evc->evc_rep_required = TRUE ;
236                                 *evc->evc_multiple  = FALSE ;
237                         }
238                         smc->srf.any_report = TRUE ;
239                         event_occurred = TRUE ;
240                 }
241 #ifdef  FDDI_MIB
242                 snmp_srf_event(smc,evc) ;
243 #endif  /* FDDI_MIB */
244         }
245         tsr = smt_get_time() - smc->srf.TSR ;
246
247         switch (smc->srf.sr_state) {
248         case SR0_WAIT :
249                 /* SR01a */
250                 if (cond_asserted && tsr < T_Limit) {
251                         smc->srf.SRThreshold = THRESHOLD_2 ;
252                         smc->srf.sr_state = SR1_HOLDOFF ;
253                         break ;
254                 }
255                 /* SR01b */
256                 if (cond_deasserted && tsr < T_Limit) {
257                         smc->srf.sr_state = SR1_HOLDOFF ;
258                         break ;
259                 }
260                 /* SR01c */
261                 if (event_occurred && tsr < T_Limit) {
262                         smc->srf.sr_state = SR1_HOLDOFF ;
263                         break ;
264                 }
265                 /* SR00b */
266                 if (cond_asserted && tsr >= T_Limit) {
267                         smc->srf.SRThreshold = THRESHOLD_2 ;
268                         smc->srf.TSR = smt_get_time() ;
269                         smt_send_srf(smc) ;
270                         break ;
271                 }
272                 /* SR00c */
273                 if (cond_deasserted && tsr >= T_Limit) {
274                         smc->srf.TSR = smt_get_time() ;
275                         smt_send_srf(smc) ;
276                         break ;
277                 }
278                 /* SR00d */
279                 if (event_occurred && tsr >= T_Limit) {
280                         smc->srf.TSR = smt_get_time() ;
281                         smt_send_srf(smc) ;
282                         break ;
283                 }
284                 /* SR00e */
285                 if (smc->srf.any_report && (u_long) tsr >=
286                         smc->srf.SRThreshold) {
287                         smc->srf.SRThreshold *= 2 ;
288                         if (smc->srf.SRThreshold > THRESHOLD_32)
289                                 smc->srf.SRThreshold = THRESHOLD_32 ;
290                         smc->srf.TSR = smt_get_time() ;
291                         smt_send_srf(smc) ;
292                         break ;
293                 }
294                 /* SR02 */
295                 if (!smc->mib.fddiSMTStatRptPolicy) {
296                         smc->srf.sr_state = SR2_DISABLED ;
297                         break ;
298                 }
299                 break ;
300         case SR1_HOLDOFF :
301                 /* SR10b */
302                 if (tsr >= T_Limit) {
303                         smc->srf.sr_state = SR0_WAIT ;
304                         smc->srf.TSR = smt_get_time() ;
305                         smt_send_srf(smc) ;
306                         break ;
307                 }
308                 /* SR11a */
309                 if (cond_asserted) {
310                         smc->srf.SRThreshold = THRESHOLD_2 ;
311                 }
312                 /* SR11b */
313                 /* SR11c */
314                 /* handled above */
315                 /* SR12 */
316                 if (!smc->mib.fddiSMTStatRptPolicy) {
317                         smc->srf.sr_state = SR2_DISABLED ;
318                         break ;
319                 }
320                 break ;
321         case SR2_DISABLED :
322                 if (smc->mib.fddiSMTStatRptPolicy) {
323                         smc->srf.sr_state = SR0_WAIT ;
324                         smc->srf.TSR = smt_get_time() ;
325                         smc->srf.SRThreshold = THRESHOLD_2 ;
326                         clear_all_rep(smc) ;
327                         break ;
328                 }
329                 break ;
330         }
331 }
332
333 static void clear_all_rep(struct s_smc *smc)
334 {
335         struct s_srf_evc        *evc ;
336         unsigned int            i ;
337
338         for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) {
339                 evc->evc_rep_required = FALSE ;
340                 if (SMT_IS_CONDITION(evc->evc_code))
341                         *evc->evc_cond_state = FALSE ;
342         }
343         smc->srf.any_report = FALSE ;
344 }
345
346 static void clear_reported(struct s_smc *smc)
347 {
348         struct s_srf_evc        *evc ;
349         unsigned int            i ;
350
351         smc->srf.any_report = FALSE ;
352         for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) {
353                 if (SMT_IS_CONDITION(evc->evc_code)) {
354                         if (*evc->evc_cond_state == FALSE)
355                                 evc->evc_rep_required = FALSE ;
356                         else
357                                 smc->srf.any_report = TRUE ;
358                 }
359                 else {
360                         evc->evc_rep_required = FALSE ;
361                         *evc->evc_multiple = FALSE ;
362                 }
363         }
364 }
365
366 /*
367  * build and send SMT SRF frame
368  */
369 static void smt_send_srf(struct s_smc *smc)
370 {
371
372         struct smt_header       *smt ;
373         struct s_srf_evc        *evc ;
374         SK_LOC_DECL(struct s_pcon,pcon) ;
375         SMbuf                   *mb ;
376         unsigned int            i ;
377
378         static const struct fddi_addr SMT_SRF_DA = {
379                 { 0x80, 0x01, 0x43, 0x00, 0x80, 0x08 }
380         } ;
381
382         /*
383          * build SMT header
384          */
385         if (!smc->r.sm_ma_avail)
386                 return ;
387         if (!(mb = smt_build_frame(smc,SMT_SRF,SMT_ANNOUNCE,0)))
388                 return ;
389
390         RS_SET(smc,RS_SOFTERROR) ;
391
392         smt = smtod(mb, struct smt_header *) ;
393         smt->smt_dest = SMT_SRF_DA ;            /* DA == SRF multicast */
394
395         /*
396          * setup parameter status
397          */
398         pcon.pc_len = SMT_MAX_INFO_LEN ;        /* max para length */
399         pcon.pc_err = 0 ;                       /* no error */
400         pcon.pc_badset = 0 ;                    /* no bad set count */
401         pcon.pc_p = (void *) (smt + 1) ;        /* paras start here */
402
403         smt_add_para(smc,&pcon,(u_short) SMT_P1033,0,0) ;
404         smt_add_para(smc,&pcon,(u_short) SMT_P1034,0,0) ;
405
406         for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) {
407                 if (evc->evc_rep_required) {
408                         smt_add_para(smc,&pcon,evc->evc_para,
409                                 (int)evc->evc_index,0) ;
410                 }
411         }
412         smt->smt_len = SMT_MAX_INFO_LEN - pcon.pc_len ;
413         mb->sm_len = smt->smt_len + sizeof(struct smt_header) ;
414
415         DB_SMT("SRF: sending SRF at %p, len %d", smt, mb->sm_len);
416         DB_SMT("SRF: state SR%d Threshold %lu",
417                smc->srf.sr_state, smc->srf.SRThreshold / TICKS_PER_SECOND);
418 #ifdef  DEBUG
419         dump_smt(smc,smt,"SRF Send") ;
420 #endif
421         smt_send_frame(smc,mb,FC_SMT_INFO,0) ;
422         clear_reported(smc) ;
423 }
424
425 #endif  /* no BOOT */
426 #endif  /* no SLIM_SMT */
427