diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/net/skfp/srf.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/net/skfp/srf.c')
-rw-r--r-- | drivers/net/skfp/srf.c | 429 |
1 files changed, 429 insertions, 0 deletions
diff --git a/drivers/net/skfp/srf.c b/drivers/net/skfp/srf.c new file mode 100644 index 000000000000..16573aca8b62 --- /dev/null +++ b/drivers/net/skfp/srf.c | |||
@@ -0,0 +1,429 @@ | |||
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 (sizeof(smc->evcs)/sizeof(smc->evcs[0])) | ||
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 (sizeof(evc_inits)/sizeof(evc_inits[0])) | ||
71 | |||
72 | void smt_init_evc(struct s_smc *smc) | ||
73 | { | ||
74 | struct s_srf_evc *evc ; | ||
75 | const struct evc_init *init ; | ||
76 | 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 ; (unsigned) 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) (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 ; (unsigned) 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 | int i ; | ||
164 | struct s_srf_evc *evc ; | ||
165 | |||
166 | for (i = 0, evc = smc->evcs ; (unsigned) 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 | #ifdef DEBUG | ||
177 | static const char * const srf_names[] = { | ||
178 | "None","MACPathChangeEvent", "MACNeighborChangeEvent", | ||
179 | "PORTPathChangeEvent", "PORTUndesiredConnectionAttemptEvent", | ||
180 | "SMTPeerWrapCondition", "SMTHoldCondition", | ||
181 | "MACFrameErrorCondition", "MACDuplicateAddressCondition", | ||
182 | "MACNotCopiedCondition", "PORTEBErrorCondition", | ||
183 | "PORTLerCondition" | ||
184 | } ; | ||
185 | #endif | ||
186 | |||
187 | void smt_srf_event(struct s_smc *smc, int code, int index, int cond) | ||
188 | { | ||
189 | struct s_srf_evc *evc ; | ||
190 | int cond_asserted = 0 ; | ||
191 | int cond_deasserted = 0 ; | ||
192 | int event_occurred = 0 ; | ||
193 | int tsr ; | ||
194 | int T_Limit = 2*TICKS_PER_SECOND ; | ||
195 | |||
196 | if (code == SMT_COND_MAC_DUP_ADDR && cond) { | ||
197 | RS_SET(smc,RS_DUPADDR) ; | ||
198 | } | ||
199 | |||
200 | if (code) { | ||
201 | DB_SMT("SRF: %s index %d\n",srf_names[code],index) ; | ||
202 | |||
203 | if (!(evc = smt_get_evc(smc,code,index))) { | ||
204 | DB_SMT("SRF : smt_get_evc() failed\n",0,0) ; | ||
205 | return ; | ||
206 | } | ||
207 | /* | ||
208 | * ignore condition if no change | ||
209 | */ | ||
210 | if (SMT_IS_CONDITION(code)) { | ||
211 | if (*evc->evc_cond_state == cond) | ||
212 | return ; | ||
213 | } | ||
214 | |||
215 | /* | ||
216 | * set transition time stamp | ||
217 | */ | ||
218 | smt_set_timestamp(smc,smc->mib.fddiSMTTransitionTimeStamp) ; | ||
219 | if (SMT_IS_CONDITION(code)) { | ||
220 | DB_SMT("SRF: condition is %s\n",cond ? "ON":"OFF",0) ; | ||
221 | if (cond) { | ||
222 | *evc->evc_cond_state = TRUE ; | ||
223 | evc->evc_rep_required = TRUE ; | ||
224 | smc->srf.any_report = TRUE ; | ||
225 | cond_asserted = TRUE ; | ||
226 | } | ||
227 | else { | ||
228 | *evc->evc_cond_state = FALSE ; | ||
229 | cond_deasserted = TRUE ; | ||
230 | } | ||
231 | } | ||
232 | else { | ||
233 | if (evc->evc_rep_required) { | ||
234 | *evc->evc_multiple = TRUE ; | ||
235 | } | ||
236 | else { | ||
237 | evc->evc_rep_required = TRUE ; | ||
238 | *evc->evc_multiple = FALSE ; | ||
239 | } | ||
240 | smc->srf.any_report = TRUE ; | ||
241 | event_occurred = TRUE ; | ||
242 | } | ||
243 | #ifdef FDDI_MIB | ||
244 | snmp_srf_event(smc,evc) ; | ||
245 | #endif /* FDDI_MIB */ | ||
246 | } | ||
247 | tsr = smt_get_time() - smc->srf.TSR ; | ||
248 | |||
249 | switch (smc->srf.sr_state) { | ||
250 | case SR0_WAIT : | ||
251 | /* SR01a */ | ||
252 | if (cond_asserted && tsr < T_Limit) { | ||
253 | smc->srf.SRThreshold = THRESHOLD_2 ; | ||
254 | smc->srf.sr_state = SR1_HOLDOFF ; | ||
255 | break ; | ||
256 | } | ||
257 | /* SR01b */ | ||
258 | if (cond_deasserted && tsr < T_Limit) { | ||
259 | smc->srf.sr_state = SR1_HOLDOFF ; | ||
260 | break ; | ||
261 | } | ||
262 | /* SR01c */ | ||
263 | if (event_occurred && tsr < T_Limit) { | ||
264 | smc->srf.sr_state = SR1_HOLDOFF ; | ||
265 | break ; | ||
266 | } | ||
267 | /* SR00b */ | ||
268 | if (cond_asserted && tsr >= T_Limit) { | ||
269 | smc->srf.SRThreshold = THRESHOLD_2 ; | ||
270 | smc->srf.TSR = smt_get_time() ; | ||
271 | smt_send_srf(smc) ; | ||
272 | break ; | ||
273 | } | ||
274 | /* SR00c */ | ||
275 | if (cond_deasserted && tsr >= T_Limit) { | ||
276 | smc->srf.TSR = smt_get_time() ; | ||
277 | smt_send_srf(smc) ; | ||
278 | break ; | ||
279 | } | ||
280 | /* SR00d */ | ||
281 | if (event_occurred && tsr >= T_Limit) { | ||
282 | smc->srf.TSR = smt_get_time() ; | ||
283 | smt_send_srf(smc) ; | ||
284 | break ; | ||
285 | } | ||
286 | /* SR00e */ | ||
287 | if (smc->srf.any_report && (u_long) tsr >= | ||
288 | smc->srf.SRThreshold) { | ||
289 | smc->srf.SRThreshold *= 2 ; | ||
290 | if (smc->srf.SRThreshold > THRESHOLD_32) | ||
291 | smc->srf.SRThreshold = THRESHOLD_32 ; | ||
292 | smc->srf.TSR = smt_get_time() ; | ||
293 | smt_send_srf(smc) ; | ||
294 | break ; | ||
295 | } | ||
296 | /* SR02 */ | ||
297 | if (!smc->mib.fddiSMTStatRptPolicy) { | ||
298 | smc->srf.sr_state = SR2_DISABLED ; | ||
299 | break ; | ||
300 | } | ||
301 | break ; | ||
302 | case SR1_HOLDOFF : | ||
303 | /* SR10b */ | ||
304 | if (tsr >= T_Limit) { | ||
305 | smc->srf.sr_state = SR0_WAIT ; | ||
306 | smc->srf.TSR = smt_get_time() ; | ||
307 | smt_send_srf(smc) ; | ||
308 | break ; | ||
309 | } | ||
310 | /* SR11a */ | ||
311 | if (cond_asserted) { | ||
312 | smc->srf.SRThreshold = THRESHOLD_2 ; | ||
313 | } | ||
314 | /* SR11b */ | ||
315 | /* SR11c */ | ||
316 | /* handled above */ | ||
317 | /* SR12 */ | ||
318 | if (!smc->mib.fddiSMTStatRptPolicy) { | ||
319 | smc->srf.sr_state = SR2_DISABLED ; | ||
320 | break ; | ||
321 | } | ||
322 | break ; | ||
323 | case SR2_DISABLED : | ||
324 | if (smc->mib.fddiSMTStatRptPolicy) { | ||
325 | smc->srf.sr_state = SR0_WAIT ; | ||
326 | smc->srf.TSR = smt_get_time() ; | ||
327 | smc->srf.SRThreshold = THRESHOLD_2 ; | ||
328 | clear_all_rep(smc) ; | ||
329 | break ; | ||
330 | } | ||
331 | break ; | ||
332 | } | ||
333 | } | ||
334 | |||
335 | static void clear_all_rep(struct s_smc *smc) | ||
336 | { | ||
337 | struct s_srf_evc *evc ; | ||
338 | int i ; | ||
339 | |||
340 | for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) { | ||
341 | evc->evc_rep_required = FALSE ; | ||
342 | if (SMT_IS_CONDITION(evc->evc_code)) | ||
343 | *evc->evc_cond_state = FALSE ; | ||
344 | } | ||
345 | smc->srf.any_report = FALSE ; | ||
346 | } | ||
347 | |||
348 | static void clear_reported(struct s_smc *smc) | ||
349 | { | ||
350 | struct s_srf_evc *evc ; | ||
351 | int i ; | ||
352 | |||
353 | smc->srf.any_report = FALSE ; | ||
354 | for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) { | ||
355 | if (SMT_IS_CONDITION(evc->evc_code)) { | ||
356 | if (*evc->evc_cond_state == FALSE) | ||
357 | evc->evc_rep_required = FALSE ; | ||
358 | else | ||
359 | smc->srf.any_report = TRUE ; | ||
360 | } | ||
361 | else { | ||
362 | evc->evc_rep_required = FALSE ; | ||
363 | *evc->evc_multiple = FALSE ; | ||
364 | } | ||
365 | } | ||
366 | } | ||
367 | |||
368 | /* | ||
369 | * build and send SMT SRF frame | ||
370 | */ | ||
371 | static void smt_send_srf(struct s_smc *smc) | ||
372 | { | ||
373 | |||
374 | struct smt_header *smt ; | ||
375 | struct s_srf_evc *evc ; | ||
376 | SK_LOC_DECL(struct s_pcon,pcon) ; | ||
377 | SMbuf *mb ; | ||
378 | int i ; | ||
379 | |||
380 | static const struct fddi_addr SMT_SRF_DA = { | ||
381 | { 0x80, 0x01, 0x43, 0x00, 0x80, 0x08 } | ||
382 | } ; | ||
383 | |||
384 | /* | ||
385 | * build SMT header | ||
386 | */ | ||
387 | if (!smc->r.sm_ma_avail) | ||
388 | return ; | ||
389 | if (!(mb = smt_build_frame(smc,SMT_SRF,SMT_ANNOUNCE,0))) | ||
390 | return ; | ||
391 | |||
392 | RS_SET(smc,RS_SOFTERROR) ; | ||
393 | |||
394 | smt = smtod(mb, struct smt_header *) ; | ||
395 | smt->smt_dest = SMT_SRF_DA ; /* DA == SRF multicast */ | ||
396 | |||
397 | /* | ||
398 | * setup parameter status | ||
399 | */ | ||
400 | pcon.pc_len = SMT_MAX_INFO_LEN ; /* max para length */ | ||
401 | pcon.pc_err = 0 ; /* no error */ | ||
402 | pcon.pc_badset = 0 ; /* no bad set count */ | ||
403 | pcon.pc_p = (void *) (smt + 1) ; /* paras start here */ | ||
404 | |||
405 | smt_add_para(smc,&pcon,(u_short) SMT_P1033,0,0) ; | ||
406 | smt_add_para(smc,&pcon,(u_short) SMT_P1034,0,0) ; | ||
407 | |||
408 | for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) { | ||
409 | if (evc->evc_rep_required) { | ||
410 | smt_add_para(smc,&pcon,evc->evc_para, | ||
411 | (int)evc->evc_index,0) ; | ||
412 | } | ||
413 | } | ||
414 | smt->smt_len = SMT_MAX_INFO_LEN - pcon.pc_len ; | ||
415 | mb->sm_len = smt->smt_len + sizeof(struct smt_header) ; | ||
416 | |||
417 | DB_SMT("SRF: sending SRF at %x, len %d \n",smt,mb->sm_len) ; | ||
418 | DB_SMT("SRF: state SR%d Threshold %d\n", | ||
419 | smc->srf.sr_state,smc->srf.SRThreshold/TICKS_PER_SECOND) ; | ||
420 | #ifdef DEBUG | ||
421 | dump_smt(smc,smt,"SRF Send") ; | ||
422 | #endif | ||
423 | smt_send_frame(smc,mb,FC_SMT_INFO,0) ; | ||
424 | clear_reported(smc) ; | ||
425 | } | ||
426 | |||
427 | #endif /* no BOOT */ | ||
428 | #endif /* no SLIM_SMT */ | ||
429 | |||