diff options
author | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-07-31 03:06:29 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-08-27 03:58:13 -0400 |
commit | 33f810b2036f13f1b123062a9e5c1794d400ce81 (patch) | |
tree | 370b55026f4bd856e96842f86af631ca2bab3da2 /drivers/net/skfp/smt.c | |
parent | 3cd0999d134235d64b175edd2eb1d46ebc97b377 (diff) |
fddi: Move the FDDI drivers
Move the FDDI drivers into drivers/net/fddi/ and make the
necessary Kconfig and Makefile changes.
CC: "Maciej W. Rozycki" <macro@linux-mips.org>
CC: Christoph Goos <cgoos@syskonnect.de>
CC: <linux@syskonnect.de>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/skfp/smt.c')
-rw-r--r-- | drivers/net/skfp/smt.c | 2046 |
1 files changed, 0 insertions, 2046 deletions
diff --git a/drivers/net/skfp/smt.c b/drivers/net/skfp/smt.c deleted file mode 100644 index 08d94329c12f..000000000000 --- a/drivers/net/skfp/smt.c +++ /dev/null | |||
@@ -1,2046 +0,0 @@ | |||
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 | #include "h/types.h" | ||
18 | #include "h/fddi.h" | ||
19 | #include "h/smc.h" | ||
20 | #include "h/smt_p.h" | ||
21 | #include <linux/bitrev.h> | ||
22 | #include <linux/kernel.h> | ||
23 | |||
24 | #define KERNEL | ||
25 | #include "h/smtstate.h" | ||
26 | |||
27 | #ifndef lint | ||
28 | static const char ID_sccs[] = "@(#)smt.c 2.43 98/11/23 (C) SK " ; | ||
29 | #endif | ||
30 | |||
31 | /* | ||
32 | * FC in SMbuf | ||
33 | */ | ||
34 | #define m_fc(mb) ((mb)->sm_data[0]) | ||
35 | |||
36 | #define SMT_TID_MAGIC 0x1f0a7b3c | ||
37 | |||
38 | #ifdef DEBUG | ||
39 | static const char *const smt_type_name[] = { | ||
40 | "SMT_00??", "SMT_INFO", "SMT_02??", "SMT_03??", | ||
41 | "SMT_04??", "SMT_05??", "SMT_06??", "SMT_07??", | ||
42 | "SMT_08??", "SMT_09??", "SMT_0A??", "SMT_0B??", | ||
43 | "SMT_0C??", "SMT_0D??", "SMT_0E??", "SMT_NSA" | ||
44 | } ; | ||
45 | |||
46 | static const char *const smt_class_name[] = { | ||
47 | "UNKNOWN","NIF","SIF_CONFIG","SIF_OPER","ECF","RAF","RDF", | ||
48 | "SRF","PMF_GET","PMF_SET","ESF" | ||
49 | } ; | ||
50 | #endif | ||
51 | #define LAST_CLASS (SMT_PMF_SET) | ||
52 | |||
53 | static const struct fddi_addr SMT_Unknown = { | ||
54 | { 0,0,0x1f,0,0,0 } | ||
55 | } ; | ||
56 | |||
57 | /* | ||
58 | * function prototypes | ||
59 | */ | ||
60 | #ifdef LITTLE_ENDIAN | ||
61 | static int smt_swap_short(u_short s); | ||
62 | #endif | ||
63 | static int mac_index(struct s_smc *smc, int mac); | ||
64 | static int phy_index(struct s_smc *smc, int phy); | ||
65 | static int mac_con_resource_index(struct s_smc *smc, int mac); | ||
66 | static int phy_con_resource_index(struct s_smc *smc, int phy); | ||
67 | static void smt_send_rdf(struct s_smc *smc, SMbuf *rej, int fc, int reason, | ||
68 | int local); | ||
69 | static void smt_send_nif(struct s_smc *smc, const struct fddi_addr *dest, | ||
70 | int fc, u_long tid, int type, int local); | ||
71 | static void smt_send_ecf(struct s_smc *smc, struct fddi_addr *dest, int fc, | ||
72 | u_long tid, int type, int len); | ||
73 | static void smt_echo_test(struct s_smc *smc, int dna); | ||
74 | static void smt_send_sif_config(struct s_smc *smc, struct fddi_addr *dest, | ||
75 | u_long tid, int local); | ||
76 | static void smt_send_sif_operation(struct s_smc *smc, struct fddi_addr *dest, | ||
77 | u_long tid, int local); | ||
78 | #ifdef LITTLE_ENDIAN | ||
79 | static void smt_string_swap(char *data, const char *format, int len); | ||
80 | #endif | ||
81 | static void smt_add_frame_len(SMbuf *mb, int len); | ||
82 | static void smt_fill_una(struct s_smc *smc, struct smt_p_una *una); | ||
83 | static void smt_fill_sde(struct s_smc *smc, struct smt_p_sde *sde); | ||
84 | static void smt_fill_state(struct s_smc *smc, struct smt_p_state *state); | ||
85 | static void smt_fill_timestamp(struct s_smc *smc, struct smt_p_timestamp *ts); | ||
86 | static void smt_fill_policy(struct s_smc *smc, struct smt_p_policy *policy); | ||
87 | static void smt_fill_latency(struct s_smc *smc, struct smt_p_latency *latency); | ||
88 | static void smt_fill_neighbor(struct s_smc *smc, struct smt_p_neighbor *neighbor); | ||
89 | static int smt_fill_path(struct s_smc *smc, struct smt_p_path *path); | ||
90 | static void smt_fill_mac_status(struct s_smc *smc, struct smt_p_mac_status *st); | ||
91 | static void smt_fill_lem(struct s_smc *smc, struct smt_p_lem *lem, int phy); | ||
92 | static void smt_fill_version(struct s_smc *smc, struct smt_p_version *vers); | ||
93 | static void smt_fill_fsc(struct s_smc *smc, struct smt_p_fsc *fsc); | ||
94 | static void smt_fill_mac_counter(struct s_smc *smc, struct smt_p_mac_counter *mc); | ||
95 | static void smt_fill_mac_fnc(struct s_smc *smc, struct smt_p_mac_fnc *fnc); | ||
96 | static void smt_fill_manufacturer(struct s_smc *smc, | ||
97 | struct smp_p_manufacturer *man); | ||
98 | static void smt_fill_user(struct s_smc *smc, struct smp_p_user *user); | ||
99 | static void smt_fill_setcount(struct s_smc *smc, struct smt_p_setcount *setcount); | ||
100 | static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long seed, | ||
101 | int len); | ||
102 | |||
103 | static void smt_clear_una_dna(struct s_smc *smc); | ||
104 | static void smt_clear_old_una_dna(struct s_smc *smc); | ||
105 | #ifdef CONCENTRATOR | ||
106 | static int entity_to_index(void); | ||
107 | #endif | ||
108 | static void update_dac(struct s_smc *smc, int report); | ||
109 | static int div_ratio(u_long upper, u_long lower); | ||
110 | #ifdef USE_CAN_ADDR | ||
111 | static void hwm_conv_can(struct s_smc *smc, char *data, int len); | ||
112 | #else | ||
113 | #define hwm_conv_can(smc,data,len) | ||
114 | #endif | ||
115 | |||
116 | |||
117 | static inline int is_my_addr(const struct s_smc *smc, | ||
118 | const struct fddi_addr *addr) | ||
119 | { | ||
120 | return(*(short *)(&addr->a[0]) == | ||
121 | *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[0]) | ||
122 | && *(short *)(&addr->a[2]) == | ||
123 | *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[2]) | ||
124 | && *(short *)(&addr->a[4]) == | ||
125 | *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[4])) ; | ||
126 | } | ||
127 | |||
128 | static inline int is_broadcast(const struct fddi_addr *addr) | ||
129 | { | ||
130 | return *(u_short *)(&addr->a[0]) == 0xffff && | ||
131 | *(u_short *)(&addr->a[2]) == 0xffff && | ||
132 | *(u_short *)(&addr->a[4]) == 0xffff; | ||
133 | } | ||
134 | |||
135 | static inline int is_individual(const struct fddi_addr *addr) | ||
136 | { | ||
137 | return !(addr->a[0] & GROUP_ADDR); | ||
138 | } | ||
139 | |||
140 | static inline int is_equal(const struct fddi_addr *addr1, | ||
141 | const struct fddi_addr *addr2) | ||
142 | { | ||
143 | return *(u_short *)(&addr1->a[0]) == *(u_short *)(&addr2->a[0]) && | ||
144 | *(u_short *)(&addr1->a[2]) == *(u_short *)(&addr2->a[2]) && | ||
145 | *(u_short *)(&addr1->a[4]) == *(u_short *)(&addr2->a[4]); | ||
146 | } | ||
147 | |||
148 | /* | ||
149 | * list of mandatory paras in frames | ||
150 | */ | ||
151 | static const u_short plist_nif[] = { SMT_P_UNA,SMT_P_SDE,SMT_P_STATE,0 } ; | ||
152 | |||
153 | /* | ||
154 | * init SMT agent | ||
155 | */ | ||
156 | void smt_agent_init(struct s_smc *smc) | ||
157 | { | ||
158 | int i ; | ||
159 | |||
160 | /* | ||
161 | * get MAC address | ||
162 | */ | ||
163 | smc->mib.m[MAC0].fddiMACSMTAddress = smc->hw.fddi_home_addr ; | ||
164 | |||
165 | /* | ||
166 | * get OUI address from driver (bia == built-in-address) | ||
167 | */ | ||
168 | smc->mib.fddiSMTStationId.sid_oem[0] = 0 ; | ||
169 | smc->mib.fddiSMTStationId.sid_oem[1] = 0 ; | ||
170 | driver_get_bia(smc,&smc->mib.fddiSMTStationId.sid_node) ; | ||
171 | for (i = 0 ; i < 6 ; i ++) { | ||
172 | smc->mib.fddiSMTStationId.sid_node.a[i] = | ||
173 | bitrev8(smc->mib.fddiSMTStationId.sid_node.a[i]); | ||
174 | } | ||
175 | smc->mib.fddiSMTManufacturerData[0] = | ||
176 | smc->mib.fddiSMTStationId.sid_node.a[0] ; | ||
177 | smc->mib.fddiSMTManufacturerData[1] = | ||
178 | smc->mib.fddiSMTStationId.sid_node.a[1] ; | ||
179 | smc->mib.fddiSMTManufacturerData[2] = | ||
180 | smc->mib.fddiSMTStationId.sid_node.a[2] ; | ||
181 | smc->sm.smt_tid = 0 ; | ||
182 | smc->mib.m[MAC0].fddiMACDupAddressTest = DA_NONE ; | ||
183 | smc->mib.m[MAC0].fddiMACUNDA_Flag = FALSE ; | ||
184 | #ifndef SLIM_SMT | ||
185 | smt_clear_una_dna(smc) ; | ||
186 | smt_clear_old_una_dna(smc) ; | ||
187 | #endif | ||
188 | for (i = 0 ; i < SMT_MAX_TEST ; i++) | ||
189 | smc->sm.pend[i] = 0 ; | ||
190 | smc->sm.please_reconnect = 0 ; | ||
191 | smc->sm.uniq_ticks = 0 ; | ||
192 | } | ||
193 | |||
194 | /* | ||
195 | * SMT task | ||
196 | * forever | ||
197 | * delay 30 seconds | ||
198 | * send NIF | ||
199 | * check tvu & tvd | ||
200 | * end | ||
201 | */ | ||
202 | void smt_agent_task(struct s_smc *smc) | ||
203 | { | ||
204 | smt_timer_start(smc,&smc->sm.smt_timer, (u_long)1000000L, | ||
205 | EV_TOKEN(EVENT_SMT,SM_TIMER)) ; | ||
206 | DB_SMT("SMT agent task\n",0,0) ; | ||
207 | } | ||
208 | |||
209 | #ifndef SMT_REAL_TOKEN_CT | ||
210 | void smt_emulate_token_ct(struct s_smc *smc, int mac_index) | ||
211 | { | ||
212 | u_long count; | ||
213 | u_long time; | ||
214 | |||
215 | |||
216 | time = smt_get_time(); | ||
217 | count = ((time - smc->sm.last_tok_time[mac_index]) * | ||
218 | 100)/TICKS_PER_SECOND; | ||
219 | |||
220 | /* | ||
221 | * Only when ring is up we will have a token count. The | ||
222 | * flag is unfortunately a single instance value. This | ||
223 | * doesn't matter now, because we currently have only | ||
224 | * one MAC instance. | ||
225 | */ | ||
226 | if (smc->hw.mac_ring_is_up){ | ||
227 | smc->mib.m[mac_index].fddiMACToken_Ct += count; | ||
228 | } | ||
229 | |||
230 | /* Remember current time */ | ||
231 | smc->sm.last_tok_time[mac_index] = time; | ||
232 | |||
233 | } | ||
234 | #endif | ||
235 | |||
236 | /*ARGSUSED1*/ | ||
237 | void smt_event(struct s_smc *smc, int event) | ||
238 | { | ||
239 | u_long time ; | ||
240 | #ifndef SMT_REAL_TOKEN_CT | ||
241 | int i ; | ||
242 | #endif | ||
243 | |||
244 | |||
245 | if (smc->sm.please_reconnect) { | ||
246 | smc->sm.please_reconnect -- ; | ||
247 | if (smc->sm.please_reconnect == 0) { | ||
248 | /* Counted down */ | ||
249 | queue_event(smc,EVENT_ECM,EC_CONNECT) ; | ||
250 | } | ||
251 | } | ||
252 | |||
253 | if (event == SM_FAST) | ||
254 | return ; | ||
255 | |||
256 | /* | ||
257 | * timer for periodic cleanup in driver | ||
258 | * reset and start the watchdog (FM2) | ||
259 | * ESS timer | ||
260 | * SBA timer | ||
261 | */ | ||
262 | smt_timer_poll(smc) ; | ||
263 | smt_start_watchdog(smc) ; | ||
264 | #ifndef SLIM_SMT | ||
265 | #ifndef BOOT | ||
266 | #ifdef ESS | ||
267 | ess_timer_poll(smc) ; | ||
268 | #endif | ||
269 | #endif | ||
270 | #ifdef SBA | ||
271 | sba_timer_poll(smc) ; | ||
272 | #endif | ||
273 | |||
274 | smt_srf_event(smc,0,0,0) ; | ||
275 | |||
276 | #endif /* no SLIM_SMT */ | ||
277 | |||
278 | time = smt_get_time() ; | ||
279 | |||
280 | if (time - smc->sm.smt_last_lem >= TICKS_PER_SECOND*8) { | ||
281 | /* | ||
282 | * Use 8 sec. for the time intervall, it simplifies the | ||
283 | * LER estimation. | ||
284 | */ | ||
285 | struct fddi_mib_m *mib ; | ||
286 | u_long upper ; | ||
287 | u_long lower ; | ||
288 | int cond ; | ||
289 | int port; | ||
290 | struct s_phy *phy ; | ||
291 | /* | ||
292 | * calculate LEM bit error rate | ||
293 | */ | ||
294 | sm_lem_evaluate(smc) ; | ||
295 | smc->sm.smt_last_lem = time ; | ||
296 | |||
297 | /* | ||
298 | * check conditions | ||
299 | */ | ||
300 | #ifndef SLIM_SMT | ||
301 | mac_update_counter(smc) ; | ||
302 | mib = smc->mib.m ; | ||
303 | upper = | ||
304 | (mib->fddiMACLost_Ct - mib->fddiMACOld_Lost_Ct) + | ||
305 | (mib->fddiMACError_Ct - mib->fddiMACOld_Error_Ct) ; | ||
306 | lower = | ||
307 | (mib->fddiMACFrame_Ct - mib->fddiMACOld_Frame_Ct) + | ||
308 | (mib->fddiMACLost_Ct - mib->fddiMACOld_Lost_Ct) ; | ||
309 | mib->fddiMACFrameErrorRatio = div_ratio(upper,lower) ; | ||
310 | |||
311 | cond = | ||
312 | ((!mib->fddiMACFrameErrorThreshold && | ||
313 | mib->fddiMACError_Ct != mib->fddiMACOld_Error_Ct) || | ||
314 | (mib->fddiMACFrameErrorRatio > | ||
315 | mib->fddiMACFrameErrorThreshold)) ; | ||
316 | |||
317 | if (cond != mib->fddiMACFrameErrorFlag) | ||
318 | smt_srf_event(smc,SMT_COND_MAC_FRAME_ERROR, | ||
319 | INDEX_MAC,cond) ; | ||
320 | |||
321 | upper = | ||
322 | (mib->fddiMACNotCopied_Ct - mib->fddiMACOld_NotCopied_Ct) ; | ||
323 | lower = | ||
324 | upper + | ||
325 | (mib->fddiMACCopied_Ct - mib->fddiMACOld_Copied_Ct) ; | ||
326 | mib->fddiMACNotCopiedRatio = div_ratio(upper,lower) ; | ||
327 | |||
328 | cond = | ||
329 | ((!mib->fddiMACNotCopiedThreshold && | ||
330 | mib->fddiMACNotCopied_Ct != | ||
331 | mib->fddiMACOld_NotCopied_Ct)|| | ||
332 | (mib->fddiMACNotCopiedRatio > | ||
333 | mib->fddiMACNotCopiedThreshold)) ; | ||
334 | |||
335 | if (cond != mib->fddiMACNotCopiedFlag) | ||
336 | smt_srf_event(smc,SMT_COND_MAC_NOT_COPIED, | ||
337 | INDEX_MAC,cond) ; | ||
338 | |||
339 | /* | ||
340 | * set old values | ||
341 | */ | ||
342 | mib->fddiMACOld_Frame_Ct = mib->fddiMACFrame_Ct ; | ||
343 | mib->fddiMACOld_Copied_Ct = mib->fddiMACCopied_Ct ; | ||
344 | mib->fddiMACOld_Error_Ct = mib->fddiMACError_Ct ; | ||
345 | mib->fddiMACOld_Lost_Ct = mib->fddiMACLost_Ct ; | ||
346 | mib->fddiMACOld_NotCopied_Ct = mib->fddiMACNotCopied_Ct ; | ||
347 | |||
348 | /* | ||
349 | * Check port EBError Condition | ||
350 | */ | ||
351 | for (port = 0; port < NUMPHYS; port ++) { | ||
352 | phy = &smc->y[port] ; | ||
353 | |||
354 | if (!phy->mib->fddiPORTHardwarePresent) { | ||
355 | continue; | ||
356 | } | ||
357 | |||
358 | cond = (phy->mib->fddiPORTEBError_Ct - | ||
359 | phy->mib->fddiPORTOldEBError_Ct > 5) ; | ||
360 | |||
361 | /* If ratio is more than 5 in 8 seconds | ||
362 | * Set the condition. | ||
363 | */ | ||
364 | smt_srf_event(smc,SMT_COND_PORT_EB_ERROR, | ||
365 | (int) (INDEX_PORT+ phy->np) ,cond) ; | ||
366 | |||
367 | /* | ||
368 | * set old values | ||
369 | */ | ||
370 | phy->mib->fddiPORTOldEBError_Ct = | ||
371 | phy->mib->fddiPORTEBError_Ct ; | ||
372 | } | ||
373 | |||
374 | #endif /* no SLIM_SMT */ | ||
375 | } | ||
376 | |||
377 | #ifndef SLIM_SMT | ||
378 | |||
379 | if (time - smc->sm.smt_last_notify >= (u_long) | ||
380 | (smc->mib.fddiSMTTT_Notify * TICKS_PER_SECOND) ) { | ||
381 | /* | ||
382 | * we can either send an announcement or a request | ||
383 | * a request will trigger a reply so that we can update | ||
384 | * our dna | ||
385 | * note: same tid must be used until reply is received | ||
386 | */ | ||
387 | if (!smc->sm.pend[SMT_TID_NIF]) | ||
388 | smc->sm.pend[SMT_TID_NIF] = smt_get_tid(smc) ; | ||
389 | smt_send_nif(smc,&fddi_broadcast, FC_SMT_NSA, | ||
390 | smc->sm.pend[SMT_TID_NIF], SMT_REQUEST,0) ; | ||
391 | smc->sm.smt_last_notify = time ; | ||
392 | } | ||
393 | |||
394 | /* | ||
395 | * check timer | ||
396 | */ | ||
397 | if (smc->sm.smt_tvu && | ||
398 | time - smc->sm.smt_tvu > 228*TICKS_PER_SECOND) { | ||
399 | DB_SMT("SMT : UNA expired\n",0,0) ; | ||
400 | smc->sm.smt_tvu = 0 ; | ||
401 | |||
402 | if (!is_equal(&smc->mib.m[MAC0].fddiMACUpstreamNbr, | ||
403 | &SMT_Unknown)){ | ||
404 | /* Do not update unknown address */ | ||
405 | smc->mib.m[MAC0].fddiMACOldUpstreamNbr= | ||
406 | smc->mib.m[MAC0].fddiMACUpstreamNbr ; | ||
407 | } | ||
408 | smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ; | ||
409 | smc->mib.m[MAC0].fddiMACUNDA_Flag = FALSE ; | ||
410 | /* | ||
411 | * Make sure the fddiMACUNDA_Flag = FALSE is | ||
412 | * included in the SRF so we don't generate | ||
413 | * a separate SRF for the deassertion of this | ||
414 | * condition | ||
415 | */ | ||
416 | update_dac(smc,0) ; | ||
417 | smt_srf_event(smc, SMT_EVENT_MAC_NEIGHBOR_CHANGE, | ||
418 | INDEX_MAC,0) ; | ||
419 | } | ||
420 | if (smc->sm.smt_tvd && | ||
421 | time - smc->sm.smt_tvd > 228*TICKS_PER_SECOND) { | ||
422 | DB_SMT("SMT : DNA expired\n",0,0) ; | ||
423 | smc->sm.smt_tvd = 0 ; | ||
424 | if (!is_equal(&smc->mib.m[MAC0].fddiMACDownstreamNbr, | ||
425 | &SMT_Unknown)){ | ||
426 | /* Do not update unknown address */ | ||
427 | smc->mib.m[MAC0].fddiMACOldDownstreamNbr= | ||
428 | smc->mib.m[MAC0].fddiMACDownstreamNbr ; | ||
429 | } | ||
430 | smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ; | ||
431 | smt_srf_event(smc, SMT_EVENT_MAC_NEIGHBOR_CHANGE, | ||
432 | INDEX_MAC,0) ; | ||
433 | } | ||
434 | |||
435 | #endif /* no SLIM_SMT */ | ||
436 | |||
437 | #ifndef SMT_REAL_TOKEN_CT | ||
438 | /* | ||
439 | * Token counter emulation section. If hardware supports the token | ||
440 | * count, the token counter will be updated in mac_update_counter. | ||
441 | */ | ||
442 | for (i = MAC0; i < NUMMACS; i++ ){ | ||
443 | if (time - smc->sm.last_tok_time[i] > 2*TICKS_PER_SECOND ){ | ||
444 | smt_emulate_token_ct( smc, i ); | ||
445 | } | ||
446 | } | ||
447 | #endif | ||
448 | |||
449 | smt_timer_start(smc,&smc->sm.smt_timer, (u_long)1000000L, | ||
450 | EV_TOKEN(EVENT_SMT,SM_TIMER)) ; | ||
451 | } | ||
452 | |||
453 | static int div_ratio(u_long upper, u_long lower) | ||
454 | { | ||
455 | if ((upper<<16L) < upper) | ||
456 | upper = 0xffff0000L ; | ||
457 | else | ||
458 | upper <<= 16L ; | ||
459 | if (!lower) | ||
460 | return 0; | ||
461 | return (int)(upper/lower) ; | ||
462 | } | ||
463 | |||
464 | #ifndef SLIM_SMT | ||
465 | |||
466 | /* | ||
467 | * receive packet handler | ||
468 | */ | ||
469 | void smt_received_pack(struct s_smc *smc, SMbuf *mb, int fs) | ||
470 | /* int fs; frame status */ | ||
471 | { | ||
472 | struct smt_header *sm ; | ||
473 | int local ; | ||
474 | |||
475 | int illegal = 0 ; | ||
476 | |||
477 | switch (m_fc(mb)) { | ||
478 | case FC_SMT_INFO : | ||
479 | case FC_SMT_LAN_LOC : | ||
480 | case FC_SMT_LOC : | ||
481 | case FC_SMT_NSA : | ||
482 | break ; | ||
483 | default : | ||
484 | smt_free_mbuf(smc,mb) ; | ||
485 | return ; | ||
486 | } | ||
487 | |||
488 | smc->mib.m[MAC0].fddiMACSMTCopied_Ct++ ; | ||
489 | sm = smtod(mb,struct smt_header *) ; | ||
490 | local = ((fs & L_INDICATOR) != 0) ; | ||
491 | hwm_conv_can(smc,(char *)sm,12) ; | ||
492 | |||
493 | /* check destination address */ | ||
494 | if (is_individual(&sm->smt_dest) && !is_my_addr(smc,&sm->smt_dest)) { | ||
495 | smt_free_mbuf(smc,mb) ; | ||
496 | return ; | ||
497 | } | ||
498 | #if 0 /* for DUP recognition, do NOT filter them */ | ||
499 | /* ignore loop back packets */ | ||
500 | if (is_my_addr(smc,&sm->smt_source) && !local) { | ||
501 | smt_free_mbuf(smc,mb) ; | ||
502 | return ; | ||
503 | } | ||
504 | #endif | ||
505 | |||
506 | smt_swap_para(sm,(int) mb->sm_len,1) ; | ||
507 | DB_SMT("SMT : received packet [%s] at 0x%x\n", | ||
508 | smt_type_name[m_fc(mb) & 0xf],sm) ; | ||
509 | DB_SMT("SMT : version %d, class %s\n",sm->smt_version, | ||
510 | smt_class_name[(sm->smt_class>LAST_CLASS)?0 : sm->smt_class]) ; | ||
511 | |||
512 | #ifdef SBA | ||
513 | /* | ||
514 | * check if NSA frame | ||
515 | */ | ||
516 | if (m_fc(mb) == FC_SMT_NSA && sm->smt_class == SMT_NIF && | ||
517 | (sm->smt_type == SMT_ANNOUNCE || sm->smt_type == SMT_REQUEST)) { | ||
518 | smc->sba.sm = sm ; | ||
519 | sba(smc,NIF) ; | ||
520 | } | ||
521 | #endif | ||
522 | |||
523 | /* | ||
524 | * ignore any packet with NSA and A-indicator set | ||
525 | */ | ||
526 | if ( (fs & A_INDICATOR) && m_fc(mb) == FC_SMT_NSA) { | ||
527 | DB_SMT("SMT : ignoring NSA with A-indicator set from %s\n", | ||
528 | addr_to_string(&sm->smt_source),0) ; | ||
529 | smt_free_mbuf(smc,mb) ; | ||
530 | return ; | ||
531 | } | ||
532 | |||
533 | /* | ||
534 | * ignore frames with illegal length | ||
535 | */ | ||
536 | if (((sm->smt_class == SMT_ECF) && (sm->smt_len > SMT_MAX_ECHO_LEN)) || | ||
537 | ((sm->smt_class != SMT_ECF) && (sm->smt_len > SMT_MAX_INFO_LEN))) { | ||
538 | smt_free_mbuf(smc,mb) ; | ||
539 | return ; | ||
540 | } | ||
541 | |||
542 | /* | ||
543 | * check SMT version | ||
544 | */ | ||
545 | switch (sm->smt_class) { | ||
546 | case SMT_NIF : | ||
547 | case SMT_SIF_CONFIG : | ||
548 | case SMT_SIF_OPER : | ||
549 | case SMT_ECF : | ||
550 | if (sm->smt_version != SMT_VID) | ||
551 | illegal = 1; | ||
552 | break ; | ||
553 | default : | ||
554 | if (sm->smt_version != SMT_VID_2) | ||
555 | illegal = 1; | ||
556 | break ; | ||
557 | } | ||
558 | if (illegal) { | ||
559 | DB_SMT("SMT : version = %d, dest = %s\n", | ||
560 | sm->smt_version,addr_to_string(&sm->smt_source)) ; | ||
561 | smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_VERSION,local) ; | ||
562 | smt_free_mbuf(smc,mb) ; | ||
563 | return ; | ||
564 | } | ||
565 | if ((sm->smt_len > mb->sm_len - sizeof(struct smt_header)) || | ||
566 | ((sm->smt_len & 3) && (sm->smt_class != SMT_ECF))) { | ||
567 | DB_SMT("SMT: info length error, len = %d\n",sm->smt_len,0) ; | ||
568 | smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_LENGTH,local) ; | ||
569 | smt_free_mbuf(smc,mb) ; | ||
570 | return ; | ||
571 | } | ||
572 | switch (sm->smt_class) { | ||
573 | case SMT_NIF : | ||
574 | if (smt_check_para(smc,sm,plist_nif)) { | ||
575 | DB_SMT("SMT: NIF with para problem, ignoring\n",0,0) ; | ||
576 | break ; | ||
577 | } | ||
578 | switch (sm->smt_type) { | ||
579 | case SMT_ANNOUNCE : | ||
580 | case SMT_REQUEST : | ||
581 | if (!(fs & C_INDICATOR) && m_fc(mb) == FC_SMT_NSA | ||
582 | && is_broadcast(&sm->smt_dest)) { | ||
583 | struct smt_p_state *st ; | ||
584 | |||
585 | /* set my UNA */ | ||
586 | if (!is_equal( | ||
587 | &smc->mib.m[MAC0].fddiMACUpstreamNbr, | ||
588 | &sm->smt_source)) { | ||
589 | DB_SMT("SMT : updated my UNA = %s\n", | ||
590 | addr_to_string(&sm->smt_source),0) ; | ||
591 | if (!is_equal(&smc->mib.m[MAC0]. | ||
592 | fddiMACUpstreamNbr,&SMT_Unknown)){ | ||
593 | /* Do not update unknown address */ | ||
594 | smc->mib.m[MAC0].fddiMACOldUpstreamNbr= | ||
595 | smc->mib.m[MAC0].fddiMACUpstreamNbr ; | ||
596 | } | ||
597 | |||
598 | smc->mib.m[MAC0].fddiMACUpstreamNbr = | ||
599 | sm->smt_source ; | ||
600 | smt_srf_event(smc, | ||
601 | SMT_EVENT_MAC_NEIGHBOR_CHANGE, | ||
602 | INDEX_MAC,0) ; | ||
603 | smt_echo_test(smc,0) ; | ||
604 | } | ||
605 | smc->sm.smt_tvu = smt_get_time() ; | ||
606 | st = (struct smt_p_state *) | ||
607 | sm_to_para(smc,sm,SMT_P_STATE) ; | ||
608 | if (st) { | ||
609 | smc->mib.m[MAC0].fddiMACUNDA_Flag = | ||
610 | (st->st_dupl_addr & SMT_ST_MY_DUPA) ? | ||
611 | TRUE : FALSE ; | ||
612 | update_dac(smc,1) ; | ||
613 | } | ||
614 | } | ||
615 | if ((sm->smt_type == SMT_REQUEST) && | ||
616 | is_individual(&sm->smt_source) && | ||
617 | ((!(fs & A_INDICATOR) && m_fc(mb) == FC_SMT_NSA) || | ||
618 | (m_fc(mb) != FC_SMT_NSA))) { | ||
619 | DB_SMT("SMT : replying to NIF request %s\n", | ||
620 | addr_to_string(&sm->smt_source),0) ; | ||
621 | smt_send_nif(smc,&sm->smt_source, | ||
622 | FC_SMT_INFO, | ||
623 | sm->smt_tid, | ||
624 | SMT_REPLY,local) ; | ||
625 | } | ||
626 | break ; | ||
627 | case SMT_REPLY : | ||
628 | DB_SMT("SMT : received NIF response from %s\n", | ||
629 | addr_to_string(&sm->smt_source),0) ; | ||
630 | if (fs & A_INDICATOR) { | ||
631 | smc->sm.pend[SMT_TID_NIF] = 0 ; | ||
632 | DB_SMT("SMT : duplicate address\n",0,0) ; | ||
633 | smc->mib.m[MAC0].fddiMACDupAddressTest = | ||
634 | DA_FAILED ; | ||
635 | smc->r.dup_addr_test = DA_FAILED ; | ||
636 | queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ; | ||
637 | smc->mib.m[MAC0].fddiMACDA_Flag = TRUE ; | ||
638 | update_dac(smc,1) ; | ||
639 | break ; | ||
640 | } | ||
641 | if (sm->smt_tid == smc->sm.pend[SMT_TID_NIF]) { | ||
642 | smc->sm.pend[SMT_TID_NIF] = 0 ; | ||
643 | /* set my DNA */ | ||
644 | if (!is_equal( | ||
645 | &smc->mib.m[MAC0].fddiMACDownstreamNbr, | ||
646 | &sm->smt_source)) { | ||
647 | DB_SMT("SMT : updated my DNA\n",0,0) ; | ||
648 | if (!is_equal(&smc->mib.m[MAC0]. | ||
649 | fddiMACDownstreamNbr, &SMT_Unknown)){ | ||
650 | /* Do not update unknown address */ | ||
651 | smc->mib.m[MAC0].fddiMACOldDownstreamNbr = | ||
652 | smc->mib.m[MAC0].fddiMACDownstreamNbr ; | ||
653 | } | ||
654 | |||
655 | smc->mib.m[MAC0].fddiMACDownstreamNbr = | ||
656 | sm->smt_source ; | ||
657 | smt_srf_event(smc, | ||
658 | SMT_EVENT_MAC_NEIGHBOR_CHANGE, | ||
659 | INDEX_MAC,0) ; | ||
660 | smt_echo_test(smc,1) ; | ||
661 | } | ||
662 | smc->mib.m[MAC0].fddiMACDA_Flag = FALSE ; | ||
663 | update_dac(smc,1) ; | ||
664 | smc->sm.smt_tvd = smt_get_time() ; | ||
665 | smc->mib.m[MAC0].fddiMACDupAddressTest = | ||
666 | DA_PASSED ; | ||
667 | if (smc->r.dup_addr_test != DA_PASSED) { | ||
668 | smc->r.dup_addr_test = DA_PASSED ; | ||
669 | queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ; | ||
670 | } | ||
671 | } | ||
672 | else if (sm->smt_tid == | ||
673 | smc->sm.pend[SMT_TID_NIF_TEST]) { | ||
674 | DB_SMT("SMT : NIF test TID ok\n",0,0) ; | ||
675 | } | ||
676 | else { | ||
677 | DB_SMT("SMT : expected TID %lx, got %lx\n", | ||
678 | smc->sm.pend[SMT_TID_NIF],sm->smt_tid) ; | ||
679 | } | ||
680 | break ; | ||
681 | default : | ||
682 | illegal = 2 ; | ||
683 | break ; | ||
684 | } | ||
685 | break ; | ||
686 | case SMT_SIF_CONFIG : /* station information */ | ||
687 | if (sm->smt_type != SMT_REQUEST) | ||
688 | break ; | ||
689 | DB_SMT("SMT : replying to SIF Config request from %s\n", | ||
690 | addr_to_string(&sm->smt_source),0) ; | ||
691 | smt_send_sif_config(smc,&sm->smt_source,sm->smt_tid,local) ; | ||
692 | break ; | ||
693 | case SMT_SIF_OPER : /* station information */ | ||
694 | if (sm->smt_type != SMT_REQUEST) | ||
695 | break ; | ||
696 | DB_SMT("SMT : replying to SIF Operation request from %s\n", | ||
697 | addr_to_string(&sm->smt_source),0) ; | ||
698 | smt_send_sif_operation(smc,&sm->smt_source,sm->smt_tid,local) ; | ||
699 | break ; | ||
700 | case SMT_ECF : /* echo frame */ | ||
701 | switch (sm->smt_type) { | ||
702 | case SMT_REPLY : | ||
703 | smc->mib.priv.fddiPRIVECF_Reply_Rx++ ; | ||
704 | DB_SMT("SMT: received ECF reply from %s\n", | ||
705 | addr_to_string(&sm->smt_source),0) ; | ||
706 | if (sm_to_para(smc,sm,SMT_P_ECHODATA) == NULL) { | ||
707 | DB_SMT("SMT: ECHODATA missing\n",0,0) ; | ||
708 | break ; | ||
709 | } | ||
710 | if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF]) { | ||
711 | DB_SMT("SMT : ECF test TID ok\n",0,0) ; | ||
712 | } | ||
713 | else if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF_UNA]) { | ||
714 | DB_SMT("SMT : ECF test UNA ok\n",0,0) ; | ||
715 | } | ||
716 | else if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF_DNA]) { | ||
717 | DB_SMT("SMT : ECF test DNA ok\n",0,0) ; | ||
718 | } | ||
719 | else { | ||
720 | DB_SMT("SMT : expected TID %lx, got %lx\n", | ||
721 | smc->sm.pend[SMT_TID_ECF], | ||
722 | sm->smt_tid) ; | ||
723 | } | ||
724 | break ; | ||
725 | case SMT_REQUEST : | ||
726 | smc->mib.priv.fddiPRIVECF_Req_Rx++ ; | ||
727 | { | ||
728 | if (sm->smt_len && !sm_to_para(smc,sm,SMT_P_ECHODATA)) { | ||
729 | DB_SMT("SMT: ECF with para problem,sending RDF\n",0,0) ; | ||
730 | smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_LENGTH, | ||
731 | local) ; | ||
732 | break ; | ||
733 | } | ||
734 | DB_SMT("SMT - sending ECF reply to %s\n", | ||
735 | addr_to_string(&sm->smt_source),0) ; | ||
736 | |||
737 | /* set destination addr. & reply */ | ||
738 | sm->smt_dest = sm->smt_source ; | ||
739 | sm->smt_type = SMT_REPLY ; | ||
740 | dump_smt(smc,sm,"ECF REPLY") ; | ||
741 | smc->mib.priv.fddiPRIVECF_Reply_Tx++ ; | ||
742 | smt_send_frame(smc,mb,FC_SMT_INFO,local) ; | ||
743 | return ; /* DON'T free mbuf */ | ||
744 | } | ||
745 | default : | ||
746 | illegal = 1 ; | ||
747 | break ; | ||
748 | } | ||
749 | break ; | ||
750 | #ifndef BOOT | ||
751 | case SMT_RAF : /* resource allocation */ | ||
752 | #ifdef ESS | ||
753 | DB_ESSN(2,"ESS: RAF frame received\n",0,0) ; | ||
754 | fs = ess_raf_received_pack(smc,mb,sm,fs) ; | ||
755 | #endif | ||
756 | |||
757 | #ifdef SBA | ||
758 | DB_SBAN(2,"SBA: RAF frame received\n",0,0) ; | ||
759 | sba_raf_received_pack(smc,sm,fs) ; | ||
760 | #endif | ||
761 | break ; | ||
762 | case SMT_RDF : /* request denied */ | ||
763 | smc->mib.priv.fddiPRIVRDF_Rx++ ; | ||
764 | break ; | ||
765 | case SMT_ESF : /* extended service - not supported */ | ||
766 | if (sm->smt_type == SMT_REQUEST) { | ||
767 | DB_SMT("SMT - received ESF, sending RDF\n",0,0) ; | ||
768 | smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_CLASS,local) ; | ||
769 | } | ||
770 | break ; | ||
771 | case SMT_PMF_GET : | ||
772 | case SMT_PMF_SET : | ||
773 | if (sm->smt_type != SMT_REQUEST) | ||
774 | break ; | ||
775 | /* update statistics */ | ||
776 | if (sm->smt_class == SMT_PMF_GET) | ||
777 | smc->mib.priv.fddiPRIVPMF_Get_Rx++ ; | ||
778 | else | ||
779 | smc->mib.priv.fddiPRIVPMF_Set_Rx++ ; | ||
780 | /* | ||
781 | * ignore PMF SET with I/G set | ||
782 | */ | ||
783 | if ((sm->smt_class == SMT_PMF_SET) && | ||
784 | !is_individual(&sm->smt_dest)) { | ||
785 | DB_SMT("SMT: ignoring PMF-SET with I/G set\n",0,0) ; | ||
786 | break ; | ||
787 | } | ||
788 | smt_pmf_received_pack(smc,mb, local) ; | ||
789 | break ; | ||
790 | case SMT_SRF : | ||
791 | dump_smt(smc,sm,"SRF received") ; | ||
792 | break ; | ||
793 | default : | ||
794 | if (sm->smt_type != SMT_REQUEST) | ||
795 | break ; | ||
796 | /* | ||
797 | * For frames with unknown class: | ||
798 | * we need to send a RDF frame according to 8.1.3.1.1, | ||
799 | * only if it is a REQUEST. | ||
800 | */ | ||
801 | DB_SMT("SMT : class = %d, send RDF to %s\n", | ||
802 | sm->smt_class, addr_to_string(&sm->smt_source)) ; | ||
803 | |||
804 | smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_CLASS,local) ; | ||
805 | break ; | ||
806 | #endif | ||
807 | } | ||
808 | if (illegal) { | ||
809 | DB_SMT("SMT: discarding invalid frame, reason = %d\n", | ||
810 | illegal,0) ; | ||
811 | } | ||
812 | smt_free_mbuf(smc,mb) ; | ||
813 | } | ||
814 | |||
815 | static void update_dac(struct s_smc *smc, int report) | ||
816 | { | ||
817 | int cond ; | ||
818 | |||
819 | cond = ( smc->mib.m[MAC0].fddiMACUNDA_Flag | | ||
820 | smc->mib.m[MAC0].fddiMACDA_Flag) != 0 ; | ||
821 | if (report && (cond != smc->mib.m[MAC0].fddiMACDuplicateAddressCond)) | ||
822 | smt_srf_event(smc, SMT_COND_MAC_DUP_ADDR,INDEX_MAC,cond) ; | ||
823 | else | ||
824 | smc->mib.m[MAC0].fddiMACDuplicateAddressCond = cond ; | ||
825 | } | ||
826 | |||
827 | /* | ||
828 | * send SMT frame | ||
829 | * set source address | ||
830 | * set station ID | ||
831 | * send frame | ||
832 | */ | ||
833 | void smt_send_frame(struct s_smc *smc, SMbuf *mb, int fc, int local) | ||
834 | /* SMbuf *mb; buffer to send */ | ||
835 | /* int fc; FC value */ | ||
836 | { | ||
837 | struct smt_header *sm ; | ||
838 | |||
839 | if (!smc->r.sm_ma_avail && !local) { | ||
840 | smt_free_mbuf(smc,mb) ; | ||
841 | return ; | ||
842 | } | ||
843 | sm = smtod(mb,struct smt_header *) ; | ||
844 | sm->smt_source = smc->mib.m[MAC0].fddiMACSMTAddress ; | ||
845 | sm->smt_sid = smc->mib.fddiSMTStationId ; | ||
846 | |||
847 | smt_swap_para(sm,(int) mb->sm_len,0) ; /* swap para & header */ | ||
848 | hwm_conv_can(smc,(char *)sm,12) ; /* convert SA and DA */ | ||
849 | smc->mib.m[MAC0].fddiMACSMTTransmit_Ct++ ; | ||
850 | smt_send_mbuf(smc,mb,local ? FC_SMT_LOC : fc) ; | ||
851 | } | ||
852 | |||
853 | /* | ||
854 | * generate and send RDF | ||
855 | */ | ||
856 | static void smt_send_rdf(struct s_smc *smc, SMbuf *rej, int fc, int reason, | ||
857 | int local) | ||
858 | /* SMbuf *rej; mbuf of offending frame */ | ||
859 | /* int fc; FC of denied frame */ | ||
860 | /* int reason; reason code */ | ||
861 | { | ||
862 | SMbuf *mb ; | ||
863 | struct smt_header *sm ; /* header of offending frame */ | ||
864 | struct smt_rdf *rdf ; | ||
865 | int len ; | ||
866 | int frame_len ; | ||
867 | |||
868 | sm = smtod(rej,struct smt_header *) ; | ||
869 | if (sm->smt_type != SMT_REQUEST) | ||
870 | return ; | ||
871 | |||
872 | DB_SMT("SMT: sending RDF to %s,reason = 0x%x\n", | ||
873 | addr_to_string(&sm->smt_source),reason) ; | ||
874 | |||
875 | |||
876 | /* | ||
877 | * note: get framelength from MAC length, NOT from SMT header | ||
878 | * smt header length is included in sm_len | ||
879 | */ | ||
880 | frame_len = rej->sm_len ; | ||
881 | |||
882 | if (!(mb=smt_build_frame(smc,SMT_RDF,SMT_REPLY,sizeof(struct smt_rdf)))) | ||
883 | return ; | ||
884 | rdf = smtod(mb,struct smt_rdf *) ; | ||
885 | rdf->smt.smt_tid = sm->smt_tid ; /* use TID from sm */ | ||
886 | rdf->smt.smt_dest = sm->smt_source ; /* set dest = source */ | ||
887 | |||
888 | /* set P12 */ | ||
889 | rdf->reason.para.p_type = SMT_P_REASON ; | ||
890 | rdf->reason.para.p_len = sizeof(struct smt_p_reason) - PARA_LEN ; | ||
891 | rdf->reason.rdf_reason = reason ; | ||
892 | |||
893 | /* set P14 */ | ||
894 | rdf->version.para.p_type = SMT_P_VERSION ; | ||
895 | rdf->version.para.p_len = sizeof(struct smt_p_version) - PARA_LEN ; | ||
896 | rdf->version.v_pad = 0 ; | ||
897 | rdf->version.v_n = 1 ; | ||
898 | rdf->version.v_index = 1 ; | ||
899 | rdf->version.v_version[0] = SMT_VID_2 ; | ||
900 | rdf->version.v_pad2 = 0 ; | ||
901 | |||
902 | /* set P13 */ | ||
903 | if ((unsigned) frame_len <= SMT_MAX_INFO_LEN - sizeof(*rdf) + | ||
904 | 2*sizeof(struct smt_header)) | ||
905 | len = frame_len ; | ||
906 | else | ||
907 | len = SMT_MAX_INFO_LEN - sizeof(*rdf) + | ||
908 | 2*sizeof(struct smt_header) ; | ||
909 | /* make length multiple of 4 */ | ||
910 | len &= ~3 ; | ||
911 | rdf->refused.para.p_type = SMT_P_REFUSED ; | ||
912 | /* length of para is smt_frame + ref_fc */ | ||
913 | rdf->refused.para.p_len = len + 4 ; | ||
914 | rdf->refused.ref_fc = fc ; | ||
915 | |||
916 | /* swap it back */ | ||
917 | smt_swap_para(sm,frame_len,0) ; | ||
918 | |||
919 | memcpy((char *) &rdf->refused.ref_header,(char *) sm,len) ; | ||
920 | |||
921 | len -= sizeof(struct smt_header) ; | ||
922 | mb->sm_len += len ; | ||
923 | rdf->smt.smt_len += len ; | ||
924 | |||
925 | dump_smt(smc,(struct smt_header *)rdf,"RDF") ; | ||
926 | smc->mib.priv.fddiPRIVRDF_Tx++ ; | ||
927 | smt_send_frame(smc,mb,FC_SMT_INFO,local) ; | ||
928 | } | ||
929 | |||
930 | /* | ||
931 | * generate and send NIF | ||
932 | */ | ||
933 | static void smt_send_nif(struct s_smc *smc, const struct fddi_addr *dest, | ||
934 | int fc, u_long tid, int type, int local) | ||
935 | /* struct fddi_addr *dest; dest address */ | ||
936 | /* int fc; frame control */ | ||
937 | /* u_long tid; transaction id */ | ||
938 | /* int type; frame type */ | ||
939 | { | ||
940 | struct smt_nif *nif ; | ||
941 | SMbuf *mb ; | ||
942 | |||
943 | if (!(mb = smt_build_frame(smc,SMT_NIF,type,sizeof(struct smt_nif)))) | ||
944 | return ; | ||
945 | nif = smtod(mb, struct smt_nif *) ; | ||
946 | smt_fill_una(smc,&nif->una) ; /* set UNA */ | ||
947 | smt_fill_sde(smc,&nif->sde) ; /* set station descriptor */ | ||
948 | smt_fill_state(smc,&nif->state) ; /* set state information */ | ||
949 | #ifdef SMT6_10 | ||
950 | smt_fill_fsc(smc,&nif->fsc) ; /* set frame status cap. */ | ||
951 | #endif | ||
952 | nif->smt.smt_dest = *dest ; /* destination address */ | ||
953 | nif->smt.smt_tid = tid ; /* transaction ID */ | ||
954 | dump_smt(smc,(struct smt_header *)nif,"NIF") ; | ||
955 | smt_send_frame(smc,mb,fc,local) ; | ||
956 | } | ||
957 | |||
958 | #ifdef DEBUG | ||
959 | /* | ||
960 | * send NIF request (test purpose) | ||
961 | */ | ||
962 | static void smt_send_nif_request(struct s_smc *smc, struct fddi_addr *dest) | ||
963 | { | ||
964 | smc->sm.pend[SMT_TID_NIF_TEST] = smt_get_tid(smc) ; | ||
965 | smt_send_nif(smc,dest, FC_SMT_INFO, smc->sm.pend[SMT_TID_NIF_TEST], | ||
966 | SMT_REQUEST,0) ; | ||
967 | } | ||
968 | |||
969 | /* | ||
970 | * send ECF request (test purpose) | ||
971 | */ | ||
972 | static void smt_send_ecf_request(struct s_smc *smc, struct fddi_addr *dest, | ||
973 | int len) | ||
974 | { | ||
975 | smc->sm.pend[SMT_TID_ECF] = smt_get_tid(smc) ; | ||
976 | smt_send_ecf(smc,dest, FC_SMT_INFO, smc->sm.pend[SMT_TID_ECF], | ||
977 | SMT_REQUEST,len) ; | ||
978 | } | ||
979 | #endif | ||
980 | |||
981 | /* | ||
982 | * echo test | ||
983 | */ | ||
984 | static void smt_echo_test(struct s_smc *smc, int dna) | ||
985 | { | ||
986 | u_long tid ; | ||
987 | |||
988 | smc->sm.pend[dna ? SMT_TID_ECF_DNA : SMT_TID_ECF_UNA] = | ||
989 | tid = smt_get_tid(smc) ; | ||
990 | smt_send_ecf(smc, dna ? | ||
991 | &smc->mib.m[MAC0].fddiMACDownstreamNbr : | ||
992 | &smc->mib.m[MAC0].fddiMACUpstreamNbr, | ||
993 | FC_SMT_INFO,tid, SMT_REQUEST, (SMT_TEST_ECHO_LEN & ~3)-8) ; | ||
994 | } | ||
995 | |||
996 | /* | ||
997 | * generate and send ECF | ||
998 | */ | ||
999 | static void smt_send_ecf(struct s_smc *smc, struct fddi_addr *dest, int fc, | ||
1000 | u_long tid, int type, int len) | ||
1001 | /* struct fddi_addr *dest; dest address */ | ||
1002 | /* int fc; frame control */ | ||
1003 | /* u_long tid; transaction id */ | ||
1004 | /* int type; frame type */ | ||
1005 | /* int len; frame length */ | ||
1006 | { | ||
1007 | struct smt_ecf *ecf ; | ||
1008 | SMbuf *mb ; | ||
1009 | |||
1010 | if (!(mb = smt_build_frame(smc,SMT_ECF,type,SMT_ECF_LEN + len))) | ||
1011 | return ; | ||
1012 | ecf = smtod(mb, struct smt_ecf *) ; | ||
1013 | |||
1014 | smt_fill_echo(smc,&ecf->ec_echo,tid,len) ; /* set ECHO */ | ||
1015 | ecf->smt.smt_dest = *dest ; /* destination address */ | ||
1016 | ecf->smt.smt_tid = tid ; /* transaction ID */ | ||
1017 | smc->mib.priv.fddiPRIVECF_Req_Tx++ ; | ||
1018 | smt_send_frame(smc,mb,fc,0) ; | ||
1019 | } | ||
1020 | |||
1021 | /* | ||
1022 | * generate and send SIF config response | ||
1023 | */ | ||
1024 | |||
1025 | static void smt_send_sif_config(struct s_smc *smc, struct fddi_addr *dest, | ||
1026 | u_long tid, int local) | ||
1027 | /* struct fddi_addr *dest; dest address */ | ||
1028 | /* u_long tid; transaction id */ | ||
1029 | { | ||
1030 | struct smt_sif_config *sif ; | ||
1031 | SMbuf *mb ; | ||
1032 | int len ; | ||
1033 | if (!(mb = smt_build_frame(smc,SMT_SIF_CONFIG,SMT_REPLY, | ||
1034 | SIZEOF_SMT_SIF_CONFIG))) | ||
1035 | return ; | ||
1036 | |||
1037 | sif = smtod(mb, struct smt_sif_config *) ; | ||
1038 | smt_fill_timestamp(smc,&sif->ts) ; /* set time stamp */ | ||
1039 | smt_fill_sde(smc,&sif->sde) ; /* set station descriptor */ | ||
1040 | smt_fill_version(smc,&sif->version) ; /* set version information */ | ||
1041 | smt_fill_state(smc,&sif->state) ; /* set state information */ | ||
1042 | smt_fill_policy(smc,&sif->policy) ; /* set station policy */ | ||
1043 | smt_fill_latency(smc,&sif->latency); /* set station latency */ | ||
1044 | smt_fill_neighbor(smc,&sif->neighbor); /* set station neighbor */ | ||
1045 | smt_fill_setcount(smc,&sif->setcount) ; /* set count */ | ||
1046 | len = smt_fill_path(smc,&sif->path); /* set station path descriptor*/ | ||
1047 | sif->smt.smt_dest = *dest ; /* destination address */ | ||
1048 | sif->smt.smt_tid = tid ; /* transaction ID */ | ||
1049 | smt_add_frame_len(mb,len) ; /* adjust length fields */ | ||
1050 | dump_smt(smc,(struct smt_header *)sif,"SIF Configuration Reply") ; | ||
1051 | smt_send_frame(smc,mb,FC_SMT_INFO,local) ; | ||
1052 | } | ||
1053 | |||
1054 | /* | ||
1055 | * generate and send SIF operation response | ||
1056 | */ | ||
1057 | |||
1058 | static void smt_send_sif_operation(struct s_smc *smc, struct fddi_addr *dest, | ||
1059 | u_long tid, int local) | ||
1060 | /* struct fddi_addr *dest; dest address */ | ||
1061 | /* u_long tid; transaction id */ | ||
1062 | { | ||
1063 | struct smt_sif_operation *sif ; | ||
1064 | SMbuf *mb ; | ||
1065 | int ports ; | ||
1066 | int i ; | ||
1067 | |||
1068 | ports = NUMPHYS ; | ||
1069 | #ifndef CONCENTRATOR | ||
1070 | if (smc->s.sas == SMT_SAS) | ||
1071 | ports = 1 ; | ||
1072 | #endif | ||
1073 | |||
1074 | if (!(mb = smt_build_frame(smc,SMT_SIF_OPER,SMT_REPLY, | ||
1075 | SIZEOF_SMT_SIF_OPERATION+ports*sizeof(struct smt_p_lem)))) | ||
1076 | return ; | ||
1077 | sif = smtod(mb, struct smt_sif_operation *) ; | ||
1078 | smt_fill_timestamp(smc,&sif->ts) ; /* set time stamp */ | ||
1079 | smt_fill_mac_status(smc,&sif->status) ; /* set mac status */ | ||
1080 | smt_fill_mac_counter(smc,&sif->mc) ; /* set mac counter field */ | ||
1081 | smt_fill_mac_fnc(smc,&sif->fnc) ; /* set frame not copied counter */ | ||
1082 | smt_fill_manufacturer(smc,&sif->man) ; /* set manufacturer field */ | ||
1083 | smt_fill_user(smc,&sif->user) ; /* set user field */ | ||
1084 | smt_fill_setcount(smc,&sif->setcount) ; /* set count */ | ||
1085 | /* | ||
1086 | * set link error mon information | ||
1087 | */ | ||
1088 | if (ports == 1) { | ||
1089 | smt_fill_lem(smc,sif->lem,PS) ; | ||
1090 | } | ||
1091 | else { | ||
1092 | for (i = 0 ; i < ports ; i++) { | ||
1093 | smt_fill_lem(smc,&sif->lem[i],i) ; | ||
1094 | } | ||
1095 | } | ||
1096 | |||
1097 | sif->smt.smt_dest = *dest ; /* destination address */ | ||
1098 | sif->smt.smt_tid = tid ; /* transaction ID */ | ||
1099 | dump_smt(smc,(struct smt_header *)sif,"SIF Operation Reply") ; | ||
1100 | smt_send_frame(smc,mb,FC_SMT_INFO,local) ; | ||
1101 | } | ||
1102 | |||
1103 | /* | ||
1104 | * get and initialize SMT frame | ||
1105 | */ | ||
1106 | SMbuf *smt_build_frame(struct s_smc *smc, int class, int type, | ||
1107 | int length) | ||
1108 | { | ||
1109 | SMbuf *mb ; | ||
1110 | struct smt_header *smt ; | ||
1111 | |||
1112 | #if 0 | ||
1113 | if (!smc->r.sm_ma_avail) { | ||
1114 | return 0; | ||
1115 | } | ||
1116 | #endif | ||
1117 | if (!(mb = smt_get_mbuf(smc))) | ||
1118 | return mb; | ||
1119 | |||
1120 | mb->sm_len = length ; | ||
1121 | smt = smtod(mb, struct smt_header *) ; | ||
1122 | smt->smt_dest = fddi_broadcast ; /* set dest = broadcast */ | ||
1123 | smt->smt_class = class ; | ||
1124 | smt->smt_type = type ; | ||
1125 | switch (class) { | ||
1126 | case SMT_NIF : | ||
1127 | case SMT_SIF_CONFIG : | ||
1128 | case SMT_SIF_OPER : | ||
1129 | case SMT_ECF : | ||
1130 | smt->smt_version = SMT_VID ; | ||
1131 | break ; | ||
1132 | default : | ||
1133 | smt->smt_version = SMT_VID_2 ; | ||
1134 | break ; | ||
1135 | } | ||
1136 | smt->smt_tid = smt_get_tid(smc) ; /* set transaction ID */ | ||
1137 | smt->smt_pad = 0 ; | ||
1138 | smt->smt_len = length - sizeof(struct smt_header) ; | ||
1139 | return mb; | ||
1140 | } | ||
1141 | |||
1142 | static void smt_add_frame_len(SMbuf *mb, int len) | ||
1143 | { | ||
1144 | struct smt_header *smt ; | ||
1145 | |||
1146 | smt = smtod(mb, struct smt_header *) ; | ||
1147 | smt->smt_len += len ; | ||
1148 | mb->sm_len += len ; | ||
1149 | } | ||
1150 | |||
1151 | |||
1152 | |||
1153 | /* | ||
1154 | * fill values in UNA parameter | ||
1155 | */ | ||
1156 | static void smt_fill_una(struct s_smc *smc, struct smt_p_una *una) | ||
1157 | { | ||
1158 | SMTSETPARA(una,SMT_P_UNA) ; | ||
1159 | una->una_pad = 0 ; | ||
1160 | una->una_node = smc->mib.m[MAC0].fddiMACUpstreamNbr ; | ||
1161 | } | ||
1162 | |||
1163 | /* | ||
1164 | * fill values in SDE parameter | ||
1165 | */ | ||
1166 | static void smt_fill_sde(struct s_smc *smc, struct smt_p_sde *sde) | ||
1167 | { | ||
1168 | SMTSETPARA(sde,SMT_P_SDE) ; | ||
1169 | sde->sde_non_master = smc->mib.fddiSMTNonMaster_Ct ; | ||
1170 | sde->sde_master = smc->mib.fddiSMTMaster_Ct ; | ||
1171 | sde->sde_mac_count = NUMMACS ; /* only 1 MAC */ | ||
1172 | #ifdef CONCENTRATOR | ||
1173 | sde->sde_type = SMT_SDE_CONCENTRATOR ; | ||
1174 | #else | ||
1175 | sde->sde_type = SMT_SDE_STATION ; | ||
1176 | #endif | ||
1177 | } | ||
1178 | |||
1179 | /* | ||
1180 | * fill in values in station state parameter | ||
1181 | */ | ||
1182 | static void smt_fill_state(struct s_smc *smc, struct smt_p_state *state) | ||
1183 | { | ||
1184 | int top ; | ||
1185 | int twist ; | ||
1186 | |||
1187 | SMTSETPARA(state,SMT_P_STATE) ; | ||
1188 | state->st_pad = 0 ; | ||
1189 | |||
1190 | /* determine topology */ | ||
1191 | top = 0 ; | ||
1192 | if (smc->mib.fddiSMTPeerWrapFlag) { | ||
1193 | top |= SMT_ST_WRAPPED ; /* state wrapped */ | ||
1194 | } | ||
1195 | #ifdef CONCENTRATOR | ||
1196 | if (cfm_status_unattached(smc)) { | ||
1197 | top |= SMT_ST_UNATTACHED ; /* unattached concentrator */ | ||
1198 | } | ||
1199 | #endif | ||
1200 | if ((twist = pcm_status_twisted(smc)) & 1) { | ||
1201 | top |= SMT_ST_TWISTED_A ; /* twisted cable */ | ||
1202 | } | ||
1203 | if (twist & 2) { | ||
1204 | top |= SMT_ST_TWISTED_B ; /* twisted cable */ | ||
1205 | } | ||
1206 | #ifdef OPT_SRF | ||
1207 | top |= SMT_ST_SRF ; | ||
1208 | #endif | ||
1209 | if (pcm_rooted_station(smc)) | ||
1210 | top |= SMT_ST_ROOTED_S ; | ||
1211 | if (smc->mib.a[0].fddiPATHSbaPayload != 0) | ||
1212 | top |= SMT_ST_SYNC_SERVICE ; | ||
1213 | state->st_topology = top ; | ||
1214 | state->st_dupl_addr = | ||
1215 | ((smc->mib.m[MAC0].fddiMACDA_Flag ? SMT_ST_MY_DUPA : 0 ) | | ||
1216 | (smc->mib.m[MAC0].fddiMACUNDA_Flag ? SMT_ST_UNA_DUPA : 0)) ; | ||
1217 | } | ||
1218 | |||
1219 | /* | ||
1220 | * fill values in timestamp parameter | ||
1221 | */ | ||
1222 | static void smt_fill_timestamp(struct s_smc *smc, struct smt_p_timestamp *ts) | ||
1223 | { | ||
1224 | |||
1225 | SMTSETPARA(ts,SMT_P_TIMESTAMP) ; | ||
1226 | smt_set_timestamp(smc,ts->ts_time) ; | ||
1227 | } | ||
1228 | |||
1229 | void smt_set_timestamp(struct s_smc *smc, u_char *p) | ||
1230 | { | ||
1231 | u_long time ; | ||
1232 | u_long utime ; | ||
1233 | |||
1234 | /* | ||
1235 | * timestamp is 64 bits long ; resolution is 80 nS | ||
1236 | * our clock resolution is 10mS | ||
1237 | * 10mS/80ns = 125000 ~ 2^17 = 131072 | ||
1238 | */ | ||
1239 | utime = smt_get_time() ; | ||
1240 | time = utime * 100 ; | ||
1241 | time /= TICKS_PER_SECOND ; | ||
1242 | p[0] = 0 ; | ||
1243 | p[1] = (u_char)((time>>(8+8+8+8-1)) & 1) ; | ||
1244 | p[2] = (u_char)(time>>(8+8+8-1)) ; | ||
1245 | p[3] = (u_char)(time>>(8+8-1)) ; | ||
1246 | p[4] = (u_char)(time>>(8-1)) ; | ||
1247 | p[5] = (u_char)(time<<1) ; | ||
1248 | p[6] = (u_char)(smc->sm.uniq_ticks>>8) ; | ||
1249 | p[7] = (u_char)smc->sm.uniq_ticks ; | ||
1250 | /* | ||
1251 | * make sure we don't wrap: restart whenever the upper digits change | ||
1252 | */ | ||
1253 | if (utime != smc->sm.uniq_time) { | ||
1254 | smc->sm.uniq_ticks = 0 ; | ||
1255 | } | ||
1256 | smc->sm.uniq_ticks++ ; | ||
1257 | smc->sm.uniq_time = utime ; | ||
1258 | } | ||
1259 | |||
1260 | /* | ||
1261 | * fill values in station policy parameter | ||
1262 | */ | ||
1263 | static void smt_fill_policy(struct s_smc *smc, struct smt_p_policy *policy) | ||
1264 | { | ||
1265 | int i ; | ||
1266 | const u_char *map ; | ||
1267 | u_short in ; | ||
1268 | u_short out ; | ||
1269 | |||
1270 | /* | ||
1271 | * MIB para 101b (fddiSMTConnectionPolicy) coding | ||
1272 | * is different from 0005 coding | ||
1273 | */ | ||
1274 | static const u_char ansi_weirdness[16] = { | ||
1275 | 0,7,5,3,8,1,6,4,9,10,2,11,12,13,14,15 | ||
1276 | } ; | ||
1277 | SMTSETPARA(policy,SMT_P_POLICY) ; | ||
1278 | |||
1279 | out = 0 ; | ||
1280 | in = smc->mib.fddiSMTConnectionPolicy ; | ||
1281 | for (i = 0, map = ansi_weirdness ; i < 16 ; i++) { | ||
1282 | if (in & 1) | ||
1283 | out |= (1<<*map) ; | ||
1284 | in >>= 1 ; | ||
1285 | map++ ; | ||
1286 | } | ||
1287 | policy->pl_config = smc->mib.fddiSMTConfigPolicy ; | ||
1288 | policy->pl_connect = out ; | ||
1289 | } | ||
1290 | |||
1291 | /* | ||
1292 | * fill values in latency equivalent parameter | ||
1293 | */ | ||
1294 | static void smt_fill_latency(struct s_smc *smc, struct smt_p_latency *latency) | ||
1295 | { | ||
1296 | SMTSETPARA(latency,SMT_P_LATENCY) ; | ||
1297 | |||
1298 | latency->lt_phyout_idx1 = phy_index(smc,0) ; | ||
1299 | latency->lt_latency1 = 10 ; /* in octets (byte clock) */ | ||
1300 | /* | ||
1301 | * note: latency has two phy entries by definition | ||
1302 | * for a SAS, the 2nd one is null | ||
1303 | */ | ||
1304 | if (smc->s.sas == SMT_DAS) { | ||
1305 | latency->lt_phyout_idx2 = phy_index(smc,1) ; | ||
1306 | latency->lt_latency2 = 10 ; /* in octets (byte clock) */ | ||
1307 | } | ||
1308 | else { | ||
1309 | latency->lt_phyout_idx2 = 0 ; | ||
1310 | latency->lt_latency2 = 0 ; | ||
1311 | } | ||
1312 | } | ||
1313 | |||
1314 | /* | ||
1315 | * fill values in MAC neighbors parameter | ||
1316 | */ | ||
1317 | static void smt_fill_neighbor(struct s_smc *smc, struct smt_p_neighbor *neighbor) | ||
1318 | { | ||
1319 | SMTSETPARA(neighbor,SMT_P_NEIGHBORS) ; | ||
1320 | |||
1321 | neighbor->nb_mib_index = INDEX_MAC ; | ||
1322 | neighbor->nb_mac_index = mac_index(smc,1) ; | ||
1323 | neighbor->nb_una = smc->mib.m[MAC0].fddiMACUpstreamNbr ; | ||
1324 | neighbor->nb_dna = smc->mib.m[MAC0].fddiMACDownstreamNbr ; | ||
1325 | } | ||
1326 | |||
1327 | /* | ||
1328 | * fill values in path descriptor | ||
1329 | */ | ||
1330 | #ifdef CONCENTRATOR | ||
1331 | #define ALLPHYS NUMPHYS | ||
1332 | #else | ||
1333 | #define ALLPHYS ((smc->s.sas == SMT_SAS) ? 1 : 2) | ||
1334 | #endif | ||
1335 | |||
1336 | static int smt_fill_path(struct s_smc *smc, struct smt_p_path *path) | ||
1337 | { | ||
1338 | SK_LOC_DECL(int,type) ; | ||
1339 | SK_LOC_DECL(int,state) ; | ||
1340 | SK_LOC_DECL(int,remote) ; | ||
1341 | SK_LOC_DECL(int,mac) ; | ||
1342 | int len ; | ||
1343 | int p ; | ||
1344 | int physp ; | ||
1345 | struct smt_phy_rec *phy ; | ||
1346 | struct smt_mac_rec *pd_mac ; | ||
1347 | |||
1348 | len = PARA_LEN + | ||
1349 | sizeof(struct smt_mac_rec) * NUMMACS + | ||
1350 | sizeof(struct smt_phy_rec) * ALLPHYS ; | ||
1351 | path->para.p_type = SMT_P_PATH ; | ||
1352 | path->para.p_len = len - PARA_LEN ; | ||
1353 | |||
1354 | /* PHYs */ | ||
1355 | for (p = 0,phy = path->pd_phy ; p < ALLPHYS ; p++, phy++) { | ||
1356 | physp = p ; | ||
1357 | #ifndef CONCENTRATOR | ||
1358 | if (smc->s.sas == SMT_SAS) | ||
1359 | physp = PS ; | ||
1360 | #endif | ||
1361 | pcm_status_state(smc,physp,&type,&state,&remote,&mac) ; | ||
1362 | #ifdef LITTLE_ENDIAN | ||
1363 | phy->phy_mib_index = smt_swap_short((u_short)p+INDEX_PORT) ; | ||
1364 | #else | ||
1365 | phy->phy_mib_index = p+INDEX_PORT ; | ||
1366 | #endif | ||
1367 | phy->phy_type = type ; | ||
1368 | phy->phy_connect_state = state ; | ||
1369 | phy->phy_remote_type = remote ; | ||
1370 | phy->phy_remote_mac = mac ; | ||
1371 | phy->phy_resource_idx = phy_con_resource_index(smc,p) ; | ||
1372 | } | ||
1373 | |||
1374 | /* MAC */ | ||
1375 | pd_mac = (struct smt_mac_rec *) phy ; | ||
1376 | pd_mac->mac_addr = smc->mib.m[MAC0].fddiMACSMTAddress ; | ||
1377 | pd_mac->mac_resource_idx = mac_con_resource_index(smc,1) ; | ||
1378 | return len; | ||
1379 | } | ||
1380 | |||
1381 | /* | ||
1382 | * fill values in mac status | ||
1383 | */ | ||
1384 | static void smt_fill_mac_status(struct s_smc *smc, struct smt_p_mac_status *st) | ||
1385 | { | ||
1386 | SMTSETPARA(st,SMT_P_MAC_STATUS) ; | ||
1387 | |||
1388 | st->st_mib_index = INDEX_MAC ; | ||
1389 | st->st_mac_index = mac_index(smc,1) ; | ||
1390 | |||
1391 | mac_update_counter(smc) ; | ||
1392 | /* | ||
1393 | * timer values are represented in SMT as 2's complement numbers | ||
1394 | * units : internal : 2's complement BCLK | ||
1395 | */ | ||
1396 | st->st_t_req = smc->mib.m[MAC0].fddiMACT_Req ; | ||
1397 | st->st_t_neg = smc->mib.m[MAC0].fddiMACT_Neg ; | ||
1398 | st->st_t_max = smc->mib.m[MAC0].fddiMACT_Max ; | ||
1399 | st->st_tvx_value = smc->mib.m[MAC0].fddiMACTvxValue ; | ||
1400 | st->st_t_min = smc->mib.m[MAC0].fddiMACT_Min ; | ||
1401 | |||
1402 | st->st_sba = smc->mib.a[PATH0].fddiPATHSbaPayload ; | ||
1403 | st->st_frame_ct = smc->mib.m[MAC0].fddiMACFrame_Ct ; | ||
1404 | st->st_error_ct = smc->mib.m[MAC0].fddiMACError_Ct ; | ||
1405 | st->st_lost_ct = smc->mib.m[MAC0].fddiMACLost_Ct ; | ||
1406 | } | ||
1407 | |||
1408 | /* | ||
1409 | * fill values in LEM status | ||
1410 | */ | ||
1411 | static void smt_fill_lem(struct s_smc *smc, struct smt_p_lem *lem, int phy) | ||
1412 | { | ||
1413 | struct fddi_mib_p *mib ; | ||
1414 | |||
1415 | mib = smc->y[phy].mib ; | ||
1416 | |||
1417 | SMTSETPARA(lem,SMT_P_LEM) ; | ||
1418 | lem->lem_mib_index = phy+INDEX_PORT ; | ||
1419 | lem->lem_phy_index = phy_index(smc,phy) ; | ||
1420 | lem->lem_pad2 = 0 ; | ||
1421 | lem->lem_cutoff = mib->fddiPORTLer_Cutoff ; | ||
1422 | lem->lem_alarm = mib->fddiPORTLer_Alarm ; | ||
1423 | /* long term bit error rate */ | ||
1424 | lem->lem_estimate = mib->fddiPORTLer_Estimate ; | ||
1425 | /* # of rejected connections */ | ||
1426 | lem->lem_reject_ct = mib->fddiPORTLem_Reject_Ct ; | ||
1427 | lem->lem_ct = mib->fddiPORTLem_Ct ; /* total number of errors */ | ||
1428 | } | ||
1429 | |||
1430 | /* | ||
1431 | * fill version parameter | ||
1432 | */ | ||
1433 | static void smt_fill_version(struct s_smc *smc, struct smt_p_version *vers) | ||
1434 | { | ||
1435 | SK_UNUSED(smc) ; | ||
1436 | SMTSETPARA(vers,SMT_P_VERSION) ; | ||
1437 | vers->v_pad = 0 ; | ||
1438 | vers->v_n = 1 ; /* one version is enough .. */ | ||
1439 | vers->v_index = 1 ; | ||
1440 | vers->v_version[0] = SMT_VID_2 ; | ||
1441 | vers->v_pad2 = 0 ; | ||
1442 | } | ||
1443 | |||
1444 | #ifdef SMT6_10 | ||
1445 | /* | ||
1446 | * fill frame status capabilities | ||
1447 | */ | ||
1448 | /* | ||
1449 | * note: this para 200B is NOT in swap table, because it's also set in | ||
1450 | * PMF add_para | ||
1451 | */ | ||
1452 | static void smt_fill_fsc(struct s_smc *smc, struct smt_p_fsc *fsc) | ||
1453 | { | ||
1454 | SK_UNUSED(smc) ; | ||
1455 | SMTSETPARA(fsc,SMT_P_FSC) ; | ||
1456 | fsc->fsc_pad0 = 0 ; | ||
1457 | fsc->fsc_mac_index = INDEX_MAC ; /* this is MIB ; MIB is NOT | ||
1458 | * mac_index ()i ! | ||
1459 | */ | ||
1460 | fsc->fsc_pad1 = 0 ; | ||
1461 | fsc->fsc_value = FSC_TYPE0 ; /* "normal" node */ | ||
1462 | #ifdef LITTLE_ENDIAN | ||
1463 | fsc->fsc_mac_index = smt_swap_short(INDEX_MAC) ; | ||
1464 | fsc->fsc_value = smt_swap_short(FSC_TYPE0) ; | ||
1465 | #endif | ||
1466 | } | ||
1467 | #endif | ||
1468 | |||
1469 | /* | ||
1470 | * fill mac counter field | ||
1471 | */ | ||
1472 | static void smt_fill_mac_counter(struct s_smc *smc, struct smt_p_mac_counter *mc) | ||
1473 | { | ||
1474 | SMTSETPARA(mc,SMT_P_MAC_COUNTER) ; | ||
1475 | mc->mc_mib_index = INDEX_MAC ; | ||
1476 | mc->mc_index = mac_index(smc,1) ; | ||
1477 | mc->mc_receive_ct = smc->mib.m[MAC0].fddiMACCopied_Ct ; | ||
1478 | mc->mc_transmit_ct = smc->mib.m[MAC0].fddiMACTransmit_Ct ; | ||
1479 | } | ||
1480 | |||
1481 | /* | ||
1482 | * fill mac frame not copied counter | ||
1483 | */ | ||
1484 | static void smt_fill_mac_fnc(struct s_smc *smc, struct smt_p_mac_fnc *fnc) | ||
1485 | { | ||
1486 | SMTSETPARA(fnc,SMT_P_MAC_FNC) ; | ||
1487 | fnc->nc_mib_index = INDEX_MAC ; | ||
1488 | fnc->nc_index = mac_index(smc,1) ; | ||
1489 | fnc->nc_counter = smc->mib.m[MAC0].fddiMACNotCopied_Ct ; | ||
1490 | } | ||
1491 | |||
1492 | |||
1493 | /* | ||
1494 | * fill manufacturer field | ||
1495 | */ | ||
1496 | static void smt_fill_manufacturer(struct s_smc *smc, | ||
1497 | struct smp_p_manufacturer *man) | ||
1498 | { | ||
1499 | SMTSETPARA(man,SMT_P_MANUFACTURER) ; | ||
1500 | memcpy((char *) man->mf_data, | ||
1501 | (char *) smc->mib.fddiSMTManufacturerData, | ||
1502 | sizeof(man->mf_data)) ; | ||
1503 | } | ||
1504 | |||
1505 | /* | ||
1506 | * fill user field | ||
1507 | */ | ||
1508 | static void smt_fill_user(struct s_smc *smc, struct smp_p_user *user) | ||
1509 | { | ||
1510 | SMTSETPARA(user,SMT_P_USER) ; | ||
1511 | memcpy((char *) user->us_data, | ||
1512 | (char *) smc->mib.fddiSMTUserData, | ||
1513 | sizeof(user->us_data)) ; | ||
1514 | } | ||
1515 | |||
1516 | /* | ||
1517 | * fill set count | ||
1518 | */ | ||
1519 | static void smt_fill_setcount(struct s_smc *smc, struct smt_p_setcount *setcount) | ||
1520 | { | ||
1521 | SK_UNUSED(smc) ; | ||
1522 | SMTSETPARA(setcount,SMT_P_SETCOUNT) ; | ||
1523 | setcount->count = smc->mib.fddiSMTSetCount.count ; | ||
1524 | memcpy((char *)setcount->timestamp, | ||
1525 | (char *)smc->mib.fddiSMTSetCount.timestamp,8) ; | ||
1526 | } | ||
1527 | |||
1528 | /* | ||
1529 | * fill echo data | ||
1530 | */ | ||
1531 | static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long seed, | ||
1532 | int len) | ||
1533 | { | ||
1534 | u_char *p ; | ||
1535 | |||
1536 | SK_UNUSED(smc) ; | ||
1537 | SMTSETPARA(echo,SMT_P_ECHODATA) ; | ||
1538 | echo->para.p_len = len ; | ||
1539 | for (p = echo->ec_data ; len ; len--) { | ||
1540 | *p++ = (u_char) seed ; | ||
1541 | seed += 13 ; | ||
1542 | } | ||
1543 | } | ||
1544 | |||
1545 | /* | ||
1546 | * clear DNA and UNA | ||
1547 | * called from CFM if configuration changes | ||
1548 | */ | ||
1549 | static void smt_clear_una_dna(struct s_smc *smc) | ||
1550 | { | ||
1551 | smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ; | ||
1552 | smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ; | ||
1553 | } | ||
1554 | |||
1555 | static void smt_clear_old_una_dna(struct s_smc *smc) | ||
1556 | { | ||
1557 | smc->mib.m[MAC0].fddiMACOldUpstreamNbr = SMT_Unknown ; | ||
1558 | smc->mib.m[MAC0].fddiMACOldDownstreamNbr = SMT_Unknown ; | ||
1559 | } | ||
1560 | |||
1561 | u_long smt_get_tid(struct s_smc *smc) | ||
1562 | { | ||
1563 | u_long tid ; | ||
1564 | while ((tid = ++(smc->sm.smt_tid) ^ SMT_TID_MAGIC) == 0) | ||
1565 | ; | ||
1566 | return tid & 0x3fffffffL; | ||
1567 | } | ||
1568 | |||
1569 | |||
1570 | /* | ||
1571 | * table of parameter lengths | ||
1572 | */ | ||
1573 | static const struct smt_pdef { | ||
1574 | int ptype ; | ||
1575 | int plen ; | ||
1576 | const char *pswap ; | ||
1577 | } smt_pdef[] = { | ||
1578 | { SMT_P_UNA, sizeof(struct smt_p_una) , | ||
1579 | SWAP_SMT_P_UNA } , | ||
1580 | { SMT_P_SDE, sizeof(struct smt_p_sde) , | ||
1581 | SWAP_SMT_P_SDE } , | ||
1582 | { SMT_P_STATE, sizeof(struct smt_p_state) , | ||
1583 | SWAP_SMT_P_STATE } , | ||
1584 | { SMT_P_TIMESTAMP,sizeof(struct smt_p_timestamp) , | ||
1585 | SWAP_SMT_P_TIMESTAMP } , | ||
1586 | { SMT_P_POLICY, sizeof(struct smt_p_policy) , | ||
1587 | SWAP_SMT_P_POLICY } , | ||
1588 | { SMT_P_LATENCY, sizeof(struct smt_p_latency) , | ||
1589 | SWAP_SMT_P_LATENCY } , | ||
1590 | { SMT_P_NEIGHBORS,sizeof(struct smt_p_neighbor) , | ||
1591 | SWAP_SMT_P_NEIGHBORS } , | ||
1592 | { SMT_P_PATH, sizeof(struct smt_p_path) , | ||
1593 | SWAP_SMT_P_PATH } , | ||
1594 | { SMT_P_MAC_STATUS,sizeof(struct smt_p_mac_status) , | ||
1595 | SWAP_SMT_P_MAC_STATUS } , | ||
1596 | { SMT_P_LEM, sizeof(struct smt_p_lem) , | ||
1597 | SWAP_SMT_P_LEM } , | ||
1598 | { SMT_P_MAC_COUNTER,sizeof(struct smt_p_mac_counter) , | ||
1599 | SWAP_SMT_P_MAC_COUNTER } , | ||
1600 | { SMT_P_MAC_FNC,sizeof(struct smt_p_mac_fnc) , | ||
1601 | SWAP_SMT_P_MAC_FNC } , | ||
1602 | { SMT_P_PRIORITY,sizeof(struct smt_p_priority) , | ||
1603 | SWAP_SMT_P_PRIORITY } , | ||
1604 | { SMT_P_EB,sizeof(struct smt_p_eb) , | ||
1605 | SWAP_SMT_P_EB } , | ||
1606 | { SMT_P_MANUFACTURER,sizeof(struct smp_p_manufacturer) , | ||
1607 | SWAP_SMT_P_MANUFACTURER } , | ||
1608 | { SMT_P_REASON, sizeof(struct smt_p_reason) , | ||
1609 | SWAP_SMT_P_REASON } , | ||
1610 | { SMT_P_REFUSED, sizeof(struct smt_p_refused) , | ||
1611 | SWAP_SMT_P_REFUSED } , | ||
1612 | { SMT_P_VERSION, sizeof(struct smt_p_version) , | ||
1613 | SWAP_SMT_P_VERSION } , | ||
1614 | #ifdef ESS | ||
1615 | { SMT_P0015, sizeof(struct smt_p_0015) , SWAP_SMT_P0015 } , | ||
1616 | { SMT_P0016, sizeof(struct smt_p_0016) , SWAP_SMT_P0016 } , | ||
1617 | { SMT_P0017, sizeof(struct smt_p_0017) , SWAP_SMT_P0017 } , | ||
1618 | { SMT_P0018, sizeof(struct smt_p_0018) , SWAP_SMT_P0018 } , | ||
1619 | { SMT_P0019, sizeof(struct smt_p_0019) , SWAP_SMT_P0019 } , | ||
1620 | { SMT_P001A, sizeof(struct smt_p_001a) , SWAP_SMT_P001A } , | ||
1621 | { SMT_P001B, sizeof(struct smt_p_001b) , SWAP_SMT_P001B } , | ||
1622 | { SMT_P001C, sizeof(struct smt_p_001c) , SWAP_SMT_P001C } , | ||
1623 | { SMT_P001D, sizeof(struct smt_p_001d) , SWAP_SMT_P001D } , | ||
1624 | #endif | ||
1625 | #if 0 | ||
1626 | { SMT_P_FSC, sizeof(struct smt_p_fsc) , | ||
1627 | SWAP_SMT_P_FSC } , | ||
1628 | #endif | ||
1629 | |||
1630 | { SMT_P_SETCOUNT,0, SWAP_SMT_P_SETCOUNT } , | ||
1631 | { SMT_P1048, 0, SWAP_SMT_P1048 } , | ||
1632 | { SMT_P208C, 0, SWAP_SMT_P208C } , | ||
1633 | { SMT_P208D, 0, SWAP_SMT_P208D } , | ||
1634 | { SMT_P208E, 0, SWAP_SMT_P208E } , | ||
1635 | { SMT_P208F, 0, SWAP_SMT_P208F } , | ||
1636 | { SMT_P2090, 0, SWAP_SMT_P2090 } , | ||
1637 | #ifdef ESS | ||
1638 | { SMT_P320B, sizeof(struct smt_p_320b) , SWAP_SMT_P320B } , | ||
1639 | { SMT_P320F, sizeof(struct smt_p_320f) , SWAP_SMT_P320F } , | ||
1640 | { SMT_P3210, sizeof(struct smt_p_3210) , SWAP_SMT_P3210 } , | ||
1641 | #endif | ||
1642 | { SMT_P4050, 0, SWAP_SMT_P4050 } , | ||
1643 | { SMT_P4051, 0, SWAP_SMT_P4051 } , | ||
1644 | { SMT_P4052, 0, SWAP_SMT_P4052 } , | ||
1645 | { SMT_P4053, 0, SWAP_SMT_P4053 } , | ||
1646 | } ; | ||
1647 | |||
1648 | #define N_SMT_PLEN ARRAY_SIZE(smt_pdef) | ||
1649 | |||
1650 | int smt_check_para(struct s_smc *smc, struct smt_header *sm, | ||
1651 | const u_short list[]) | ||
1652 | { | ||
1653 | const u_short *p = list ; | ||
1654 | while (*p) { | ||
1655 | if (!sm_to_para(smc,sm,(int) *p)) { | ||
1656 | DB_SMT("SMT: smt_check_para - missing para %x\n",*p,0); | ||
1657 | return -1; | ||
1658 | } | ||
1659 | p++ ; | ||
1660 | } | ||
1661 | return 0; | ||
1662 | } | ||
1663 | |||
1664 | void *sm_to_para(struct s_smc *smc, struct smt_header *sm, int para) | ||
1665 | { | ||
1666 | char *p ; | ||
1667 | int len ; | ||
1668 | int plen ; | ||
1669 | void *found = NULL; | ||
1670 | |||
1671 | SK_UNUSED(smc) ; | ||
1672 | |||
1673 | len = sm->smt_len ; | ||
1674 | p = (char *)(sm+1) ; /* pointer to info */ | ||
1675 | while (len > 0 ) { | ||
1676 | if (((struct smt_para *)p)->p_type == para) | ||
1677 | found = (void *) p ; | ||
1678 | plen = ((struct smt_para *)p)->p_len + PARA_LEN ; | ||
1679 | p += plen ; | ||
1680 | len -= plen ; | ||
1681 | if (len < 0) { | ||
1682 | DB_SMT("SMT : sm_to_para - length error %d\n",plen,0) ; | ||
1683 | return NULL; | ||
1684 | } | ||
1685 | if ((plen & 3) && (para != SMT_P_ECHODATA)) { | ||
1686 | DB_SMT("SMT : sm_to_para - odd length %d\n",plen,0) ; | ||
1687 | return NULL; | ||
1688 | } | ||
1689 | if (found) | ||
1690 | return found; | ||
1691 | } | ||
1692 | return NULL; | ||
1693 | } | ||
1694 | |||
1695 | #if 0 | ||
1696 | /* | ||
1697 | * send ANTC data test frame | ||
1698 | */ | ||
1699 | void fddi_send_antc(struct s_smc *smc, struct fddi_addr *dest) | ||
1700 | { | ||
1701 | SK_UNUSED(smc) ; | ||
1702 | SK_UNUSED(dest) ; | ||
1703 | #if 0 | ||
1704 | SMbuf *mb ; | ||
1705 | struct smt_header *smt ; | ||
1706 | int i ; | ||
1707 | char *p ; | ||
1708 | |||
1709 | mb = smt_get_mbuf() ; | ||
1710 | mb->sm_len = 3000+12 ; | ||
1711 | p = smtod(mb, char *) + 12 ; | ||
1712 | for (i = 0 ; i < 3000 ; i++) | ||
1713 | *p++ = 1 << (i&7) ; | ||
1714 | |||
1715 | smt = smtod(mb, struct smt_header *) ; | ||
1716 | smt->smt_dest = *dest ; | ||
1717 | smt->smt_source = smc->mib.m[MAC0].fddiMACSMTAddress ; | ||
1718 | smt_send_mbuf(smc,mb,FC_ASYNC_LLC) ; | ||
1719 | #endif | ||
1720 | } | ||
1721 | #endif | ||
1722 | |||
1723 | #ifdef DEBUG | ||
1724 | char *addr_to_string(struct fddi_addr *addr) | ||
1725 | { | ||
1726 | int i ; | ||
1727 | static char string[6*3] = "****" ; | ||
1728 | |||
1729 | for (i = 0 ; i < 6 ; i++) { | ||
1730 | string[i * 3] = hex_asc_hi(addr->a[i]); | ||
1731 | string[i * 3 + 1] = hex_asc_lo(addr->a[i]); | ||
1732 | string[i * 3 + 2] = ':'; | ||
1733 | } | ||
1734 | string[5 * 3 + 2] = 0; | ||
1735 | return string; | ||
1736 | } | ||
1737 | #endif | ||
1738 | |||
1739 | #ifdef AM29K | ||
1740 | int smt_ifconfig(int argc, char *argv[]) | ||
1741 | { | ||
1742 | if (argc >= 2 && !strcmp(argv[0],"opt_bypass") && | ||
1743 | !strcmp(argv[1],"yes")) { | ||
1744 | smc->mib.fddiSMTBypassPresent = 1 ; | ||
1745 | return 0; | ||
1746 | } | ||
1747 | return amdfddi_config(0, argc, argv); | ||
1748 | } | ||
1749 | #endif | ||
1750 | |||
1751 | /* | ||
1752 | * return static mac index | ||
1753 | */ | ||
1754 | static int mac_index(struct s_smc *smc, int mac) | ||
1755 | { | ||
1756 | SK_UNUSED(mac) ; | ||
1757 | #ifdef CONCENTRATOR | ||
1758 | SK_UNUSED(smc) ; | ||
1759 | return NUMPHYS + 1; | ||
1760 | #else | ||
1761 | return (smc->s.sas == SMT_SAS) ? 2 : 3; | ||
1762 | #endif | ||
1763 | } | ||
1764 | |||
1765 | /* | ||
1766 | * return static phy index | ||
1767 | */ | ||
1768 | static int phy_index(struct s_smc *smc, int phy) | ||
1769 | { | ||
1770 | SK_UNUSED(smc) ; | ||
1771 | return phy + 1; | ||
1772 | } | ||
1773 | |||
1774 | /* | ||
1775 | * return dynamic mac connection resource index | ||
1776 | */ | ||
1777 | static int mac_con_resource_index(struct s_smc *smc, int mac) | ||
1778 | { | ||
1779 | #ifdef CONCENTRATOR | ||
1780 | SK_UNUSED(smc) ; | ||
1781 | SK_UNUSED(mac) ; | ||
1782 | return entity_to_index(smc, cem_get_downstream(smc, ENTITY_MAC)); | ||
1783 | #else | ||
1784 | SK_UNUSED(mac) ; | ||
1785 | switch (smc->mib.fddiSMTCF_State) { | ||
1786 | case SC9_C_WRAP_A : | ||
1787 | case SC5_THRU_B : | ||
1788 | case SC11_C_WRAP_S : | ||
1789 | return 1; | ||
1790 | case SC10_C_WRAP_B : | ||
1791 | case SC4_THRU_A : | ||
1792 | return 2; | ||
1793 | } | ||
1794 | return smc->s.sas == SMT_SAS ? 2 : 3; | ||
1795 | #endif | ||
1796 | } | ||
1797 | |||
1798 | /* | ||
1799 | * return dynamic phy connection resource index | ||
1800 | */ | ||
1801 | static int phy_con_resource_index(struct s_smc *smc, int phy) | ||
1802 | { | ||
1803 | #ifdef CONCENTRATOR | ||
1804 | return entity_to_index(smc, cem_get_downstream(smc, ENTITY_PHY(phy))) ; | ||
1805 | #else | ||
1806 | switch (smc->mib.fddiSMTCF_State) { | ||
1807 | case SC9_C_WRAP_A : | ||
1808 | return phy == PA ? 3 : 2; | ||
1809 | case SC10_C_WRAP_B : | ||
1810 | return phy == PA ? 1 : 3; | ||
1811 | case SC4_THRU_A : | ||
1812 | return phy == PA ? 3 : 1; | ||
1813 | case SC5_THRU_B : | ||
1814 | return phy == PA ? 2 : 3; | ||
1815 | case SC11_C_WRAP_S : | ||
1816 | return 2; | ||
1817 | } | ||
1818 | return phy; | ||
1819 | #endif | ||
1820 | } | ||
1821 | |||
1822 | #ifdef CONCENTRATOR | ||
1823 | static int entity_to_index(struct s_smc *smc, int e) | ||
1824 | { | ||
1825 | if (e == ENTITY_MAC) | ||
1826 | return mac_index(smc, 1); | ||
1827 | else | ||
1828 | return phy_index(smc, e - ENTITY_PHY(0)); | ||
1829 | } | ||
1830 | #endif | ||
1831 | |||
1832 | #ifdef LITTLE_ENDIAN | ||
1833 | static int smt_swap_short(u_short s) | ||
1834 | { | ||
1835 | return ((s>>8)&0xff) | ((s&0xff)<<8); | ||
1836 | } | ||
1837 | |||
1838 | void smt_swap_para(struct smt_header *sm, int len, int direction) | ||
1839 | /* int direction; 0 encode 1 decode */ | ||
1840 | { | ||
1841 | struct smt_para *pa ; | ||
1842 | const struct smt_pdef *pd ; | ||
1843 | char *p ; | ||
1844 | int plen ; | ||
1845 | int type ; | ||
1846 | int i ; | ||
1847 | |||
1848 | /* printf("smt_swap_para sm %x len %d dir %d\n", | ||
1849 | sm,len,direction) ; | ||
1850 | */ | ||
1851 | smt_string_swap((char *)sm,SWAP_SMTHEADER,len) ; | ||
1852 | |||
1853 | /* swap args */ | ||
1854 | len -= sizeof(struct smt_header) ; | ||
1855 | |||
1856 | p = (char *) (sm + 1) ; | ||
1857 | while (len > 0) { | ||
1858 | pa = (struct smt_para *) p ; | ||
1859 | plen = pa->p_len ; | ||
1860 | type = pa->p_type ; | ||
1861 | pa->p_type = smt_swap_short(pa->p_type) ; | ||
1862 | pa->p_len = smt_swap_short(pa->p_len) ; | ||
1863 | if (direction) { | ||
1864 | plen = pa->p_len ; | ||
1865 | type = pa->p_type ; | ||
1866 | } | ||
1867 | /* | ||
1868 | * note: paras can have 0 length ! | ||
1869 | */ | ||
1870 | if (plen < 0) | ||
1871 | break ; | ||
1872 | plen += PARA_LEN ; | ||
1873 | for (i = N_SMT_PLEN, pd = smt_pdef; i ; i--,pd++) { | ||
1874 | if (pd->ptype == type) | ||
1875 | break ; | ||
1876 | } | ||
1877 | if (i && pd->pswap) { | ||
1878 | smt_string_swap(p+PARA_LEN,pd->pswap,len) ; | ||
1879 | } | ||
1880 | len -= plen ; | ||
1881 | p += plen ; | ||
1882 | } | ||
1883 | } | ||
1884 | |||
1885 | static void smt_string_swap(char *data, const char *format, int len) | ||
1886 | { | ||
1887 | const char *open_paren = NULL ; | ||
1888 | int x ; | ||
1889 | |||
1890 | while (len > 0 && *format) { | ||
1891 | switch (*format) { | ||
1892 | case '[' : | ||
1893 | open_paren = format ; | ||
1894 | break ; | ||
1895 | case ']' : | ||
1896 | format = open_paren ; | ||
1897 | break ; | ||
1898 | case '1' : | ||
1899 | case '2' : | ||
1900 | case '3' : | ||
1901 | case '4' : | ||
1902 | case '5' : | ||
1903 | case '6' : | ||
1904 | case '7' : | ||
1905 | case '8' : | ||
1906 | case '9' : | ||
1907 | data += *format - '0' ; | ||
1908 | len -= *format - '0' ; | ||
1909 | break ; | ||
1910 | case 'c': | ||
1911 | data++ ; | ||
1912 | len-- ; | ||
1913 | break ; | ||
1914 | case 's' : | ||
1915 | x = data[0] ; | ||
1916 | data[0] = data[1] ; | ||
1917 | data[1] = x ; | ||
1918 | data += 2 ; | ||
1919 | len -= 2 ; | ||
1920 | break ; | ||
1921 | case 'l' : | ||
1922 | x = data[0] ; | ||
1923 | data[0] = data[3] ; | ||
1924 | data[3] = x ; | ||
1925 | x = data[1] ; | ||
1926 | data[1] = data[2] ; | ||
1927 | data[2] = x ; | ||
1928 | data += 4 ; | ||
1929 | len -= 4 ; | ||
1930 | break ; | ||
1931 | } | ||
1932 | format++ ; | ||
1933 | } | ||
1934 | } | ||
1935 | #else | ||
1936 | void smt_swap_para(struct smt_header *sm, int len, int direction) | ||
1937 | /* int direction; 0 encode 1 decode */ | ||
1938 | { | ||
1939 | SK_UNUSED(sm) ; | ||
1940 | SK_UNUSED(len) ; | ||
1941 | SK_UNUSED(direction) ; | ||
1942 | } | ||
1943 | #endif | ||
1944 | |||
1945 | /* | ||
1946 | * PMF actions | ||
1947 | */ | ||
1948 | int smt_action(struct s_smc *smc, int class, int code, int index) | ||
1949 | { | ||
1950 | int event ; | ||
1951 | int port ; | ||
1952 | DB_SMT("SMT: action %d code %d\n",class,code) ; | ||
1953 | switch(class) { | ||
1954 | case SMT_STATION_ACTION : | ||
1955 | switch(code) { | ||
1956 | case SMT_STATION_ACTION_CONNECT : | ||
1957 | smc->mib.fddiSMTRemoteDisconnectFlag = FALSE ; | ||
1958 | queue_event(smc,EVENT_ECM,EC_CONNECT) ; | ||
1959 | break ; | ||
1960 | case SMT_STATION_ACTION_DISCONNECT : | ||
1961 | queue_event(smc,EVENT_ECM,EC_DISCONNECT) ; | ||
1962 | smc->mib.fddiSMTRemoteDisconnectFlag = TRUE ; | ||
1963 | RS_SET(smc,RS_DISCONNECT) ; | ||
1964 | AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long) | ||
1965 | FDDI_SMT_EVENT, (u_long) FDDI_REMOTE_DISCONNECT, | ||
1966 | smt_get_event_word(smc)); | ||
1967 | break ; | ||
1968 | case SMT_STATION_ACTION_PATHTEST : | ||
1969 | AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long) | ||
1970 | FDDI_SMT_EVENT, (u_long) FDDI_PATH_TEST, | ||
1971 | smt_get_event_word(smc)); | ||
1972 | break ; | ||
1973 | case SMT_STATION_ACTION_SELFTEST : | ||
1974 | AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long) | ||
1975 | FDDI_SMT_EVENT, (u_long) FDDI_REMOTE_SELF_TEST, | ||
1976 | smt_get_event_word(smc)); | ||
1977 | break ; | ||
1978 | case SMT_STATION_ACTION_DISABLE_A : | ||
1979 | if (smc->y[PA].pc_mode == PM_PEER) { | ||
1980 | RS_SET(smc,RS_EVENT) ; | ||
1981 | queue_event(smc,EVENT_PCM+PA,PC_DISABLE) ; | ||
1982 | } | ||
1983 | break ; | ||
1984 | case SMT_STATION_ACTION_DISABLE_B : | ||
1985 | if (smc->y[PB].pc_mode == PM_PEER) { | ||
1986 | RS_SET(smc,RS_EVENT) ; | ||
1987 | queue_event(smc,EVENT_PCM+PB,PC_DISABLE) ; | ||
1988 | } | ||
1989 | break ; | ||
1990 | case SMT_STATION_ACTION_DISABLE_M : | ||
1991 | for (port = 0 ; port < NUMPHYS ; port++) { | ||
1992 | if (smc->mib.p[port].fddiPORTMy_Type != TM) | ||
1993 | continue ; | ||
1994 | RS_SET(smc,RS_EVENT) ; | ||
1995 | queue_event(smc,EVENT_PCM+port,PC_DISABLE) ; | ||
1996 | } | ||
1997 | break ; | ||
1998 | default : | ||
1999 | return 1; | ||
2000 | } | ||
2001 | break ; | ||
2002 | case SMT_PORT_ACTION : | ||
2003 | switch(code) { | ||
2004 | case SMT_PORT_ACTION_ENABLE : | ||
2005 | event = PC_ENABLE ; | ||
2006 | break ; | ||
2007 | case SMT_PORT_ACTION_DISABLE : | ||
2008 | event = PC_DISABLE ; | ||
2009 | break ; | ||
2010 | case SMT_PORT_ACTION_MAINT : | ||
2011 | event = PC_MAINT ; | ||
2012 | break ; | ||
2013 | case SMT_PORT_ACTION_START : | ||
2014 | event = PC_START ; | ||
2015 | break ; | ||
2016 | case SMT_PORT_ACTION_STOP : | ||
2017 | event = PC_STOP ; | ||
2018 | break ; | ||
2019 | default : | ||
2020 | return 1; | ||
2021 | } | ||
2022 | queue_event(smc,EVENT_PCM+index,event) ; | ||
2023 | break ; | ||
2024 | default : | ||
2025 | return 1; | ||
2026 | } | ||
2027 | return 0; | ||
2028 | } | ||
2029 | |||
2030 | /* | ||
2031 | * canonical conversion of <len> bytes beginning form *data | ||
2032 | */ | ||
2033 | #ifdef USE_CAN_ADDR | ||
2034 | static void hwm_conv_can(struct s_smc *smc, char *data, int len) | ||
2035 | { | ||
2036 | int i ; | ||
2037 | |||
2038 | SK_UNUSED(smc) ; | ||
2039 | |||
2040 | for (i = len; i ; i--, data++) | ||
2041 | *data = bitrev8(*data); | ||
2042 | } | ||
2043 | #endif | ||
2044 | |||
2045 | #endif /* no SLIM_SMT */ | ||
2046 | |||