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/sk98lin/skrlmt.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/sk98lin/skrlmt.c')
-rw-r--r-- | drivers/net/sk98lin/skrlmt.c | 3258 |
1 files changed, 3258 insertions, 0 deletions
diff --git a/drivers/net/sk98lin/skrlmt.c b/drivers/net/sk98lin/skrlmt.c new file mode 100644 index 000000000000..9ea11ab2296a --- /dev/null +++ b/drivers/net/sk98lin/skrlmt.c | |||
@@ -0,0 +1,3258 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Name: skrlmt.c | ||
4 | * Project: GEnesis, PCI Gigabit Ethernet Adapter | ||
5 | * Version: $Revision: 1.69 $ | ||
6 | * Date: $Date: 2003/04/15 09:39:22 $ | ||
7 | * Purpose: Manage links on SK-NET Adapters, esp. redundant ones. | ||
8 | * | ||
9 | ******************************************************************************/ | ||
10 | |||
11 | /****************************************************************************** | ||
12 | * | ||
13 | * (C)Copyright 1998-2002 SysKonnect GmbH. | ||
14 | * (C)Copyright 2002-2003 Marvell. | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License as published by | ||
18 | * the Free Software Foundation; either version 2 of the License, or | ||
19 | * (at your option) any later version. | ||
20 | * | ||
21 | * The information in this file is provided "AS IS" without warranty. | ||
22 | * | ||
23 | ******************************************************************************/ | ||
24 | |||
25 | /****************************************************************************** | ||
26 | * | ||
27 | * Description: | ||
28 | * | ||
29 | * This module contains code for Link ManagemenT (LMT) of SK-NET Adapters. | ||
30 | * It is mainly intended for adapters with more than one link. | ||
31 | * For such adapters, this module realizes Redundant Link ManagemenT (RLMT). | ||
32 | * | ||
33 | * Include File Hierarchy: | ||
34 | * | ||
35 | * "skdrv1st.h" | ||
36 | * "skdrv2nd.h" | ||
37 | * | ||
38 | ******************************************************************************/ | ||
39 | |||
40 | #ifndef lint | ||
41 | static const char SysKonnectFileId[] = | ||
42 | "@(#) $Id: skrlmt.c,v 1.69 2003/04/15 09:39:22 tschilli Exp $ (C) Marvell."; | ||
43 | #endif /* !defined(lint) */ | ||
44 | |||
45 | #define __SKRLMT_C | ||
46 | |||
47 | #ifdef __cplusplus | ||
48 | extern "C" { | ||
49 | #endif /* cplusplus */ | ||
50 | |||
51 | #include "h/skdrv1st.h" | ||
52 | #include "h/skdrv2nd.h" | ||
53 | |||
54 | /* defines ********************************************************************/ | ||
55 | |||
56 | #ifndef SK_HWAC_LINK_LED | ||
57 | #define SK_HWAC_LINK_LED(a,b,c,d) | ||
58 | #endif /* !defined(SK_HWAC_LINK_LED) */ | ||
59 | |||
60 | #ifndef DEBUG | ||
61 | #define RLMT_STATIC static | ||
62 | #else /* DEBUG */ | ||
63 | #define RLMT_STATIC | ||
64 | |||
65 | #ifndef SK_LITTLE_ENDIAN | ||
66 | /* First 32 bits */ | ||
67 | #define OFFS_LO32 1 | ||
68 | |||
69 | /* Second 32 bits */ | ||
70 | #define OFFS_HI32 0 | ||
71 | #else /* SK_LITTLE_ENDIAN */ | ||
72 | /* First 32 bits */ | ||
73 | #define OFFS_LO32 0 | ||
74 | |||
75 | /* Second 32 bits */ | ||
76 | #define OFFS_HI32 1 | ||
77 | #endif /* SK_LITTLE_ENDIAN */ | ||
78 | |||
79 | #endif /* DEBUG */ | ||
80 | |||
81 | /* ----- Private timeout values ----- */ | ||
82 | |||
83 | #define SK_RLMT_MIN_TO_VAL 125000 /* 1/8 sec. */ | ||
84 | #define SK_RLMT_DEF_TO_VAL 1000000 /* 1 sec. */ | ||
85 | #define SK_RLMT_PORTDOWN_TIM_VAL 900000 /* another 0.9 sec. */ | ||
86 | #define SK_RLMT_PORTSTART_TIM_VAL 100000 /* 0.1 sec. */ | ||
87 | #define SK_RLMT_PORTUP_TIM_VAL 2500000 /* 2.5 sec. */ | ||
88 | #define SK_RLMT_SEG_TO_VAL 900000000 /* 15 min. */ | ||
89 | |||
90 | /* Assume tick counter increment is 1 - may be set OS-dependent. */ | ||
91 | #ifndef SK_TICK_INCR | ||
92 | #define SK_TICK_INCR SK_CONSTU64(1) | ||
93 | #endif /* !defined(SK_TICK_INCR) */ | ||
94 | |||
95 | /* | ||
96 | * Amount that a time stamp must be later to be recognized as "substantially | ||
97 | * later". This is about 1/128 sec, but above 1 tick counter increment. | ||
98 | */ | ||
99 | #define SK_RLMT_BC_DELTA (1 + ((SK_TICKS_PER_SEC >> 7) > SK_TICK_INCR ? \ | ||
100 | (SK_TICKS_PER_SEC >> 7) : SK_TICK_INCR)) | ||
101 | |||
102 | /* ----- Private RLMT defaults ----- */ | ||
103 | |||
104 | #define SK_RLMT_DEF_PREF_PORT 0 /* "Lower" port. */ | ||
105 | #define SK_RLMT_DEF_MODE SK_RLMT_CHECK_LINK /* Default RLMT Mode. */ | ||
106 | |||
107 | /* ----- Private RLMT checking states ----- */ | ||
108 | |||
109 | #define SK_RLMT_RCS_SEG 1 /* RLMT Check State: check seg. */ | ||
110 | #define SK_RLMT_RCS_START_SEG 2 /* RLMT Check State: start check seg. */ | ||
111 | #define SK_RLMT_RCS_SEND_SEG 4 /* RLMT Check State: send BPDU packet */ | ||
112 | #define SK_RLMT_RCS_REPORT_SEG 8 /* RLMT Check State: report seg. */ | ||
113 | |||
114 | /* ----- Private PORT checking states ----- */ | ||
115 | |||
116 | #define SK_RLMT_PCS_TX 1 /* Port Check State: check tx. */ | ||
117 | #define SK_RLMT_PCS_RX 2 /* Port Check State: check rx. */ | ||
118 | |||
119 | /* ----- Private PORT events ----- */ | ||
120 | |||
121 | /* Note: Update simulation when changing these. */ | ||
122 | #define SK_RLMT_PORTSTART_TIM 1100 /* Port start timeout. */ | ||
123 | #define SK_RLMT_PORTUP_TIM 1101 /* Port can now go up. */ | ||
124 | #define SK_RLMT_PORTDOWN_RX_TIM 1102 /* Port did not receive once ... */ | ||
125 | #define SK_RLMT_PORTDOWN 1103 /* Port went down. */ | ||
126 | #define SK_RLMT_PORTDOWN_TX_TIM 1104 /* Partner did not receive ... */ | ||
127 | |||
128 | /* ----- Private RLMT events ----- */ | ||
129 | |||
130 | /* Note: Update simulation when changing these. */ | ||
131 | #define SK_RLMT_TIM 2100 /* RLMT timeout. */ | ||
132 | #define SK_RLMT_SEG_TIM 2101 /* RLMT segmentation check timeout. */ | ||
133 | |||
134 | #define TO_SHORTEN(tim) ((tim) / 2) | ||
135 | |||
136 | /* Error numbers and messages. */ | ||
137 | #define SKERR_RLMT_E001 (SK_ERRBASE_RLMT + 0) | ||
138 | #define SKERR_RLMT_E001_MSG "No Packet." | ||
139 | #define SKERR_RLMT_E002 (SKERR_RLMT_E001 + 1) | ||
140 | #define SKERR_RLMT_E002_MSG "Short Packet." | ||
141 | #define SKERR_RLMT_E003 (SKERR_RLMT_E002 + 1) | ||
142 | #define SKERR_RLMT_E003_MSG "Unknown RLMT event." | ||
143 | #define SKERR_RLMT_E004 (SKERR_RLMT_E003 + 1) | ||
144 | #define SKERR_RLMT_E004_MSG "PortsUp incorrect." | ||
145 | #define SKERR_RLMT_E005 (SKERR_RLMT_E004 + 1) | ||
146 | #define SKERR_RLMT_E005_MSG \ | ||
147 | "Net seems to be segmented (different root bridges are reported on the ports)." | ||
148 | #define SKERR_RLMT_E006 (SKERR_RLMT_E005 + 1) | ||
149 | #define SKERR_RLMT_E006_MSG "Duplicate MAC Address detected." | ||
150 | #define SKERR_RLMT_E007 (SKERR_RLMT_E006 + 1) | ||
151 | #define SKERR_RLMT_E007_MSG "LinksUp incorrect." | ||
152 | #define SKERR_RLMT_E008 (SKERR_RLMT_E007 + 1) | ||
153 | #define SKERR_RLMT_E008_MSG "Port not started but link came up." | ||
154 | #define SKERR_RLMT_E009 (SKERR_RLMT_E008 + 1) | ||
155 | #define SKERR_RLMT_E009_MSG "Corrected illegal setting of Preferred Port." | ||
156 | #define SKERR_RLMT_E010 (SKERR_RLMT_E009 + 1) | ||
157 | #define SKERR_RLMT_E010_MSG "Ignored illegal Preferred Port." | ||
158 | |||
159 | /* LLC field values. */ | ||
160 | #define LLC_COMMAND_RESPONSE_BIT 1 | ||
161 | #define LLC_TEST_COMMAND 0xE3 | ||
162 | #define LLC_UI 0x03 | ||
163 | |||
164 | /* RLMT Packet fields. */ | ||
165 | #define SK_RLMT_DSAP 0 | ||
166 | #define SK_RLMT_SSAP 0 | ||
167 | #define SK_RLMT_CTRL (LLC_TEST_COMMAND) | ||
168 | #define SK_RLMT_INDICATOR0 0x53 /* S */ | ||
169 | #define SK_RLMT_INDICATOR1 0x4B /* K */ | ||
170 | #define SK_RLMT_INDICATOR2 0x2D /* - */ | ||
171 | #define SK_RLMT_INDICATOR3 0x52 /* R */ | ||
172 | #define SK_RLMT_INDICATOR4 0x4C /* L */ | ||
173 | #define SK_RLMT_INDICATOR5 0x4D /* M */ | ||
174 | #define SK_RLMT_INDICATOR6 0x54 /* T */ | ||
175 | #define SK_RLMT_PACKET_VERSION 0 | ||
176 | |||
177 | /* RLMT SPT Flag values. */ | ||
178 | #define SK_RLMT_SPT_FLAG_CHANGE 0x01 | ||
179 | #define SK_RLMT_SPT_FLAG_CHANGE_ACK 0x80 | ||
180 | |||
181 | /* RLMT SPT Packet fields. */ | ||
182 | #define SK_RLMT_SPT_DSAP 0x42 | ||
183 | #define SK_RLMT_SPT_SSAP 0x42 | ||
184 | #define SK_RLMT_SPT_CTRL (LLC_UI) | ||
185 | #define SK_RLMT_SPT_PROTOCOL_ID0 0x00 | ||
186 | #define SK_RLMT_SPT_PROTOCOL_ID1 0x00 | ||
187 | #define SK_RLMT_SPT_PROTOCOL_VERSION_ID 0x00 | ||
188 | #define SK_RLMT_SPT_BPDU_TYPE 0x00 | ||
189 | #define SK_RLMT_SPT_FLAGS 0x00 /* ?? */ | ||
190 | #define SK_RLMT_SPT_ROOT_ID0 0xFF /* Lowest possible priority. */ | ||
191 | #define SK_RLMT_SPT_ROOT_ID1 0xFF /* Lowest possible priority. */ | ||
192 | |||
193 | /* Remaining 6 bytes will be the current port address. */ | ||
194 | #define SK_RLMT_SPT_ROOT_PATH_COST0 0x00 | ||
195 | #define SK_RLMT_SPT_ROOT_PATH_COST1 0x00 | ||
196 | #define SK_RLMT_SPT_ROOT_PATH_COST2 0x00 | ||
197 | #define SK_RLMT_SPT_ROOT_PATH_COST3 0x00 | ||
198 | #define SK_RLMT_SPT_BRIDGE_ID0 0xFF /* Lowest possible priority. */ | ||
199 | #define SK_RLMT_SPT_BRIDGE_ID1 0xFF /* Lowest possible priority. */ | ||
200 | |||
201 | /* Remaining 6 bytes will be the current port address. */ | ||
202 | #define SK_RLMT_SPT_PORT_ID0 0xFF /* Lowest possible priority. */ | ||
203 | #define SK_RLMT_SPT_PORT_ID1 0xFF /* Lowest possible priority. */ | ||
204 | #define SK_RLMT_SPT_MSG_AGE0 0x00 | ||
205 | #define SK_RLMT_SPT_MSG_AGE1 0x00 | ||
206 | #define SK_RLMT_SPT_MAX_AGE0 0x00 | ||
207 | #define SK_RLMT_SPT_MAX_AGE1 0xFF | ||
208 | #define SK_RLMT_SPT_HELLO_TIME0 0x00 | ||
209 | #define SK_RLMT_SPT_HELLO_TIME1 0xFF | ||
210 | #define SK_RLMT_SPT_FWD_DELAY0 0x00 | ||
211 | #define SK_RLMT_SPT_FWD_DELAY1 0x40 | ||
212 | |||
213 | /* Size defines. */ | ||
214 | #define SK_RLMT_MIN_PACKET_SIZE 34 | ||
215 | #define SK_RLMT_MAX_PACKET_SIZE (SK_RLMT_MAX_TX_BUF_SIZE) | ||
216 | #define SK_PACKET_DATA_LEN (SK_RLMT_MAX_PACKET_SIZE - \ | ||
217 | SK_RLMT_MIN_PACKET_SIZE) | ||
218 | |||
219 | /* ----- RLMT packet types ----- */ | ||
220 | #define SK_PACKET_ANNOUNCE 1 /* Port announcement. */ | ||
221 | #define SK_PACKET_ALIVE 2 /* Alive packet to port. */ | ||
222 | #define SK_PACKET_ADDR_CHANGED 3 /* Port address changed. */ | ||
223 | #define SK_PACKET_CHECK_TX 4 /* Check your tx line. */ | ||
224 | |||
225 | #ifdef SK_LITTLE_ENDIAN | ||
226 | #define SK_U16_TO_NETWORK_ORDER(Val,Addr) { \ | ||
227 | SK_U8 *_Addr = (SK_U8*)(Addr); \ | ||
228 | SK_U16 _Val = (SK_U16)(Val); \ | ||
229 | *_Addr++ = (SK_U8)(_Val >> 8); \ | ||
230 | *_Addr = (SK_U8)(_Val & 0xFF); \ | ||
231 | } | ||
232 | #endif /* SK_LITTLE_ENDIAN */ | ||
233 | |||
234 | #ifdef SK_BIG_ENDIAN | ||
235 | #define SK_U16_TO_NETWORK_ORDER(Val,Addr) (*(SK_U16*)(Addr) = (SK_U16)(Val)) | ||
236 | #endif /* SK_BIG_ENDIAN */ | ||
237 | |||
238 | #define AUTONEG_FAILED SK_FALSE | ||
239 | #define AUTONEG_SUCCESS SK_TRUE | ||
240 | |||
241 | |||
242 | /* typedefs *******************************************************************/ | ||
243 | |||
244 | /* RLMT packet. Length: SK_RLMT_MAX_PACKET_SIZE (60) bytes. */ | ||
245 | typedef struct s_RlmtPacket { | ||
246 | SK_U8 DstAddr[SK_MAC_ADDR_LEN]; | ||
247 | SK_U8 SrcAddr[SK_MAC_ADDR_LEN]; | ||
248 | SK_U8 TypeLen[2]; | ||
249 | SK_U8 DSap; | ||
250 | SK_U8 SSap; | ||
251 | SK_U8 Ctrl; | ||
252 | SK_U8 Indicator[7]; | ||
253 | SK_U8 RlmtPacketType[2]; | ||
254 | SK_U8 Align1[2]; | ||
255 | SK_U8 Random[4]; /* Random value of requesting(!) station. */ | ||
256 | SK_U8 RlmtPacketVersion[2]; /* RLMT Packet version. */ | ||
257 | SK_U8 Data[SK_PACKET_DATA_LEN]; | ||
258 | } SK_RLMT_PACKET; | ||
259 | |||
260 | typedef struct s_SpTreeRlmtPacket { | ||
261 | SK_U8 DstAddr[SK_MAC_ADDR_LEN]; | ||
262 | SK_U8 SrcAddr[SK_MAC_ADDR_LEN]; | ||
263 | SK_U8 TypeLen[2]; | ||
264 | SK_U8 DSap; | ||
265 | SK_U8 SSap; | ||
266 | SK_U8 Ctrl; | ||
267 | SK_U8 ProtocolId[2]; | ||
268 | SK_U8 ProtocolVersionId; | ||
269 | SK_U8 BpduType; | ||
270 | SK_U8 Flags; | ||
271 | SK_U8 RootId[8]; | ||
272 | SK_U8 RootPathCost[4]; | ||
273 | SK_U8 BridgeId[8]; | ||
274 | SK_U8 PortId[2]; | ||
275 | SK_U8 MessageAge[2]; | ||
276 | SK_U8 MaxAge[2]; | ||
277 | SK_U8 HelloTime[2]; | ||
278 | SK_U8 ForwardDelay[2]; | ||
279 | } SK_SPTREE_PACKET; | ||
280 | |||
281 | /* global variables ***********************************************************/ | ||
282 | |||
283 | SK_MAC_ADDR SkRlmtMcAddr = {{0x01, 0x00, 0x5A, 0x52, 0x4C, 0x4D}}; | ||
284 | SK_MAC_ADDR BridgeMcAddr = {{0x01, 0x80, 0xC2, 0x00, 0x00, 0x00}}; | ||
285 | SK_MAC_ADDR BcAddr = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; | ||
286 | |||
287 | /* local variables ************************************************************/ | ||
288 | |||
289 | /* None. */ | ||
290 | |||
291 | /* functions ******************************************************************/ | ||
292 | |||
293 | RLMT_STATIC void SkRlmtCheckSwitch( | ||
294 | SK_AC *pAC, | ||
295 | SK_IOC IoC, | ||
296 | SK_U32 NetIdx); | ||
297 | RLMT_STATIC void SkRlmtCheckSeg( | ||
298 | SK_AC *pAC, | ||
299 | SK_IOC IoC, | ||
300 | SK_U32 NetIdx); | ||
301 | RLMT_STATIC void SkRlmtEvtSetNets( | ||
302 | SK_AC *pAC, | ||
303 | SK_IOC IoC, | ||
304 | SK_EVPARA Para); | ||
305 | |||
306 | /****************************************************************************** | ||
307 | * | ||
308 | * SkRlmtInit - initialize data, set state to init | ||
309 | * | ||
310 | * Description: | ||
311 | * | ||
312 | * SK_INIT_DATA | ||
313 | * ============ | ||
314 | * | ||
315 | * This routine initializes all RLMT-related variables to a known state. | ||
316 | * The initial state is SK_RLMT_RS_INIT. | ||
317 | * All ports are initialized to SK_RLMT_PS_INIT. | ||
318 | * | ||
319 | * | ||
320 | * SK_INIT_IO | ||
321 | * ========== | ||
322 | * | ||
323 | * Nothing. | ||
324 | * | ||
325 | * | ||
326 | * SK_INIT_RUN | ||
327 | * =========== | ||
328 | * | ||
329 | * Determine the adapter's random value. | ||
330 | * Set the hw registers, the "logical MAC address", the | ||
331 | * RLMT multicast address, and eventually the BPDU multicast address. | ||
332 | * | ||
333 | * Context: | ||
334 | * init, pageable | ||
335 | * | ||
336 | * Returns: | ||
337 | * Nothing. | ||
338 | */ | ||
339 | void SkRlmtInit( | ||
340 | SK_AC *pAC, /* Adapter Context */ | ||
341 | SK_IOC IoC, /* I/O Context */ | ||
342 | int Level) /* Initialization Level */ | ||
343 | { | ||
344 | SK_U32 i, j; | ||
345 | SK_U64 Random; | ||
346 | SK_EVPARA Para; | ||
347 | SK_MAC_ADDR VirtualMacAddress; | ||
348 | SK_MAC_ADDR PhysicalAMacAddress; | ||
349 | SK_BOOL VirtualMacAddressSet; | ||
350 | SK_BOOL PhysicalAMacAddressSet; | ||
351 | |||
352 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT, | ||
353 | ("RLMT Init level %d.\n", Level)) | ||
354 | |||
355 | switch (Level) { | ||
356 | case SK_INIT_DATA: /* Initialize data structures. */ | ||
357 | SK_MEMSET((char *)&pAC->Rlmt, 0, sizeof(SK_RLMT)); | ||
358 | |||
359 | for (i = 0; i < SK_MAX_MACS; i++) { | ||
360 | pAC->Rlmt.Port[i].PortState = SK_RLMT_PS_INIT; | ||
361 | pAC->Rlmt.Port[i].LinkDown = SK_TRUE; | ||
362 | pAC->Rlmt.Port[i].PortDown = SK_TRUE; | ||
363 | pAC->Rlmt.Port[i].PortStarted = SK_FALSE; | ||
364 | pAC->Rlmt.Port[i].PortNoRx = SK_FALSE; | ||
365 | pAC->Rlmt.Port[i].RootIdSet = SK_FALSE; | ||
366 | pAC->Rlmt.Port[i].PortNumber = i; | ||
367 | pAC->Rlmt.Port[i].Net = &pAC->Rlmt.Net[0]; | ||
368 | pAC->Rlmt.Port[i].AddrPort = &pAC->Addr.Port[i]; | ||
369 | } | ||
370 | |||
371 | pAC->Rlmt.NumNets = 1; | ||
372 | for (i = 0; i < SK_MAX_NETS; i++) { | ||
373 | pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT; | ||
374 | pAC->Rlmt.Net[i].RootIdSet = SK_FALSE; | ||
375 | pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT; | ||
376 | pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF; /* Automatic. */ | ||
377 | /* Just assuming. */ | ||
378 | pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort; | ||
379 | pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE; | ||
380 | pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL; | ||
381 | pAC->Rlmt.Net[i].NetNumber = i; | ||
382 | } | ||
383 | |||
384 | pAC->Rlmt.Net[0].Port[0] = &pAC->Rlmt.Port[0]; | ||
385 | pAC->Rlmt.Net[0].Port[1] = &pAC->Rlmt.Port[1]; | ||
386 | #if SK_MAX_NETS > 1 | ||
387 | pAC->Rlmt.Net[1].Port[0] = &pAC->Rlmt.Port[1]; | ||
388 | #endif /* SK_MAX_NETS > 1 */ | ||
389 | break; | ||
390 | |||
391 | case SK_INIT_IO: /* GIMacsFound first available here. */ | ||
392 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT, | ||
393 | ("RLMT: %d MACs were detected.\n", pAC->GIni.GIMacsFound)) | ||
394 | |||
395 | pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound; | ||
396 | |||
397 | /* Initialize HW registers? */ | ||
398 | if (pAC->GIni.GIMacsFound == 1) { | ||
399 | Para.Para32[0] = SK_RLMT_MODE_CLS; | ||
400 | Para.Para32[1] = 0; | ||
401 | (void)SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE, Para); | ||
402 | } | ||
403 | break; | ||
404 | |||
405 | case SK_INIT_RUN: | ||
406 | /* Ensure RLMT is set to one net. */ | ||
407 | if (pAC->Rlmt.NumNets > 1) { | ||
408 | Para.Para32[0] = 1; | ||
409 | Para.Para32[1] = -1; | ||
410 | SkRlmtEvtSetNets(pAC, IoC, Para); | ||
411 | } | ||
412 | |||
413 | for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { | ||
414 | Random = SkOsGetTime(pAC); | ||
415 | *(SK_U32*)&pAC->Rlmt.Port[i].Random = *(SK_U32*)&Random; | ||
416 | |||
417 | for (j = 0; j < 4; j++) { | ||
418 | pAC->Rlmt.Port[i].Random[j] ^= pAC->Rlmt.Port[i].AddrPort-> | ||
419 | CurrentMacAddress.a[SK_MAC_ADDR_LEN - 1 - j]; | ||
420 | } | ||
421 | |||
422 | (void)SkAddrMcClear(pAC, IoC, i, SK_ADDR_PERMANENT | SK_MC_SW_ONLY); | ||
423 | |||
424 | /* Add RLMT MC address. */ | ||
425 | (void)SkAddrMcAdd(pAC, IoC, i, &SkRlmtMcAddr, SK_ADDR_PERMANENT); | ||
426 | |||
427 | if (pAC->Rlmt.Net[0].RlmtMode & SK_RLMT_CHECK_SEG) { | ||
428 | /* Add BPDU MC address. */ | ||
429 | (void)SkAddrMcAdd(pAC, IoC, i, &BridgeMcAddr, SK_ADDR_PERMANENT); | ||
430 | } | ||
431 | |||
432 | (void)SkAddrMcUpdate(pAC, IoC, i); | ||
433 | } | ||
434 | |||
435 | VirtualMacAddressSet = SK_FALSE; | ||
436 | /* Read virtual MAC address from Control Register File. */ | ||
437 | for (j = 0; j < SK_MAC_ADDR_LEN; j++) { | ||
438 | |||
439 | SK_IN8(IoC, B2_MAC_1 + j, &VirtualMacAddress.a[j]); | ||
440 | VirtualMacAddressSet |= VirtualMacAddress.a[j]; | ||
441 | } | ||
442 | |||
443 | PhysicalAMacAddressSet = SK_FALSE; | ||
444 | /* Read physical MAC address for MAC A from Control Register File. */ | ||
445 | for (j = 0; j < SK_MAC_ADDR_LEN; j++) { | ||
446 | |||
447 | SK_IN8(IoC, B2_MAC_2 + j, &PhysicalAMacAddress.a[j]); | ||
448 | PhysicalAMacAddressSet |= PhysicalAMacAddress.a[j]; | ||
449 | } | ||
450 | |||
451 | /* check if the two mac addresses contain reasonable values */ | ||
452 | if (!VirtualMacAddressSet || !PhysicalAMacAddressSet) { | ||
453 | |||
454 | pAC->Rlmt.RlmtOff = SK_TRUE; | ||
455 | } | ||
456 | |||
457 | /* if the two mac addresses are equal switch off the RLMT_PRE_LOOKAHEAD | ||
458 | and the RLMT_LOOKAHEAD macros */ | ||
459 | else if (SK_ADDR_EQUAL(PhysicalAMacAddress.a, VirtualMacAddress.a)) { | ||
460 | |||
461 | pAC->Rlmt.RlmtOff = SK_TRUE; | ||
462 | } | ||
463 | else { | ||
464 | pAC->Rlmt.RlmtOff = SK_FALSE; | ||
465 | } | ||
466 | break; | ||
467 | |||
468 | default: /* error */ | ||
469 | break; | ||
470 | } | ||
471 | return; | ||
472 | } /* SkRlmtInit */ | ||
473 | |||
474 | |||
475 | /****************************************************************************** | ||
476 | * | ||
477 | * SkRlmtBuildCheckChain - build the check chain | ||
478 | * | ||
479 | * Description: | ||
480 | * This routine builds the local check chain: | ||
481 | * - Each port that is up checks the next port. | ||
482 | * - The last port that is up checks the first port that is up. | ||
483 | * | ||
484 | * Notes: | ||
485 | * - Currently only local ports are considered when building the chain. | ||
486 | * - Currently the SuspectState is just reset; | ||
487 | * it would be better to save it ... | ||
488 | * | ||
489 | * Context: | ||
490 | * runtime, pageable? | ||
491 | * | ||
492 | * Returns: | ||
493 | * Nothing | ||
494 | */ | ||
495 | RLMT_STATIC void SkRlmtBuildCheckChain( | ||
496 | SK_AC *pAC, /* Adapter Context */ | ||
497 | SK_U32 NetIdx) /* Net Number */ | ||
498 | { | ||
499 | SK_U32 i; | ||
500 | SK_U32 NumMacsUp; | ||
501 | SK_RLMT_PORT * FirstMacUp; | ||
502 | SK_RLMT_PORT * PrevMacUp; | ||
503 | |||
504 | FirstMacUp = NULL; | ||
505 | PrevMacUp = NULL; | ||
506 | |||
507 | if (!(pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) { | ||
508 | for (i = 0; i < pAC->Rlmt.Net[i].NumPorts; i++) { | ||
509 | pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0; | ||
510 | } | ||
511 | return; /* Done. */ | ||
512 | } | ||
513 | |||
514 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
515 | ("SkRlmtBuildCheckChain.\n")) | ||
516 | |||
517 | NumMacsUp = 0; | ||
518 | |||
519 | for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) { | ||
520 | pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0; | ||
521 | pAC->Rlmt.Net[NetIdx].Port[i]->PortsSuspect = 0; | ||
522 | pAC->Rlmt.Net[NetIdx].Port[i]->CheckingState &= | ||
523 | ~(SK_RLMT_PCS_RX | SK_RLMT_PCS_TX); | ||
524 | |||
525 | /* | ||
526 | * If more than two links are detected we should consider | ||
527 | * checking at least two other ports: | ||
528 | * 1. the next port that is not LinkDown and | ||
529 | * 2. the next port that is not PortDown. | ||
530 | */ | ||
531 | if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) { | ||
532 | if (NumMacsUp == 0) { | ||
533 | FirstMacUp = pAC->Rlmt.Net[NetIdx].Port[i]; | ||
534 | } | ||
535 | else { | ||
536 | PrevMacUp->PortCheck[ | ||
537 | pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked].CheckAddr = | ||
538 | pAC->Rlmt.Net[NetIdx].Port[i]->AddrPort->CurrentMacAddress; | ||
539 | PrevMacUp->PortCheck[ | ||
540 | PrevMacUp->PortsChecked].SuspectTx = SK_FALSE; | ||
541 | PrevMacUp->PortsChecked++; | ||
542 | } | ||
543 | PrevMacUp = pAC->Rlmt.Net[NetIdx].Port[i]; | ||
544 | NumMacsUp++; | ||
545 | } | ||
546 | } | ||
547 | |||
548 | if (NumMacsUp > 1) { | ||
549 | PrevMacUp->PortCheck[PrevMacUp->PortsChecked].CheckAddr = | ||
550 | FirstMacUp->AddrPort->CurrentMacAddress; | ||
551 | PrevMacUp->PortCheck[PrevMacUp->PortsChecked].SuspectTx = | ||
552 | SK_FALSE; | ||
553 | PrevMacUp->PortsChecked++; | ||
554 | } | ||
555 | |||
556 | #ifdef DEBUG | ||
557 | for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) { | ||
558 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
559 | ("Port %d checks %d other ports: %2X.\n", i, | ||
560 | pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked, | ||
561 | pAC->Rlmt.Net[NetIdx].Port[i]->PortCheck[0].CheckAddr.a[5])) | ||
562 | } | ||
563 | #endif /* DEBUG */ | ||
564 | |||
565 | return; | ||
566 | } /* SkRlmtBuildCheckChain */ | ||
567 | |||
568 | |||
569 | /****************************************************************************** | ||
570 | * | ||
571 | * SkRlmtBuildPacket - build an RLMT packet | ||
572 | * | ||
573 | * Description: | ||
574 | * This routine sets up an RLMT packet. | ||
575 | * | ||
576 | * Context: | ||
577 | * runtime, pageable? | ||
578 | * | ||
579 | * Returns: | ||
580 | * NULL or pointer to RLMT mbuf | ||
581 | */ | ||
582 | RLMT_STATIC SK_MBUF *SkRlmtBuildPacket( | ||
583 | SK_AC *pAC, /* Adapter Context */ | ||
584 | SK_IOC IoC, /* I/O Context */ | ||
585 | SK_U32 PortNumber, /* Sending port */ | ||
586 | SK_U16 PacketType, /* RLMT packet type */ | ||
587 | SK_MAC_ADDR *SrcAddr, /* Source address */ | ||
588 | SK_MAC_ADDR *DestAddr) /* Destination address */ | ||
589 | { | ||
590 | int i; | ||
591 | SK_U16 Length; | ||
592 | SK_MBUF *pMb; | ||
593 | SK_RLMT_PACKET *pPacket; | ||
594 | |||
595 | #ifdef DEBUG | ||
596 | SK_U8 CheckSrc = 0; | ||
597 | SK_U8 CheckDest = 0; | ||
598 | |||
599 | for (i = 0; i < SK_MAC_ADDR_LEN; ++i) { | ||
600 | CheckSrc |= SrcAddr->a[i]; | ||
601 | CheckDest |= DestAddr->a[i]; | ||
602 | } | ||
603 | |||
604 | if ((CheckSrc == 0) || (CheckDest == 0)) { | ||
605 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_ERR, | ||
606 | ("SkRlmtBuildPacket: Invalid %s%saddr.\n", | ||
607 | (CheckSrc == 0 ? "Src" : ""), (CheckDest == 0 ? "Dest" : ""))) | ||
608 | } | ||
609 | #endif | ||
610 | |||
611 | if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) != NULL) { | ||
612 | pPacket = (SK_RLMT_PACKET*)pMb->pData; | ||
613 | for (i = 0; i < SK_MAC_ADDR_LEN; i++) { | ||
614 | pPacket->DstAddr[i] = DestAddr->a[i]; | ||
615 | pPacket->SrcAddr[i] = SrcAddr->a[i]; | ||
616 | } | ||
617 | pPacket->DSap = SK_RLMT_DSAP; | ||
618 | pPacket->SSap = SK_RLMT_SSAP; | ||
619 | pPacket->Ctrl = SK_RLMT_CTRL; | ||
620 | pPacket->Indicator[0] = SK_RLMT_INDICATOR0; | ||
621 | pPacket->Indicator[1] = SK_RLMT_INDICATOR1; | ||
622 | pPacket->Indicator[2] = SK_RLMT_INDICATOR2; | ||
623 | pPacket->Indicator[3] = SK_RLMT_INDICATOR3; | ||
624 | pPacket->Indicator[4] = SK_RLMT_INDICATOR4; | ||
625 | pPacket->Indicator[5] = SK_RLMT_INDICATOR5; | ||
626 | pPacket->Indicator[6] = SK_RLMT_INDICATOR6; | ||
627 | |||
628 | SK_U16_TO_NETWORK_ORDER(PacketType, &pPacket->RlmtPacketType[0]); | ||
629 | |||
630 | for (i = 0; i < 4; i++) { | ||
631 | pPacket->Random[i] = pAC->Rlmt.Port[PortNumber].Random[i]; | ||
632 | } | ||
633 | |||
634 | SK_U16_TO_NETWORK_ORDER( | ||
635 | SK_RLMT_PACKET_VERSION, &pPacket->RlmtPacketVersion[0]); | ||
636 | |||
637 | for (i = 0; i < SK_PACKET_DATA_LEN; i++) { | ||
638 | pPacket->Data[i] = 0x00; | ||
639 | } | ||
640 | |||
641 | Length = SK_RLMT_MAX_PACKET_SIZE; /* Or smaller. */ | ||
642 | pMb->Length = Length; | ||
643 | pMb->PortIdx = PortNumber; | ||
644 | Length -= 14; | ||
645 | SK_U16_TO_NETWORK_ORDER(Length, &pPacket->TypeLen[0]); | ||
646 | |||
647 | if (PacketType == SK_PACKET_ALIVE) { | ||
648 | pAC->Rlmt.Port[PortNumber].TxHelloCts++; | ||
649 | } | ||
650 | } | ||
651 | |||
652 | return (pMb); | ||
653 | } /* SkRlmtBuildPacket */ | ||
654 | |||
655 | |||
656 | /****************************************************************************** | ||
657 | * | ||
658 | * SkRlmtBuildSpanningTreePacket - build spanning tree check packet | ||
659 | * | ||
660 | * Description: | ||
661 | * This routine sets up a BPDU packet for spanning tree check. | ||
662 | * | ||
663 | * Context: | ||
664 | * runtime, pageable? | ||
665 | * | ||
666 | * Returns: | ||
667 | * NULL or pointer to RLMT mbuf | ||
668 | */ | ||
669 | RLMT_STATIC SK_MBUF *SkRlmtBuildSpanningTreePacket( | ||
670 | SK_AC *pAC, /* Adapter Context */ | ||
671 | SK_IOC IoC, /* I/O Context */ | ||
672 | SK_U32 PortNumber) /* Sending port */ | ||
673 | { | ||
674 | unsigned i; | ||
675 | SK_U16 Length; | ||
676 | SK_MBUF *pMb; | ||
677 | SK_SPTREE_PACKET *pSPacket; | ||
678 | |||
679 | if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) != | ||
680 | NULL) { | ||
681 | pSPacket = (SK_SPTREE_PACKET*)pMb->pData; | ||
682 | for (i = 0; i < SK_MAC_ADDR_LEN; i++) { | ||
683 | pSPacket->DstAddr[i] = BridgeMcAddr.a[i]; | ||
684 | pSPacket->SrcAddr[i] = | ||
685 | pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i]; | ||
686 | } | ||
687 | pSPacket->DSap = SK_RLMT_SPT_DSAP; | ||
688 | pSPacket->SSap = SK_RLMT_SPT_SSAP; | ||
689 | pSPacket->Ctrl = SK_RLMT_SPT_CTRL; | ||
690 | |||
691 | pSPacket->ProtocolId[0] = SK_RLMT_SPT_PROTOCOL_ID0; | ||
692 | pSPacket->ProtocolId[1] = SK_RLMT_SPT_PROTOCOL_ID1; | ||
693 | pSPacket->ProtocolVersionId = SK_RLMT_SPT_PROTOCOL_VERSION_ID; | ||
694 | pSPacket->BpduType = SK_RLMT_SPT_BPDU_TYPE; | ||
695 | pSPacket->Flags = SK_RLMT_SPT_FLAGS; | ||
696 | pSPacket->RootId[0] = SK_RLMT_SPT_ROOT_ID0; | ||
697 | pSPacket->RootId[1] = SK_RLMT_SPT_ROOT_ID1; | ||
698 | pSPacket->RootPathCost[0] = SK_RLMT_SPT_ROOT_PATH_COST0; | ||
699 | pSPacket->RootPathCost[1] = SK_RLMT_SPT_ROOT_PATH_COST1; | ||
700 | pSPacket->RootPathCost[2] = SK_RLMT_SPT_ROOT_PATH_COST2; | ||
701 | pSPacket->RootPathCost[3] = SK_RLMT_SPT_ROOT_PATH_COST3; | ||
702 | pSPacket->BridgeId[0] = SK_RLMT_SPT_BRIDGE_ID0; | ||
703 | pSPacket->BridgeId[1] = SK_RLMT_SPT_BRIDGE_ID1; | ||
704 | |||
705 | /* | ||
706 | * Use logical MAC address as bridge ID and filter these packets | ||
707 | * on receive. | ||
708 | */ | ||
709 | for (i = 0; i < SK_MAC_ADDR_LEN; i++) { | ||
710 | pSPacket->BridgeId[i + 2] = pSPacket->RootId[i + 2] = | ||
711 | pAC->Addr.Net[pAC->Rlmt.Port[PortNumber].Net->NetNumber]. | ||
712 | CurrentMacAddress.a[i]; | ||
713 | } | ||
714 | pSPacket->PortId[0] = SK_RLMT_SPT_PORT_ID0; | ||
715 | pSPacket->PortId[1] = SK_RLMT_SPT_PORT_ID1; | ||
716 | pSPacket->MessageAge[0] = SK_RLMT_SPT_MSG_AGE0; | ||
717 | pSPacket->MessageAge[1] = SK_RLMT_SPT_MSG_AGE1; | ||
718 | pSPacket->MaxAge[0] = SK_RLMT_SPT_MAX_AGE0; | ||
719 | pSPacket->MaxAge[1] = SK_RLMT_SPT_MAX_AGE1; | ||
720 | pSPacket->HelloTime[0] = SK_RLMT_SPT_HELLO_TIME0; | ||
721 | pSPacket->HelloTime[1] = SK_RLMT_SPT_HELLO_TIME1; | ||
722 | pSPacket->ForwardDelay[0] = SK_RLMT_SPT_FWD_DELAY0; | ||
723 | pSPacket->ForwardDelay[1] = SK_RLMT_SPT_FWD_DELAY1; | ||
724 | |||
725 | Length = SK_RLMT_MAX_PACKET_SIZE; /* Or smaller. */ | ||
726 | pMb->Length = Length; | ||
727 | pMb->PortIdx = PortNumber; | ||
728 | Length -= 14; | ||
729 | SK_U16_TO_NETWORK_ORDER(Length, &pSPacket->TypeLen[0]); | ||
730 | |||
731 | pAC->Rlmt.Port[PortNumber].TxSpHelloReqCts++; | ||
732 | } | ||
733 | |||
734 | return (pMb); | ||
735 | } /* SkRlmtBuildSpanningTreePacket */ | ||
736 | |||
737 | |||
738 | /****************************************************************************** | ||
739 | * | ||
740 | * SkRlmtSend - build and send check packets | ||
741 | * | ||
742 | * Description: | ||
743 | * Depending on the RLMT state and the checking state, several packets | ||
744 | * are sent through the indicated port. | ||
745 | * | ||
746 | * Context: | ||
747 | * runtime, pageable? | ||
748 | * | ||
749 | * Returns: | ||
750 | * Nothing. | ||
751 | */ | ||
752 | RLMT_STATIC void SkRlmtSend( | ||
753 | SK_AC *pAC, /* Adapter Context */ | ||
754 | SK_IOC IoC, /* I/O Context */ | ||
755 | SK_U32 PortNumber) /* Sending port */ | ||
756 | { | ||
757 | unsigned j; | ||
758 | SK_EVPARA Para; | ||
759 | SK_RLMT_PORT *pRPort; | ||
760 | |||
761 | pRPort = &pAC->Rlmt.Port[PortNumber]; | ||
762 | if (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) { | ||
763 | if (pRPort->CheckingState & (SK_RLMT_PCS_TX | SK_RLMT_PCS_RX)) { | ||
764 | /* Port is suspicious. Send the RLMT packet to the RLMT mc addr. */ | ||
765 | if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber, | ||
766 | SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress, | ||
767 | &SkRlmtMcAddr)) != NULL) { | ||
768 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); | ||
769 | } | ||
770 | } | ||
771 | else { | ||
772 | /* | ||
773 | * Send a directed RLMT packet to all ports that are | ||
774 | * checked by the indicated port. | ||
775 | */ | ||
776 | for (j = 0; j < pRPort->PortsChecked; j++) { | ||
777 | if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber, | ||
778 | SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress, | ||
779 | &pRPort->PortCheck[j].CheckAddr)) != NULL) { | ||
780 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); | ||
781 | } | ||
782 | } | ||
783 | } | ||
784 | } | ||
785 | |||
786 | if ((pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) && | ||
787 | (pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEND_SEG)) { | ||
788 | /* | ||
789 | * Send a BPDU packet to make a connected switch tell us | ||
790 | * the correct root bridge. | ||
791 | */ | ||
792 | if ((Para.pParaPtr = | ||
793 | SkRlmtBuildSpanningTreePacket(pAC, IoC, PortNumber)) != NULL) { | ||
794 | pAC->Rlmt.Port[PortNumber].Net->CheckingState &= ~SK_RLMT_RCS_SEND_SEG; | ||
795 | pRPort->RootIdSet = SK_FALSE; | ||
796 | |||
797 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); | ||
798 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_TX, | ||
799 | ("SkRlmtSend: BPDU Packet on Port %u.\n", PortNumber)) | ||
800 | } | ||
801 | } | ||
802 | return; | ||
803 | } /* SkRlmtSend */ | ||
804 | |||
805 | |||
806 | /****************************************************************************** | ||
807 | * | ||
808 | * SkRlmtPortReceives - check if port is (going) down and bring it up | ||
809 | * | ||
810 | * Description: | ||
811 | * This routine checks if a port who received a non-BPDU packet | ||
812 | * needs to go up or needs to be stopped going down. | ||
813 | * | ||
814 | * Context: | ||
815 | * runtime, pageable? | ||
816 | * | ||
817 | * Returns: | ||
818 | * Nothing. | ||
819 | */ | ||
820 | RLMT_STATIC void SkRlmtPortReceives( | ||
821 | SK_AC *pAC, /* Adapter Context */ | ||
822 | SK_IOC IoC, /* I/O Context */ | ||
823 | SK_U32 PortNumber) /* Port to check */ | ||
824 | { | ||
825 | SK_RLMT_PORT *pRPort; | ||
826 | SK_EVPARA Para; | ||
827 | |||
828 | pRPort = &pAC->Rlmt.Port[PortNumber]; | ||
829 | pRPort->PortNoRx = SK_FALSE; | ||
830 | |||
831 | if ((pRPort->PortState == SK_RLMT_PS_DOWN) && | ||
832 | !(pRPort->CheckingState & SK_RLMT_PCS_TX)) { | ||
833 | /* | ||
834 | * Port is marked down (rx), but received a non-BPDU packet. | ||
835 | * Bring it up. | ||
836 | */ | ||
837 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, | ||
838 | ("SkRlmtPacketReceive: Received on PortDown.\n")) | ||
839 | |||
840 | pRPort->PortState = SK_RLMT_PS_GOING_UP; | ||
841 | pRPort->GuTimeStamp = SkOsGetTime(pAC); | ||
842 | Para.Para32[0] = PortNumber; | ||
843 | Para.Para32[1] = (SK_U32)-1; | ||
844 | SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL, | ||
845 | SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para); | ||
846 | pRPort->CheckingState &= ~SK_RLMT_PCS_RX; | ||
847 | /* pAC->Rlmt.CheckSwitch = SK_TRUE; */ | ||
848 | SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); | ||
849 | } /* PortDown && !SuspectTx */ | ||
850 | else if (pRPort->CheckingState & SK_RLMT_PCS_RX) { | ||
851 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, | ||
852 | ("SkRlmtPacketReceive: Stop bringing port down.\n")) | ||
853 | SkTimerStop(pAC, IoC, &pRPort->DownRxTimer); | ||
854 | pRPort->CheckingState &= ~SK_RLMT_PCS_RX; | ||
855 | /* pAC->Rlmt.CheckSwitch = SK_TRUE; */ | ||
856 | SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); | ||
857 | } /* PortGoingDown */ | ||
858 | |||
859 | return; | ||
860 | } /* SkRlmtPortReceives */ | ||
861 | |||
862 | |||
863 | /****************************************************************************** | ||
864 | * | ||
865 | * SkRlmtPacketReceive - receive a packet for closer examination | ||
866 | * | ||
867 | * Description: | ||
868 | * This routine examines a packet more closely than SK_RLMT_LOOKAHEAD. | ||
869 | * | ||
870 | * Context: | ||
871 | * runtime, pageable? | ||
872 | * | ||
873 | * Returns: | ||
874 | * Nothing. | ||
875 | */ | ||
876 | RLMT_STATIC void SkRlmtPacketReceive( | ||
877 | SK_AC *pAC, /* Adapter Context */ | ||
878 | SK_IOC IoC, /* I/O Context */ | ||
879 | SK_MBUF *pMb) /* Received packet */ | ||
880 | { | ||
881 | #ifdef xDEBUG | ||
882 | extern void DumpData(char *p, int size); | ||
883 | #endif /* DEBUG */ | ||
884 | int i; | ||
885 | unsigned j; | ||
886 | SK_U16 PacketType; | ||
887 | SK_U32 PortNumber; | ||
888 | SK_ADDR_PORT *pAPort; | ||
889 | SK_RLMT_PORT *pRPort; | ||
890 | SK_RLMT_PACKET *pRPacket; | ||
891 | SK_SPTREE_PACKET *pSPacket; | ||
892 | SK_EVPARA Para; | ||
893 | |||
894 | PortNumber = pMb->PortIdx; | ||
895 | pAPort = &pAC->Addr.Port[PortNumber]; | ||
896 | pRPort = &pAC->Rlmt.Port[PortNumber]; | ||
897 | |||
898 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, | ||
899 | ("SkRlmtPacketReceive: PortNumber == %d.\n", PortNumber)) | ||
900 | |||
901 | pRPacket = (SK_RLMT_PACKET*)pMb->pData; | ||
902 | pSPacket = (SK_SPTREE_PACKET*)pRPacket; | ||
903 | |||
904 | #ifdef xDEBUG | ||
905 | DumpData((char *)pRPacket, 32); | ||
906 | #endif /* DEBUG */ | ||
907 | |||
908 | if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) != 0) { | ||
909 | SkRlmtPortReceives(pAC, IoC, PortNumber); | ||
910 | } | ||
911 | |||
912 | /* Check destination address. */ | ||
913 | |||
914 | if (!SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->DstAddr) && | ||
915 | !SK_ADDR_EQUAL(SkRlmtMcAddr.a, pRPacket->DstAddr) && | ||
916 | !SK_ADDR_EQUAL(BridgeMcAddr.a, pRPacket->DstAddr)) { | ||
917 | |||
918 | /* Not sent to current MAC or registered MC address => Trash it. */ | ||
919 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, | ||
920 | ("SkRlmtPacketReceive: Not for me.\n")) | ||
921 | |||
922 | SkDrvFreeRlmtMbuf(pAC, IoC, pMb); | ||
923 | return; | ||
924 | } | ||
925 | else if (SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->SrcAddr)) { | ||
926 | |||
927 | /* | ||
928 | * Was sent by same port (may happen during port switching | ||
929 | * or in case of duplicate MAC addresses). | ||
930 | */ | ||
931 | |||
932 | /* | ||
933 | * Check for duplicate address here: | ||
934 | * If Packet.Random != My.Random => DupAddr. | ||
935 | */ | ||
936 | for (i = 3; i >= 0; i--) { | ||
937 | if (pRPort->Random[i] != pRPacket->Random[i]) { | ||
938 | break; | ||
939 | } | ||
940 | } | ||
941 | |||
942 | /* | ||
943 | * CAUTION: Do not check for duplicate MAC address in RLMT Alive Reply | ||
944 | * packets (they have the LLC_COMMAND_RESPONSE_BIT set in | ||
945 | * pRPacket->SSap). | ||
946 | */ | ||
947 | if (i >= 0 && pRPacket->DSap == SK_RLMT_DSAP && | ||
948 | pRPacket->Ctrl == SK_RLMT_CTRL && | ||
949 | pRPacket->SSap == SK_RLMT_SSAP && | ||
950 | pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 && | ||
951 | pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 && | ||
952 | pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 && | ||
953 | pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 && | ||
954 | pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 && | ||
955 | pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 && | ||
956 | pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) { | ||
957 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, | ||
958 | ("SkRlmtPacketReceive: Duplicate MAC Address.\n")) | ||
959 | |||
960 | /* Error Log entry. */ | ||
961 | SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E006, SKERR_RLMT_E006_MSG); | ||
962 | } | ||
963 | else { | ||
964 | /* Simply trash it. */ | ||
965 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, | ||
966 | ("SkRlmtPacketReceive: Sent by me.\n")) | ||
967 | } | ||
968 | |||
969 | SkDrvFreeRlmtMbuf(pAC, IoC, pMb); | ||
970 | return; | ||
971 | } | ||
972 | |||
973 | /* Check SuspectTx entries. */ | ||
974 | if (pRPort->PortsSuspect > 0) { | ||
975 | for (j = 0; j < pRPort->PortsChecked; j++) { | ||
976 | if (pRPort->PortCheck[j].SuspectTx && | ||
977 | SK_ADDR_EQUAL( | ||
978 | pRPacket->SrcAddr, pRPort->PortCheck[j].CheckAddr.a)) { | ||
979 | pRPort->PortCheck[j].SuspectTx = SK_FALSE; | ||
980 | pRPort->PortsSuspect--; | ||
981 | break; | ||
982 | } | ||
983 | } | ||
984 | } | ||
985 | |||
986 | /* Determine type of packet. */ | ||
987 | if (pRPacket->DSap == SK_RLMT_DSAP && | ||
988 | pRPacket->Ctrl == SK_RLMT_CTRL && | ||
989 | (pRPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SSAP && | ||
990 | pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 && | ||
991 | pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 && | ||
992 | pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 && | ||
993 | pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 && | ||
994 | pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 && | ||
995 | pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 && | ||
996 | pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) { | ||
997 | |||
998 | /* It's an RLMT packet. */ | ||
999 | PacketType = (SK_U16)((pRPacket->RlmtPacketType[0] << 8) | | ||
1000 | pRPacket->RlmtPacketType[1]); | ||
1001 | |||
1002 | switch (PacketType) { | ||
1003 | case SK_PACKET_ANNOUNCE: /* Not yet used. */ | ||
1004 | #if 0 | ||
1005 | /* Build the check chain. */ | ||
1006 | SkRlmtBuildCheckChain(pAC); | ||
1007 | #endif /* 0 */ | ||
1008 | |||
1009 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, | ||
1010 | ("SkRlmtPacketReceive: Announce.\n")) | ||
1011 | |||
1012 | SkDrvFreeRlmtMbuf(pAC, IoC, pMb); | ||
1013 | break; | ||
1014 | |||
1015 | case SK_PACKET_ALIVE: | ||
1016 | if (pRPacket->SSap & LLC_COMMAND_RESPONSE_BIT) { | ||
1017 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, | ||
1018 | ("SkRlmtPacketReceive: Alive Reply.\n")) | ||
1019 | |||
1020 | if (!(pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_LLC) || | ||
1021 | SK_ADDR_EQUAL( | ||
1022 | pRPacket->DstAddr, pAPort->CurrentMacAddress.a)) { | ||
1023 | /* Obviously we could send something. */ | ||
1024 | if (pRPort->CheckingState & SK_RLMT_PCS_TX) { | ||
1025 | pRPort->CheckingState &= ~SK_RLMT_PCS_TX; | ||
1026 | SkTimerStop(pAC, IoC, &pRPort->DownTxTimer); | ||
1027 | } | ||
1028 | |||
1029 | if ((pRPort->PortState == SK_RLMT_PS_DOWN) && | ||
1030 | !(pRPort->CheckingState & SK_RLMT_PCS_RX)) { | ||
1031 | pRPort->PortState = SK_RLMT_PS_GOING_UP; | ||
1032 | pRPort->GuTimeStamp = SkOsGetTime(pAC); | ||
1033 | |||
1034 | SkTimerStop(pAC, IoC, &pRPort->DownTxTimer); | ||
1035 | |||
1036 | Para.Para32[0] = PortNumber; | ||
1037 | Para.Para32[1] = (SK_U32)-1; | ||
1038 | SkTimerStart(pAC, IoC, &pRPort->UpTimer, | ||
1039 | SK_RLMT_PORTUP_TIM_VAL, SKGE_RLMT, | ||
1040 | SK_RLMT_PORTUP_TIM, Para); | ||
1041 | } | ||
1042 | } | ||
1043 | |||
1044 | /* Mark sending port as alive? */ | ||
1045 | SkDrvFreeRlmtMbuf(pAC, IoC, pMb); | ||
1046 | } | ||
1047 | else { /* Alive Request Packet. */ | ||
1048 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, | ||
1049 | ("SkRlmtPacketReceive: Alive Request.\n")) | ||
1050 | |||
1051 | pRPort->RxHelloCts++; | ||
1052 | |||
1053 | /* Answer. */ | ||
1054 | for (i = 0; i < SK_MAC_ADDR_LEN; i++) { | ||
1055 | pRPacket->DstAddr[i] = pRPacket->SrcAddr[i]; | ||
1056 | pRPacket->SrcAddr[i] = | ||
1057 | pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i]; | ||
1058 | } | ||
1059 | pRPacket->SSap |= LLC_COMMAND_RESPONSE_BIT; | ||
1060 | |||
1061 | Para.pParaPtr = pMb; | ||
1062 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); | ||
1063 | } | ||
1064 | break; | ||
1065 | |||
1066 | case SK_PACKET_CHECK_TX: | ||
1067 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, | ||
1068 | ("SkRlmtPacketReceive: Check your tx line.\n")) | ||
1069 | |||
1070 | /* A port checking us requests us to check our tx line. */ | ||
1071 | pRPort->CheckingState |= SK_RLMT_PCS_TX; | ||
1072 | |||
1073 | /* Start PortDownTx timer. */ | ||
1074 | Para.Para32[0] = PortNumber; | ||
1075 | Para.Para32[1] = (SK_U32)-1; | ||
1076 | SkTimerStart(pAC, IoC, &pRPort->DownTxTimer, | ||
1077 | SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT, | ||
1078 | SK_RLMT_PORTDOWN_TX_TIM, Para); | ||
1079 | |||
1080 | SkDrvFreeRlmtMbuf(pAC, IoC, pMb); | ||
1081 | |||
1082 | if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber, | ||
1083 | SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress, | ||
1084 | &SkRlmtMcAddr)) != NULL) { | ||
1085 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); | ||
1086 | } | ||
1087 | break; | ||
1088 | |||
1089 | case SK_PACKET_ADDR_CHANGED: | ||
1090 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, | ||
1091 | ("SkRlmtPacketReceive: Address Change.\n")) | ||
1092 | |||
1093 | /* Build the check chain. */ | ||
1094 | SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber); | ||
1095 | SkDrvFreeRlmtMbuf(pAC, IoC, pMb); | ||
1096 | break; | ||
1097 | |||
1098 | default: | ||
1099 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, | ||
1100 | ("SkRlmtPacketReceive: Unknown RLMT packet.\n")) | ||
1101 | |||
1102 | /* RA;:;: ??? */ | ||
1103 | SkDrvFreeRlmtMbuf(pAC, IoC, pMb); | ||
1104 | } | ||
1105 | } | ||
1106 | else if (pSPacket->DSap == SK_RLMT_SPT_DSAP && | ||
1107 | pSPacket->Ctrl == SK_RLMT_SPT_CTRL && | ||
1108 | (pSPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SPT_SSAP) { | ||
1109 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, | ||
1110 | ("SkRlmtPacketReceive: BPDU Packet.\n")) | ||
1111 | |||
1112 | /* Spanning Tree packet. */ | ||
1113 | pRPort->RxSpHelloCts++; | ||
1114 | |||
1115 | if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pAC->Addr.Net[pAC->Rlmt. | ||
1116 | Port[PortNumber].Net->NetNumber].CurrentMacAddress.a[0])) { | ||
1117 | /* | ||
1118 | * Check segmentation if a new root bridge is set and | ||
1119 | * the segmentation check is not currently running. | ||
1120 | */ | ||
1121 | if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pRPort->Root.Id[2]) && | ||
1122 | (pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) && | ||
1123 | (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) | ||
1124 | != 0 && (pAC->Rlmt.Port[PortNumber].Net->CheckingState & | ||
1125 | SK_RLMT_RCS_SEG) == 0) { | ||
1126 | pAC->Rlmt.Port[PortNumber].Net->CheckingState |= | ||
1127 | SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG; | ||
1128 | } | ||
1129 | |||
1130 | /* Store tree view of this port. */ | ||
1131 | for (i = 0; i < 8; i++) { | ||
1132 | pRPort->Root.Id[i] = pSPacket->RootId[i]; | ||
1133 | } | ||
1134 | pRPort->RootIdSet = SK_TRUE; | ||
1135 | |||
1136 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP, | ||
1137 | ("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n", | ||
1138 | PortNumber, | ||
1139 | pRPort->Root.Id[0], pRPort->Root.Id[1], | ||
1140 | pRPort->Root.Id[2], pRPort->Root.Id[3], | ||
1141 | pRPort->Root.Id[4], pRPort->Root.Id[5], | ||
1142 | pRPort->Root.Id[6], pRPort->Root.Id[7])) | ||
1143 | } | ||
1144 | |||
1145 | SkDrvFreeRlmtMbuf(pAC, IoC, pMb); | ||
1146 | if ((pAC->Rlmt.Port[PortNumber].Net->CheckingState & | ||
1147 | SK_RLMT_RCS_REPORT_SEG) != 0) { | ||
1148 | SkRlmtCheckSeg(pAC, IoC, pAC->Rlmt.Port[PortNumber].Net->NetNumber); | ||
1149 | } | ||
1150 | } | ||
1151 | else { | ||
1152 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, | ||
1153 | ("SkRlmtPacketReceive: Unknown Packet Type.\n")) | ||
1154 | |||
1155 | /* Unknown packet. */ | ||
1156 | SkDrvFreeRlmtMbuf(pAC, IoC, pMb); | ||
1157 | } | ||
1158 | return; | ||
1159 | } /* SkRlmtPacketReceive */ | ||
1160 | |||
1161 | |||
1162 | /****************************************************************************** | ||
1163 | * | ||
1164 | * SkRlmtCheckPort - check if a port works | ||
1165 | * | ||
1166 | * Description: | ||
1167 | * This routine checks if a port whose link is up received something | ||
1168 | * and if it seems to transmit successfully. | ||
1169 | * | ||
1170 | * # PortState: PsInit, PsLinkDown, PsDown, PsGoingUp, PsUp | ||
1171 | * # PortCheckingState (Bitfield): ChkTx, ChkRx, ChkSeg | ||
1172 | * # RlmtCheckingState (Bitfield): ChkSeg, StartChkSeg, ReportSeg | ||
1173 | * | ||
1174 | * if (Rx - RxBpdu == 0) { # No rx. | ||
1175 | * if (state == PsUp) { | ||
1176 | * PortCheckingState |= ChkRx | ||
1177 | * } | ||
1178 | * if (ModeCheckSeg && (Timeout == | ||
1179 | * TO_SHORTEN(RLMT_DEFAULT_TIMEOUT))) { | ||
1180 | * RlmtCheckingState |= ChkSeg) | ||
1181 | * PortCheckingState |= ChkSeg | ||
1182 | * } | ||
1183 | * NewTimeout = TO_SHORTEN(Timeout) | ||
1184 | * if (NewTimeout < RLMT_MIN_TIMEOUT) { | ||
1185 | * NewTimeout = RLMT_MIN_TIMEOUT | ||
1186 | * PortState = PsDown | ||
1187 | * ... | ||
1188 | * } | ||
1189 | * } | ||
1190 | * else { # something was received | ||
1191 | * # Set counter to 0 at LinkDown? | ||
1192 | * # No - rx may be reported after LinkDown ??? | ||
1193 | * PortCheckingState &= ~ChkRx | ||
1194 | * NewTimeout = RLMT_DEFAULT_TIMEOUT | ||
1195 | * if (RxAck == 0) { | ||
1196 | * possible reasons: | ||
1197 | * is my tx line bad? -- | ||
1198 | * send RLMT multicast and report | ||
1199 | * back internally? (only possible | ||
1200 | * between ports on same adapter) | ||
1201 | * } | ||
1202 | * if (RxChk == 0) { | ||
1203 | * possible reasons: | ||
1204 | * - tx line of port set to check me | ||
1205 | * maybe bad | ||
1206 | * - no other port/adapter available or set | ||
1207 | * to check me | ||
1208 | * - adapter checking me has a longer | ||
1209 | * timeout | ||
1210 | * ??? anything that can be done here? | ||
1211 | * } | ||
1212 | * } | ||
1213 | * | ||
1214 | * Context: | ||
1215 | * runtime, pageable? | ||
1216 | * | ||
1217 | * Returns: | ||
1218 | * New timeout value. | ||
1219 | */ | ||
1220 | RLMT_STATIC SK_U32 SkRlmtCheckPort( | ||
1221 | SK_AC *pAC, /* Adapter Context */ | ||
1222 | SK_IOC IoC, /* I/O Context */ | ||
1223 | SK_U32 PortNumber) /* Port to check */ | ||
1224 | { | ||
1225 | unsigned i; | ||
1226 | SK_U32 NewTimeout; | ||
1227 | SK_RLMT_PORT *pRPort; | ||
1228 | SK_EVPARA Para; | ||
1229 | |||
1230 | pRPort = &pAC->Rlmt.Port[PortNumber]; | ||
1231 | |||
1232 | if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) == 0) { | ||
1233 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
1234 | ("SkRlmtCheckPort %d: No (%d) receives in last time slot.\n", | ||
1235 | PortNumber, pRPort->PacketsPerTimeSlot)) | ||
1236 | |||
1237 | /* | ||
1238 | * Check segmentation if there was no receive at least twice | ||
1239 | * in a row (PortNoRx is already set) and the segmentation | ||
1240 | * check is not currently running. | ||
1241 | */ | ||
1242 | |||
1243 | if (pRPort->PortNoRx && (pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) && | ||
1244 | (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) && | ||
1245 | !(pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEG)) { | ||
1246 | pAC->Rlmt.Port[PortNumber].Net->CheckingState |= | ||
1247 | SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG; | ||
1248 | } | ||
1249 | |||
1250 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
1251 | ("SkRlmtCheckPort: PortsSuspect %d, PcsRx %d.\n", | ||
1252 | pRPort->PortsSuspect, pRPort->CheckingState & SK_RLMT_PCS_RX)) | ||
1253 | |||
1254 | if (pRPort->PortState != SK_RLMT_PS_DOWN) { | ||
1255 | NewTimeout = TO_SHORTEN(pAC->Rlmt.Port[PortNumber].Net->TimeoutValue); | ||
1256 | if (NewTimeout < SK_RLMT_MIN_TO_VAL) { | ||
1257 | NewTimeout = SK_RLMT_MIN_TO_VAL; | ||
1258 | } | ||
1259 | |||
1260 | if (!(pRPort->CheckingState & SK_RLMT_PCS_RX)) { | ||
1261 | Para.Para32[0] = PortNumber; | ||
1262 | pRPort->CheckingState |= SK_RLMT_PCS_RX; | ||
1263 | |||
1264 | /* | ||
1265 | * What shall we do if the port checked by this one receives | ||
1266 | * our request frames? What's bad - our rx line or his tx line? | ||
1267 | */ | ||
1268 | Para.Para32[1] = (SK_U32)-1; | ||
1269 | SkTimerStart(pAC, IoC, &pRPort->DownRxTimer, | ||
1270 | SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT, | ||
1271 | SK_RLMT_PORTDOWN_RX_TIM, Para); | ||
1272 | |||
1273 | for (i = 0; i < pRPort->PortsChecked; i++) { | ||
1274 | if (pRPort->PortCheck[i].SuspectTx) { | ||
1275 | continue; | ||
1276 | } | ||
1277 | pRPort->PortCheck[i].SuspectTx = SK_TRUE; | ||
1278 | pRPort->PortsSuspect++; | ||
1279 | if ((Para.pParaPtr = | ||
1280 | SkRlmtBuildPacket(pAC, IoC, PortNumber, SK_PACKET_CHECK_TX, | ||
1281 | &pAC->Addr.Port[PortNumber].CurrentMacAddress, | ||
1282 | &pRPort->PortCheck[i].CheckAddr)) != NULL) { | ||
1283 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); | ||
1284 | } | ||
1285 | } | ||
1286 | } | ||
1287 | } | ||
1288 | else { /* PortDown -- or all partners suspect. */ | ||
1289 | NewTimeout = SK_RLMT_DEF_TO_VAL; | ||
1290 | } | ||
1291 | pRPort->PortNoRx = SK_TRUE; | ||
1292 | } | ||
1293 | else { /* A non-BPDU packet was received. */ | ||
1294 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
1295 | ("SkRlmtCheckPort %d: %d (%d) receives in last time slot.\n", | ||
1296 | PortNumber, | ||
1297 | pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot, | ||
1298 | pRPort->PacketsPerTimeSlot)) | ||
1299 | |||
1300 | SkRlmtPortReceives(pAC, IoC, PortNumber); | ||
1301 | if (pAC->Rlmt.CheckSwitch) { | ||
1302 | SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); | ||
1303 | } | ||
1304 | |||
1305 | NewTimeout = SK_RLMT_DEF_TO_VAL; | ||
1306 | } | ||
1307 | |||
1308 | return (NewTimeout); | ||
1309 | } /* SkRlmtCheckPort */ | ||
1310 | |||
1311 | |||
1312 | /****************************************************************************** | ||
1313 | * | ||
1314 | * SkRlmtSelectBcRx - select new active port, criteria 1 (CLP) | ||
1315 | * | ||
1316 | * Description: | ||
1317 | * This routine selects the port that received a broadcast frame | ||
1318 | * substantially later than all other ports. | ||
1319 | * | ||
1320 | * Context: | ||
1321 | * runtime, pageable? | ||
1322 | * | ||
1323 | * Returns: | ||
1324 | * SK_BOOL | ||
1325 | */ | ||
1326 | RLMT_STATIC SK_BOOL SkRlmtSelectBcRx( | ||
1327 | SK_AC *pAC, /* Adapter Context */ | ||
1328 | SK_IOC IoC, /* I/O Context */ | ||
1329 | SK_U32 Active, /* Active port */ | ||
1330 | SK_U32 PrefPort, /* Preferred port */ | ||
1331 | SK_U32 *pSelect) /* New active port */ | ||
1332 | { | ||
1333 | SK_U64 BcTimeStamp; | ||
1334 | SK_U32 i; | ||
1335 | SK_BOOL PortFound; | ||
1336 | |||
1337 | BcTimeStamp = 0; /* Not totally necessary, but feeling better. */ | ||
1338 | PortFound = SK_FALSE; | ||
1339 | |||
1340 | /* Select port with the latest TimeStamp. */ | ||
1341 | for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { | ||
1342 | |||
1343 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
1344 | ("TimeStamp Port %d (Down: %d, NoRx: %d): %08x %08x.\n", | ||
1345 | i, | ||
1346 | pAC->Rlmt.Port[i].PortDown, pAC->Rlmt.Port[i].PortNoRx, | ||
1347 | *((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_HI32), | ||
1348 | *((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_LO32))) | ||
1349 | |||
1350 | if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx) { | ||
1351 | if (!PortFound || pAC->Rlmt.Port[i].BcTimeStamp > BcTimeStamp) { | ||
1352 | BcTimeStamp = pAC->Rlmt.Port[i].BcTimeStamp; | ||
1353 | *pSelect = i; | ||
1354 | PortFound = SK_TRUE; | ||
1355 | } | ||
1356 | } | ||
1357 | } | ||
1358 | |||
1359 | if (PortFound) { | ||
1360 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
1361 | ("Port %d received the last broadcast.\n", *pSelect)) | ||
1362 | |||
1363 | /* Look if another port's time stamp is similar. */ | ||
1364 | for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { | ||
1365 | if (i == *pSelect) { | ||
1366 | continue; | ||
1367 | } | ||
1368 | if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx && | ||
1369 | (pAC->Rlmt.Port[i].BcTimeStamp > | ||
1370 | BcTimeStamp - SK_RLMT_BC_DELTA || | ||
1371 | pAC->Rlmt.Port[i].BcTimeStamp + | ||
1372 | SK_RLMT_BC_DELTA > BcTimeStamp)) { | ||
1373 | PortFound = SK_FALSE; | ||
1374 | |||
1375 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
1376 | ("Port %d received a broadcast at a similar time.\n", i)) | ||
1377 | break; | ||
1378 | } | ||
1379 | } | ||
1380 | } | ||
1381 | |||
1382 | #ifdef DEBUG | ||
1383 | if (PortFound) { | ||
1384 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
1385 | ("SK_RLMT_SELECT_BCRX found Port %d receiving the substantially " | ||
1386 | "latest broadcast (%u).\n", | ||
1387 | *pSelect, | ||
1388 | BcTimeStamp - pAC->Rlmt.Port[1 - *pSelect].BcTimeStamp)) | ||
1389 | } | ||
1390 | #endif /* DEBUG */ | ||
1391 | |||
1392 | return (PortFound); | ||
1393 | } /* SkRlmtSelectBcRx */ | ||
1394 | |||
1395 | |||
1396 | /****************************************************************************** | ||
1397 | * | ||
1398 | * SkRlmtSelectNotSuspect - select new active port, criteria 2 (CLP) | ||
1399 | * | ||
1400 | * Description: | ||
1401 | * This routine selects a good port (it is PortUp && !SuspectRx). | ||
1402 | * | ||
1403 | * Context: | ||
1404 | * runtime, pageable? | ||
1405 | * | ||
1406 | * Returns: | ||
1407 | * SK_BOOL | ||
1408 | */ | ||
1409 | RLMT_STATIC SK_BOOL SkRlmtSelectNotSuspect( | ||
1410 | SK_AC *pAC, /* Adapter Context */ | ||
1411 | SK_IOC IoC, /* I/O Context */ | ||
1412 | SK_U32 Active, /* Active port */ | ||
1413 | SK_U32 PrefPort, /* Preferred port */ | ||
1414 | SK_U32 *pSelect) /* New active port */ | ||
1415 | { | ||
1416 | SK_U32 i; | ||
1417 | SK_BOOL PortFound; | ||
1418 | |||
1419 | PortFound = SK_FALSE; | ||
1420 | |||
1421 | /* Select first port that is PortUp && !SuspectRx. */ | ||
1422 | for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { | ||
1423 | if (!pAC->Rlmt.Port[i].PortDown && | ||
1424 | !(pAC->Rlmt.Port[i].CheckingState & SK_RLMT_PCS_RX)) { | ||
1425 | *pSelect = i; | ||
1426 | if (!pAC->Rlmt.Port[Active].PortDown && | ||
1427 | !(pAC->Rlmt.Port[Active].CheckingState & SK_RLMT_PCS_RX)) { | ||
1428 | *pSelect = Active; | ||
1429 | } | ||
1430 | if (!pAC->Rlmt.Port[PrefPort].PortDown && | ||
1431 | !(pAC->Rlmt.Port[PrefPort].CheckingState & SK_RLMT_PCS_RX)) { | ||
1432 | *pSelect = PrefPort; | ||
1433 | } | ||
1434 | PortFound = SK_TRUE; | ||
1435 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
1436 | ("SK_RLMT_SELECT_NOTSUSPECT found Port %d up and not check RX.\n", | ||
1437 | *pSelect)) | ||
1438 | break; | ||
1439 | } | ||
1440 | } | ||
1441 | return (PortFound); | ||
1442 | } /* SkRlmtSelectNotSuspect */ | ||
1443 | |||
1444 | |||
1445 | /****************************************************************************** | ||
1446 | * | ||
1447 | * SkRlmtSelectUp - select new active port, criteria 3, 4 (CLP) | ||
1448 | * | ||
1449 | * Description: | ||
1450 | * This routine selects a port that is up. | ||
1451 | * | ||
1452 | * Context: | ||
1453 | * runtime, pageable? | ||
1454 | * | ||
1455 | * Returns: | ||
1456 | * SK_BOOL | ||
1457 | */ | ||
1458 | RLMT_STATIC SK_BOOL SkRlmtSelectUp( | ||
1459 | SK_AC *pAC, /* Adapter Context */ | ||
1460 | SK_IOC IoC, /* I/O Context */ | ||
1461 | SK_U32 Active, /* Active port */ | ||
1462 | SK_U32 PrefPort, /* Preferred port */ | ||
1463 | SK_U32 *pSelect, /* New active port */ | ||
1464 | SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */ | ||
1465 | { | ||
1466 | SK_U32 i; | ||
1467 | SK_BOOL PortFound; | ||
1468 | |||
1469 | PortFound = SK_FALSE; | ||
1470 | |||
1471 | /* Select first port that is PortUp. */ | ||
1472 | for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { | ||
1473 | if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_UP && | ||
1474 | pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) { | ||
1475 | *pSelect = i; | ||
1476 | if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_UP && | ||
1477 | pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) { | ||
1478 | *pSelect = Active; | ||
1479 | } | ||
1480 | if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_UP && | ||
1481 | pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) { | ||
1482 | *pSelect = PrefPort; | ||
1483 | } | ||
1484 | PortFound = SK_TRUE; | ||
1485 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
1486 | ("SK_RLMT_SELECT_UP found Port %d up.\n", *pSelect)) | ||
1487 | break; | ||
1488 | } | ||
1489 | } | ||
1490 | return (PortFound); | ||
1491 | } /* SkRlmtSelectUp */ | ||
1492 | |||
1493 | |||
1494 | /****************************************************************************** | ||
1495 | * | ||
1496 | * SkRlmtSelectGoingUp - select new active port, criteria 5, 6 (CLP) | ||
1497 | * | ||
1498 | * Description: | ||
1499 | * This routine selects the port that is going up for the longest time. | ||
1500 | * | ||
1501 | * Context: | ||
1502 | * runtime, pageable? | ||
1503 | * | ||
1504 | * Returns: | ||
1505 | * SK_BOOL | ||
1506 | */ | ||
1507 | RLMT_STATIC SK_BOOL SkRlmtSelectGoingUp( | ||
1508 | SK_AC *pAC, /* Adapter Context */ | ||
1509 | SK_IOC IoC, /* I/O Context */ | ||
1510 | SK_U32 Active, /* Active port */ | ||
1511 | SK_U32 PrefPort, /* Preferred port */ | ||
1512 | SK_U32 *pSelect, /* New active port */ | ||
1513 | SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */ | ||
1514 | { | ||
1515 | SK_U64 GuTimeStamp; | ||
1516 | SK_U32 i; | ||
1517 | SK_BOOL PortFound; | ||
1518 | |||
1519 | GuTimeStamp = 0; | ||
1520 | PortFound = SK_FALSE; | ||
1521 | |||
1522 | /* Select port that is PortGoingUp for the longest time. */ | ||
1523 | for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { | ||
1524 | if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP && | ||
1525 | pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) { | ||
1526 | GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp; | ||
1527 | *pSelect = i; | ||
1528 | PortFound = SK_TRUE; | ||
1529 | break; | ||
1530 | } | ||
1531 | } | ||
1532 | |||
1533 | if (!PortFound) { | ||
1534 | return (SK_FALSE); | ||
1535 | } | ||
1536 | |||
1537 | for (i = *pSelect + 1; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { | ||
1538 | if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP && | ||
1539 | pAC->Rlmt.Port[i].GuTimeStamp < GuTimeStamp && | ||
1540 | pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) { | ||
1541 | GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp; | ||
1542 | *pSelect = i; | ||
1543 | } | ||
1544 | } | ||
1545 | |||
1546 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
1547 | ("SK_RLMT_SELECT_GOINGUP found Port %d going up.\n", *pSelect)) | ||
1548 | return (SK_TRUE); | ||
1549 | } /* SkRlmtSelectGoingUp */ | ||
1550 | |||
1551 | |||
1552 | /****************************************************************************** | ||
1553 | * | ||
1554 | * SkRlmtSelectDown - select new active port, criteria 7, 8 (CLP) | ||
1555 | * | ||
1556 | * Description: | ||
1557 | * This routine selects a port that is down. | ||
1558 | * | ||
1559 | * Context: | ||
1560 | * runtime, pageable? | ||
1561 | * | ||
1562 | * Returns: | ||
1563 | * SK_BOOL | ||
1564 | */ | ||
1565 | RLMT_STATIC SK_BOOL SkRlmtSelectDown( | ||
1566 | SK_AC *pAC, /* Adapter Context */ | ||
1567 | SK_IOC IoC, /* I/O Context */ | ||
1568 | SK_U32 Active, /* Active port */ | ||
1569 | SK_U32 PrefPort, /* Preferred port */ | ||
1570 | SK_U32 *pSelect, /* New active port */ | ||
1571 | SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */ | ||
1572 | { | ||
1573 | SK_U32 i; | ||
1574 | SK_BOOL PortFound; | ||
1575 | |||
1576 | PortFound = SK_FALSE; | ||
1577 | |||
1578 | /* Select first port that is PortDown. */ | ||
1579 | for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { | ||
1580 | if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_DOWN && | ||
1581 | pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) { | ||
1582 | *pSelect = i; | ||
1583 | if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_DOWN && | ||
1584 | pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) { | ||
1585 | *pSelect = Active; | ||
1586 | } | ||
1587 | if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_DOWN && | ||
1588 | pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) { | ||
1589 | *pSelect = PrefPort; | ||
1590 | } | ||
1591 | PortFound = SK_TRUE; | ||
1592 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
1593 | ("SK_RLMT_SELECT_DOWN found Port %d down.\n", *pSelect)) | ||
1594 | break; | ||
1595 | } | ||
1596 | } | ||
1597 | return (PortFound); | ||
1598 | } /* SkRlmtSelectDown */ | ||
1599 | |||
1600 | |||
1601 | /****************************************************************************** | ||
1602 | * | ||
1603 | * SkRlmtCheckSwitch - select new active port and switch to it | ||
1604 | * | ||
1605 | * Description: | ||
1606 | * This routine decides which port should be the active one and queues | ||
1607 | * port switching if necessary. | ||
1608 | * | ||
1609 | * Context: | ||
1610 | * runtime, pageable? | ||
1611 | * | ||
1612 | * Returns: | ||
1613 | * Nothing. | ||
1614 | */ | ||
1615 | RLMT_STATIC void SkRlmtCheckSwitch( | ||
1616 | SK_AC *pAC, /* Adapter Context */ | ||
1617 | SK_IOC IoC, /* I/O Context */ | ||
1618 | SK_U32 NetIdx) /* Net index */ | ||
1619 | { | ||
1620 | SK_EVPARA Para; | ||
1621 | SK_U32 Active; | ||
1622 | SK_U32 PrefPort; | ||
1623 | SK_U32 i; | ||
1624 | SK_BOOL PortFound; | ||
1625 | |||
1626 | Active = pAC->Rlmt.Net[NetIdx].ActivePort; /* Index of active port. */ | ||
1627 | PrefPort = pAC->Rlmt.Net[NetIdx].PrefPort; /* Index of preferred port. */ | ||
1628 | PortFound = SK_FALSE; | ||
1629 | pAC->Rlmt.CheckSwitch = SK_FALSE; | ||
1630 | |||
1631 | #if 0 /* RW 2001/10/18 - active port becomes always prefered one */ | ||
1632 | if (pAC->Rlmt.Net[NetIdx].Preference == 0xFFFFFFFF) { /* Automatic */ | ||
1633 | /* disable auto-fail back */ | ||
1634 | PrefPort = Active; | ||
1635 | } | ||
1636 | #endif | ||
1637 | |||
1638 | if (pAC->Rlmt.Net[NetIdx].LinksUp == 0) { | ||
1639 | /* Last link went down - shut down the net. */ | ||
1640 | pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_DOWN; | ||
1641 | Para.Para32[0] = SK_RLMT_NET_DOWN_TEMP; | ||
1642 | Para.Para32[1] = NetIdx; | ||
1643 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para); | ||
1644 | |||
1645 | Para.Para32[0] = pAC->Rlmt.Net[NetIdx]. | ||
1646 | Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber; | ||
1647 | Para.Para32[1] = NetIdx; | ||
1648 | SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para); | ||
1649 | return; | ||
1650 | } /* pAC->Rlmt.LinksUp == 0 */ | ||
1651 | else if (pAC->Rlmt.Net[NetIdx].LinksUp == 1 && | ||
1652 | pAC->Rlmt.Net[NetIdx].RlmtState == SK_RLMT_RS_NET_DOWN) { | ||
1653 | /* First link came up - get the net up. */ | ||
1654 | pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_UP; | ||
1655 | |||
1656 | /* | ||
1657 | * If pAC->Rlmt.ActivePort != Para.Para32[0], | ||
1658 | * the DRV switches to the port that came up. | ||
1659 | */ | ||
1660 | for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) { | ||
1661 | if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) { | ||
1662 | if (!pAC->Rlmt.Net[NetIdx].Port[Active]->LinkDown) { | ||
1663 | i = Active; | ||
1664 | } | ||
1665 | if (!pAC->Rlmt.Net[NetIdx].Port[PrefPort]->LinkDown) { | ||
1666 | i = PrefPort; | ||
1667 | } | ||
1668 | PortFound = SK_TRUE; | ||
1669 | break; | ||
1670 | } | ||
1671 | } | ||
1672 | |||
1673 | if (PortFound) { | ||
1674 | Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber; | ||
1675 | Para.Para32[1] = NetIdx; | ||
1676 | SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para); | ||
1677 | |||
1678 | pAC->Rlmt.Net[NetIdx].ActivePort = i; | ||
1679 | Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber; | ||
1680 | Para.Para32[1] = NetIdx; | ||
1681 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_UP, Para); | ||
1682 | |||
1683 | if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 && | ||
1684 | (Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, | ||
1685 | pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber, | ||
1686 | SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx]. | ||
1687 | CurrentMacAddress, &SkRlmtMcAddr)) != NULL) { | ||
1688 | /* | ||
1689 | * Send announce packet to RLMT multicast address to force | ||
1690 | * switches to learn the new location of the logical MAC address. | ||
1691 | */ | ||
1692 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); | ||
1693 | } | ||
1694 | } | ||
1695 | else { | ||
1696 | SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E007, SKERR_RLMT_E007_MSG); | ||
1697 | } | ||
1698 | |||
1699 | return; | ||
1700 | } /* LinksUp == 1 && RlmtState == SK_RLMT_RS_NET_DOWN */ | ||
1701 | else { /* Cannot be reached in dual-net mode. */ | ||
1702 | Para.Para32[0] = Active; | ||
1703 | |||
1704 | /* | ||
1705 | * Preselection: | ||
1706 | * If RLMT Mode != CheckLinkState | ||
1707 | * select port that received a broadcast frame substantially later | ||
1708 | * than all other ports | ||
1709 | * else select first port that is not SuspectRx | ||
1710 | * else select first port that is PortUp | ||
1711 | * else select port that is PortGoingUp for the longest time | ||
1712 | * else select first port that is PortDown | ||
1713 | * else stop. | ||
1714 | * | ||
1715 | * For the preselected port: | ||
1716 | * If ActivePort is equal in quality, select ActivePort. | ||
1717 | * | ||
1718 | * If PrefPort is equal in quality, select PrefPort. | ||
1719 | * | ||
1720 | * If ActivePort != SelectedPort, | ||
1721 | * If old ActivePort is LinkDown, | ||
1722 | * SwitchHard | ||
1723 | * else | ||
1724 | * SwitchSoft | ||
1725 | */ | ||
1726 | /* check of ChgBcPrio flag added */ | ||
1727 | if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) && | ||
1728 | (!pAC->Rlmt.Net[0].ChgBcPrio)) { | ||
1729 | |||
1730 | if (!PortFound) { | ||
1731 | PortFound = SkRlmtSelectBcRx( | ||
1732 | pAC, IoC, Active, PrefPort, &Para.Para32[1]); | ||
1733 | } | ||
1734 | |||
1735 | if (!PortFound) { | ||
1736 | PortFound = SkRlmtSelectNotSuspect( | ||
1737 | pAC, IoC, Active, PrefPort, &Para.Para32[1]); | ||
1738 | } | ||
1739 | } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */ | ||
1740 | |||
1741 | /* with changed priority for last broadcast received */ | ||
1742 | if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) && | ||
1743 | (pAC->Rlmt.Net[0].ChgBcPrio)) { | ||
1744 | if (!PortFound) { | ||
1745 | PortFound = SkRlmtSelectNotSuspect( | ||
1746 | pAC, IoC, Active, PrefPort, &Para.Para32[1]); | ||
1747 | } | ||
1748 | |||
1749 | if (!PortFound) { | ||
1750 | PortFound = SkRlmtSelectBcRx( | ||
1751 | pAC, IoC, Active, PrefPort, &Para.Para32[1]); | ||
1752 | } | ||
1753 | } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */ | ||
1754 | |||
1755 | if (!PortFound) { | ||
1756 | PortFound = SkRlmtSelectUp( | ||
1757 | pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS); | ||
1758 | } | ||
1759 | |||
1760 | if (!PortFound) { | ||
1761 | PortFound = SkRlmtSelectUp( | ||
1762 | pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED); | ||
1763 | } | ||
1764 | |||
1765 | if (!PortFound) { | ||
1766 | PortFound = SkRlmtSelectGoingUp( | ||
1767 | pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS); | ||
1768 | } | ||
1769 | |||
1770 | if (!PortFound) { | ||
1771 | PortFound = SkRlmtSelectGoingUp( | ||
1772 | pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED); | ||
1773 | } | ||
1774 | |||
1775 | if (pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) { | ||
1776 | if (!PortFound) { | ||
1777 | PortFound = SkRlmtSelectDown(pAC, IoC, | ||
1778 | Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS); | ||
1779 | } | ||
1780 | |||
1781 | if (!PortFound) { | ||
1782 | PortFound = SkRlmtSelectDown(pAC, IoC, | ||
1783 | Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED); | ||
1784 | } | ||
1785 | } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */ | ||
1786 | |||
1787 | if (PortFound) { | ||
1788 | |||
1789 | if (Para.Para32[1] != Active) { | ||
1790 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
1791 | ("Active: %d, Para1: %d.\n", Active, Para.Para32[1])) | ||
1792 | pAC->Rlmt.Net[NetIdx].ActivePort = Para.Para32[1]; | ||
1793 | Para.Para32[0] = pAC->Rlmt.Net[NetIdx]. | ||
1794 | Port[Para.Para32[0]]->PortNumber; | ||
1795 | Para.Para32[1] = pAC->Rlmt.Net[NetIdx]. | ||
1796 | Port[Para.Para32[1]]->PortNumber; | ||
1797 | SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[1], SK_LED_ACTIVE); | ||
1798 | if (pAC->Rlmt.Port[Active].LinkDown) { | ||
1799 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_HARD, Para); | ||
1800 | } | ||
1801 | else { | ||
1802 | SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_STANDBY); | ||
1803 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_SOFT, Para); | ||
1804 | } | ||
1805 | Para.Para32[1] = NetIdx; | ||
1806 | Para.Para32[0] = | ||
1807 | pAC->Rlmt.Net[NetIdx].Port[Para.Para32[0]]->PortNumber; | ||
1808 | SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para); | ||
1809 | Para.Para32[0] = pAC->Rlmt.Net[NetIdx]. | ||
1810 | Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber; | ||
1811 | SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para); | ||
1812 | if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 && | ||
1813 | (Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, Para.Para32[0], | ||
1814 | SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx].CurrentMacAddress, | ||
1815 | &SkRlmtMcAddr)) != NULL) { | ||
1816 | /* | ||
1817 | * Send announce packet to RLMT multicast address to force | ||
1818 | * switches to learn the new location of the logical | ||
1819 | * MAC address. | ||
1820 | */ | ||
1821 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); | ||
1822 | } /* (Para.pParaPtr = SkRlmtBuildPacket(...)) != NULL */ | ||
1823 | } /* Para.Para32[1] != Active */ | ||
1824 | } /* PortFound */ | ||
1825 | else { | ||
1826 | SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E004, SKERR_RLMT_E004_MSG); | ||
1827 | } | ||
1828 | } /* LinksUp > 1 || LinksUp == 1 && RlmtState != SK_RLMT_RS_NET_DOWN */ | ||
1829 | return; | ||
1830 | } /* SkRlmtCheckSwitch */ | ||
1831 | |||
1832 | |||
1833 | /****************************************************************************** | ||
1834 | * | ||
1835 | * SkRlmtCheckSeg - Report if segmentation is detected | ||
1836 | * | ||
1837 | * Description: | ||
1838 | * This routine checks if the ports see different root bridges and reports | ||
1839 | * segmentation in such a case. | ||
1840 | * | ||
1841 | * Context: | ||
1842 | * runtime, pageable? | ||
1843 | * | ||
1844 | * Returns: | ||
1845 | * Nothing. | ||
1846 | */ | ||
1847 | RLMT_STATIC void SkRlmtCheckSeg( | ||
1848 | SK_AC *pAC, /* Adapter Context */ | ||
1849 | SK_IOC IoC, /* I/O Context */ | ||
1850 | SK_U32 NetIdx) /* Net number */ | ||
1851 | { | ||
1852 | SK_EVPARA Para; | ||
1853 | SK_RLMT_NET *pNet; | ||
1854 | SK_U32 i, j; | ||
1855 | SK_BOOL Equal; | ||
1856 | |||
1857 | pNet = &pAC->Rlmt.Net[NetIdx]; | ||
1858 | pNet->RootIdSet = SK_FALSE; | ||
1859 | Equal = SK_TRUE; | ||
1860 | |||
1861 | for (i = 0; i < pNet->NumPorts; i++) { | ||
1862 | if (pNet->Port[i]->LinkDown || !pNet->Port[i]->RootIdSet) { | ||
1863 | continue; | ||
1864 | } | ||
1865 | |||
1866 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP, | ||
1867 | ("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n", i, | ||
1868 | pNet->Port[i]->Root.Id[0], pNet->Port[i]->Root.Id[1], | ||
1869 | pNet->Port[i]->Root.Id[2], pNet->Port[i]->Root.Id[3], | ||
1870 | pNet->Port[i]->Root.Id[4], pNet->Port[i]->Root.Id[5], | ||
1871 | pNet->Port[i]->Root.Id[6], pNet->Port[i]->Root.Id[7])) | ||
1872 | |||
1873 | if (!pNet->RootIdSet) { | ||
1874 | pNet->Root = pNet->Port[i]->Root; | ||
1875 | pNet->RootIdSet = SK_TRUE; | ||
1876 | continue; | ||
1877 | } | ||
1878 | |||
1879 | for (j = 0; j < 8; j ++) { | ||
1880 | Equal &= pNet->Port[i]->Root.Id[j] == pNet->Root.Id[j]; | ||
1881 | if (!Equal) { | ||
1882 | break; | ||
1883 | } | ||
1884 | } | ||
1885 | |||
1886 | if (!Equal) { | ||
1887 | SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E005, SKERR_RLMT_E005_MSG); | ||
1888 | Para.Para32[0] = NetIdx; | ||
1889 | Para.Para32[1] = (SK_U32)-1; | ||
1890 | SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SEGMENTATION, Para); | ||
1891 | |||
1892 | pNet->CheckingState &= ~SK_RLMT_RCS_REPORT_SEG; | ||
1893 | |||
1894 | /* 2000-03-06 RA: New. */ | ||
1895 | Para.Para32[0] = NetIdx; | ||
1896 | Para.Para32[1] = (SK_U32)-1; | ||
1897 | SkTimerStart(pAC, IoC, &pNet->SegTimer, SK_RLMT_SEG_TO_VAL, | ||
1898 | SKGE_RLMT, SK_RLMT_SEG_TIM, Para); | ||
1899 | break; | ||
1900 | } | ||
1901 | } /* for (i = 0; i < pNet->NumPorts; i++) */ | ||
1902 | |||
1903 | /* 2000-03-06 RA: Moved here. */ | ||
1904 | /* Segmentation check not running anymore. */ | ||
1905 | pNet->CheckingState &= ~SK_RLMT_RCS_SEG; | ||
1906 | |||
1907 | } /* SkRlmtCheckSeg */ | ||
1908 | |||
1909 | |||
1910 | /****************************************************************************** | ||
1911 | * | ||
1912 | * SkRlmtPortStart - initialize port variables and start port | ||
1913 | * | ||
1914 | * Description: | ||
1915 | * This routine initializes a port's variables and issues a PORT_START | ||
1916 | * to the HWAC module. This handles retries if the start fails or the | ||
1917 | * link eventually goes down. | ||
1918 | * | ||
1919 | * Context: | ||
1920 | * runtime, pageable? | ||
1921 | * | ||
1922 | * Returns: | ||
1923 | * Nothing | ||
1924 | */ | ||
1925 | RLMT_STATIC void SkRlmtPortStart( | ||
1926 | SK_AC *pAC, /* Adapter Context */ | ||
1927 | SK_IOC IoC, /* I/O Context */ | ||
1928 | SK_U32 PortNumber) /* Port number */ | ||
1929 | { | ||
1930 | SK_EVPARA Para; | ||
1931 | |||
1932 | pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_LINK_DOWN; | ||
1933 | pAC->Rlmt.Port[PortNumber].PortStarted = SK_TRUE; | ||
1934 | pAC->Rlmt.Port[PortNumber].LinkDown = SK_TRUE; | ||
1935 | pAC->Rlmt.Port[PortNumber].PortDown = SK_TRUE; | ||
1936 | pAC->Rlmt.Port[PortNumber].CheckingState = 0; | ||
1937 | pAC->Rlmt.Port[PortNumber].RootIdSet = SK_FALSE; | ||
1938 | Para.Para32[0] = PortNumber; | ||
1939 | Para.Para32[1] = (SK_U32)-1; | ||
1940 | SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); | ||
1941 | } /* SkRlmtPortStart */ | ||
1942 | |||
1943 | |||
1944 | /****************************************************************************** | ||
1945 | * | ||
1946 | * SkRlmtEvtPortStartTim - PORT_START_TIM | ||
1947 | * | ||
1948 | * Description: | ||
1949 | * This routine handles PORT_START_TIM events. | ||
1950 | * | ||
1951 | * Context: | ||
1952 | * runtime, pageable? | ||
1953 | * may be called after SK_INIT_IO | ||
1954 | * | ||
1955 | * Returns: | ||
1956 | * Nothing | ||
1957 | */ | ||
1958 | RLMT_STATIC void SkRlmtEvtPortStartTim( | ||
1959 | SK_AC *pAC, /* Adapter Context */ | ||
1960 | SK_IOC IoC, /* I/O Context */ | ||
1961 | SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ | ||
1962 | { | ||
1963 | SK_U32 i; | ||
1964 | |||
1965 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
1966 | ("SK_RLMT_PORTSTART_TIMEOUT Port %d Event BEGIN.\n", Para.Para32[0])) | ||
1967 | |||
1968 | if (Para.Para32[1] != (SK_U32)-1) { | ||
1969 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
1970 | ("Bad Parameter.\n")) | ||
1971 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
1972 | ("SK_RLMT_PORTSTART_TIMEOUT Event EMPTY.\n")) | ||
1973 | return; | ||
1974 | } | ||
1975 | |||
1976 | /* | ||
1977 | * Used to start non-preferred ports if the preferred one | ||
1978 | * does not come up. | ||
1979 | * This timeout needs only be set when starting the first | ||
1980 | * (preferred) port. | ||
1981 | */ | ||
1982 | if (pAC->Rlmt.Port[Para.Para32[0]].LinkDown) { | ||
1983 | /* PORT_START failed. */ | ||
1984 | for (i = 0; i < pAC->Rlmt.Port[Para.Para32[0]].Net->NumPorts; i++) { | ||
1985 | if (!pAC->Rlmt.Port[Para.Para32[0]].Net->Port[i]->PortStarted) { | ||
1986 | SkRlmtPortStart(pAC, IoC, | ||
1987 | pAC->Rlmt.Port[Para.Para32[0]].Net->Port[i]->PortNumber); | ||
1988 | } | ||
1989 | } | ||
1990 | } | ||
1991 | |||
1992 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
1993 | ("SK_RLMT_PORTSTART_TIMEOUT Event END.\n")) | ||
1994 | } /* SkRlmtEvtPortStartTim */ | ||
1995 | |||
1996 | |||
1997 | /****************************************************************************** | ||
1998 | * | ||
1999 | * SkRlmtEvtLinkUp - LINK_UP | ||
2000 | * | ||
2001 | * Description: | ||
2002 | * This routine handles LLINK_UP events. | ||
2003 | * | ||
2004 | * Context: | ||
2005 | * runtime, pageable? | ||
2006 | * may be called after SK_INIT_IO | ||
2007 | * | ||
2008 | * Returns: | ||
2009 | * Nothing | ||
2010 | */ | ||
2011 | RLMT_STATIC void SkRlmtEvtLinkUp( | ||
2012 | SK_AC *pAC, /* Adapter Context */ | ||
2013 | SK_IOC IoC, /* I/O Context */ | ||
2014 | SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 Undefined */ | ||
2015 | { | ||
2016 | SK_U32 i; | ||
2017 | SK_RLMT_PORT *pRPort; | ||
2018 | SK_EVPARA Para2; | ||
2019 | |||
2020 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2021 | ("SK_RLMT_LINK_UP Port %d Event BEGIN.\n", Para.Para32[0])) | ||
2022 | |||
2023 | pRPort = &pAC->Rlmt.Port[Para.Para32[0]]; | ||
2024 | if (!pRPort->PortStarted) { | ||
2025 | SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E008, SKERR_RLMT_E008_MSG); | ||
2026 | |||
2027 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2028 | ("SK_RLMT_LINK_UP Event EMPTY.\n")) | ||
2029 | return; | ||
2030 | } | ||
2031 | |||
2032 | if (!pRPort->LinkDown) { | ||
2033 | /* RA;:;: Any better solution? */ | ||
2034 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2035 | ("SK_RLMT_LINK_UP Event EMPTY.\n")) | ||
2036 | return; | ||
2037 | } | ||
2038 | |||
2039 | SkTimerStop(pAC, IoC, &pRPort->UpTimer); | ||
2040 | SkTimerStop(pAC, IoC, &pRPort->DownRxTimer); | ||
2041 | SkTimerStop(pAC, IoC, &pRPort->DownTxTimer); | ||
2042 | |||
2043 | /* Do something if timer already fired? */ | ||
2044 | |||
2045 | pRPort->LinkDown = SK_FALSE; | ||
2046 | pRPort->PortState = SK_RLMT_PS_GOING_UP; | ||
2047 | pRPort->GuTimeStamp = SkOsGetTime(pAC); | ||
2048 | pRPort->BcTimeStamp = 0; | ||
2049 | pRPort->Net->LinksUp++; | ||
2050 | if (pRPort->Net->LinksUp == 1) { | ||
2051 | SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_ACTIVE); | ||
2052 | } | ||
2053 | else { | ||
2054 | SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_STANDBY); | ||
2055 | } | ||
2056 | |||
2057 | for (i = 0; i < pRPort->Net->NumPorts; i++) { | ||
2058 | if (!pRPort->Net->Port[i]->PortStarted) { | ||
2059 | SkRlmtPortStart(pAC, IoC, pRPort->Net->Port[i]->PortNumber); | ||
2060 | } | ||
2061 | } | ||
2062 | |||
2063 | SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); | ||
2064 | |||
2065 | if (pRPort->Net->LinksUp >= 2) { | ||
2066 | if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) { | ||
2067 | /* Build the check chain. */ | ||
2068 | SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber); | ||
2069 | } | ||
2070 | } | ||
2071 | |||
2072 | /* If the first link comes up, start the periodical RLMT timeout. */ | ||
2073 | if (pRPort->Net->NumPorts > 1 && pRPort->Net->LinksUp == 1 && | ||
2074 | (pRPort->Net->RlmtMode & SK_RLMT_CHECK_OTHERS) != 0) { | ||
2075 | Para2.Para32[0] = pRPort->Net->NetNumber; | ||
2076 | Para2.Para32[1] = (SK_U32)-1; | ||
2077 | SkTimerStart(pAC, IoC, &pRPort->Net->LocTimer, | ||
2078 | pRPort->Net->TimeoutValue, SKGE_RLMT, SK_RLMT_TIM, Para2); | ||
2079 | } | ||
2080 | |||
2081 | Para2 = Para; | ||
2082 | Para2.Para32[1] = (SK_U32)-1; | ||
2083 | SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL, | ||
2084 | SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para2); | ||
2085 | |||
2086 | /* Later: if (pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_LOC_LINK) && */ | ||
2087 | if ((pRPort->Net->RlmtMode & SK_RLMT_TRANSPARENT) == 0 && | ||
2088 | (pRPort->Net->RlmtMode & SK_RLMT_CHECK_LINK) != 0 && | ||
2089 | (Para2.pParaPtr = | ||
2090 | SkRlmtBuildPacket(pAC, IoC, Para.Para32[0], SK_PACKET_ANNOUNCE, | ||
2091 | &pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress, &SkRlmtMcAddr) | ||
2092 | ) != NULL) { | ||
2093 | /* Send "new" packet to RLMT multicast address. */ | ||
2094 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2); | ||
2095 | } | ||
2096 | |||
2097 | if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_SEG) { | ||
2098 | if ((Para2.pParaPtr = | ||
2099 | SkRlmtBuildSpanningTreePacket(pAC, IoC, Para.Para32[0])) != NULL) { | ||
2100 | pAC->Rlmt.Port[Para.Para32[0]].RootIdSet = SK_FALSE; | ||
2101 | pRPort->Net->CheckingState |= | ||
2102 | SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG; | ||
2103 | |||
2104 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2); | ||
2105 | |||
2106 | Para.Para32[1] = (SK_U32)-1; | ||
2107 | SkTimerStart(pAC, IoC, &pRPort->Net->SegTimer, | ||
2108 | SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para); | ||
2109 | } | ||
2110 | } | ||
2111 | |||
2112 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2113 | ("SK_RLMT_LINK_UP Event END.\n")) | ||
2114 | } /* SkRlmtEvtLinkUp */ | ||
2115 | |||
2116 | |||
2117 | /****************************************************************************** | ||
2118 | * | ||
2119 | * SkRlmtEvtPortUpTim - PORT_UP_TIM | ||
2120 | * | ||
2121 | * Description: | ||
2122 | * This routine handles PORT_UP_TIM events. | ||
2123 | * | ||
2124 | * Context: | ||
2125 | * runtime, pageable? | ||
2126 | * may be called after SK_INIT_IO | ||
2127 | * | ||
2128 | * Returns: | ||
2129 | * Nothing | ||
2130 | */ | ||
2131 | RLMT_STATIC void SkRlmtEvtPortUpTim( | ||
2132 | SK_AC *pAC, /* Adapter Context */ | ||
2133 | SK_IOC IoC, /* I/O Context */ | ||
2134 | SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ | ||
2135 | { | ||
2136 | SK_RLMT_PORT *pRPort; | ||
2137 | |||
2138 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2139 | ("SK_RLMT_PORTUP_TIM Port %d Event BEGIN.\n", Para.Para32[0])) | ||
2140 | |||
2141 | if (Para.Para32[1] != (SK_U32)-1) { | ||
2142 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2143 | ("Bad Parameter.\n")) | ||
2144 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2145 | ("SK_RLMT_PORTUP_TIM Event EMPTY.\n")) | ||
2146 | return; | ||
2147 | } | ||
2148 | |||
2149 | pRPort = &pAC->Rlmt.Port[Para.Para32[0]]; | ||
2150 | if (pRPort->LinkDown || (pRPort->PortState == SK_RLMT_PS_UP)) { | ||
2151 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2152 | ("SK_RLMT_PORTUP_TIM Port %d Event EMPTY.\n", Para.Para32[0])) | ||
2153 | return; | ||
2154 | } | ||
2155 | |||
2156 | pRPort->PortDown = SK_FALSE; | ||
2157 | pRPort->PortState = SK_RLMT_PS_UP; | ||
2158 | pRPort->Net->PortsUp++; | ||
2159 | if (pRPort->Net->RlmtState != SK_RLMT_RS_INIT) { | ||
2160 | if (pAC->Rlmt.NumNets <= 1) { | ||
2161 | SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); | ||
2162 | } | ||
2163 | SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_UP, Para); | ||
2164 | } | ||
2165 | |||
2166 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2167 | ("SK_RLMT_PORTUP_TIM Event END.\n")) | ||
2168 | } /* SkRlmtEvtPortUpTim */ | ||
2169 | |||
2170 | |||
2171 | /****************************************************************************** | ||
2172 | * | ||
2173 | * SkRlmtEvtPortDownTim - PORT_DOWN_* | ||
2174 | * | ||
2175 | * Description: | ||
2176 | * This routine handles PORT_DOWN_* events. | ||
2177 | * | ||
2178 | * Context: | ||
2179 | * runtime, pageable? | ||
2180 | * may be called after SK_INIT_IO | ||
2181 | * | ||
2182 | * Returns: | ||
2183 | * Nothing | ||
2184 | */ | ||
2185 | RLMT_STATIC void SkRlmtEvtPortDownX( | ||
2186 | SK_AC *pAC, /* Adapter Context */ | ||
2187 | SK_IOC IoC, /* I/O Context */ | ||
2188 | SK_U32 Event, /* Event code */ | ||
2189 | SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ | ||
2190 | { | ||
2191 | SK_RLMT_PORT *pRPort; | ||
2192 | |||
2193 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2194 | ("SK_RLMT_PORTDOWN* Port %d Event (%d) BEGIN.\n", | ||
2195 | Para.Para32[0], Event)) | ||
2196 | |||
2197 | if (Para.Para32[1] != (SK_U32)-1) { | ||
2198 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2199 | ("Bad Parameter.\n")) | ||
2200 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2201 | ("SK_RLMT_PORTDOWN* Event EMPTY.\n")) | ||
2202 | return; | ||
2203 | } | ||
2204 | |||
2205 | pRPort = &pAC->Rlmt.Port[Para.Para32[0]]; | ||
2206 | if (!pRPort->PortStarted || (Event == SK_RLMT_PORTDOWN_TX_TIM && | ||
2207 | !(pRPort->CheckingState & SK_RLMT_PCS_TX))) { | ||
2208 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2209 | ("SK_RLMT_PORTDOWN* Event (%d) EMPTY.\n", Event)) | ||
2210 | return; | ||
2211 | } | ||
2212 | |||
2213 | /* Stop port's timers. */ | ||
2214 | SkTimerStop(pAC, IoC, &pRPort->UpTimer); | ||
2215 | SkTimerStop(pAC, IoC, &pRPort->DownRxTimer); | ||
2216 | SkTimerStop(pAC, IoC, &pRPort->DownTxTimer); | ||
2217 | |||
2218 | if (pRPort->PortState != SK_RLMT_PS_LINK_DOWN) { | ||
2219 | pRPort->PortState = SK_RLMT_PS_DOWN; | ||
2220 | } | ||
2221 | |||
2222 | if (!pRPort->PortDown) { | ||
2223 | pRPort->Net->PortsUp--; | ||
2224 | pRPort->PortDown = SK_TRUE; | ||
2225 | SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_DOWN, Para); | ||
2226 | } | ||
2227 | |||
2228 | pRPort->PacketsPerTimeSlot = 0; | ||
2229 | /* pRPort->DataPacketsPerTimeSlot = 0; */ | ||
2230 | pRPort->BpduPacketsPerTimeSlot = 0; | ||
2231 | pRPort->BcTimeStamp = 0; | ||
2232 | |||
2233 | /* | ||
2234 | * RA;:;: To be checked: | ||
2235 | * - actions at RLMT_STOP: We should not switch anymore. | ||
2236 | */ | ||
2237 | if (pRPort->Net->RlmtState != SK_RLMT_RS_INIT) { | ||
2238 | if (Para.Para32[0] == | ||
2239 | pRPort->Net->Port[pRPort->Net->ActivePort]->PortNumber) { | ||
2240 | /* Active Port went down. */ | ||
2241 | SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); | ||
2242 | } | ||
2243 | } | ||
2244 | |||
2245 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2246 | ("SK_RLMT_PORTDOWN* Event (%d) END.\n", Event)) | ||
2247 | } /* SkRlmtEvtPortDownX */ | ||
2248 | |||
2249 | |||
2250 | /****************************************************************************** | ||
2251 | * | ||
2252 | * SkRlmtEvtLinkDown - LINK_DOWN | ||
2253 | * | ||
2254 | * Description: | ||
2255 | * This routine handles LINK_DOWN events. | ||
2256 | * | ||
2257 | * Context: | ||
2258 | * runtime, pageable? | ||
2259 | * may be called after SK_INIT_IO | ||
2260 | * | ||
2261 | * Returns: | ||
2262 | * Nothing | ||
2263 | */ | ||
2264 | RLMT_STATIC void SkRlmtEvtLinkDown( | ||
2265 | SK_AC *pAC, /* Adapter Context */ | ||
2266 | SK_IOC IoC, /* I/O Context */ | ||
2267 | SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 Undefined */ | ||
2268 | { | ||
2269 | SK_RLMT_PORT *pRPort; | ||
2270 | |||
2271 | pRPort = &pAC->Rlmt.Port[Para.Para32[0]]; | ||
2272 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2273 | ("SK_RLMT_LINK_DOWN Port %d Event BEGIN.\n", Para.Para32[0])) | ||
2274 | |||
2275 | if (!pAC->Rlmt.Port[Para.Para32[0]].LinkDown) { | ||
2276 | pRPort->Net->LinksUp--; | ||
2277 | pRPort->LinkDown = SK_TRUE; | ||
2278 | pRPort->PortState = SK_RLMT_PS_LINK_DOWN; | ||
2279 | SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_OFF); | ||
2280 | |||
2281 | if ((pRPort->Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) != 0) { | ||
2282 | /* Build the check chain. */ | ||
2283 | SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber); | ||
2284 | } | ||
2285 | |||
2286 | /* Ensure that port is marked down. */ | ||
2287 | Para.Para32[1] = -1; | ||
2288 | (void)SkRlmtEvent(pAC, IoC, SK_RLMT_PORTDOWN, Para); | ||
2289 | } | ||
2290 | |||
2291 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2292 | ("SK_RLMT_LINK_DOWN Event END.\n")) | ||
2293 | } /* SkRlmtEvtLinkDown */ | ||
2294 | |||
2295 | |||
2296 | /****************************************************************************** | ||
2297 | * | ||
2298 | * SkRlmtEvtPortAddr - PORT_ADDR | ||
2299 | * | ||
2300 | * Description: | ||
2301 | * This routine handles PORT_ADDR events. | ||
2302 | * | ||
2303 | * Context: | ||
2304 | * runtime, pageable? | ||
2305 | * may be called after SK_INIT_IO | ||
2306 | * | ||
2307 | * Returns: | ||
2308 | * Nothing | ||
2309 | */ | ||
2310 | RLMT_STATIC void SkRlmtEvtPortAddr( | ||
2311 | SK_AC *pAC, /* Adapter Context */ | ||
2312 | SK_IOC IoC, /* I/O Context */ | ||
2313 | SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ | ||
2314 | { | ||
2315 | SK_U32 i, j; | ||
2316 | SK_RLMT_PORT *pRPort; | ||
2317 | SK_MAC_ADDR *pOldMacAddr; | ||
2318 | SK_MAC_ADDR *pNewMacAddr; | ||
2319 | |||
2320 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2321 | ("SK_RLMT_PORT_ADDR Port %d Event BEGIN.\n", Para.Para32[0])) | ||
2322 | |||
2323 | if (Para.Para32[1] != (SK_U32)-1) { | ||
2324 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2325 | ("Bad Parameter.\n")) | ||
2326 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2327 | ("SK_RLMT_PORT_ADDR Event EMPTY.\n")) | ||
2328 | return; | ||
2329 | } | ||
2330 | |||
2331 | /* Port's physical MAC address changed. */ | ||
2332 | pOldMacAddr = &pAC->Addr.Port[Para.Para32[0]].PreviousMacAddress; | ||
2333 | pNewMacAddr = &pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress; | ||
2334 | |||
2335 | /* | ||
2336 | * NOTE: This is not scalable for solutions where ports are | ||
2337 | * checked remotely. There, we need to send an RLMT | ||
2338 | * address change packet - and how do we ensure delivery? | ||
2339 | */ | ||
2340 | for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { | ||
2341 | pRPort = &pAC->Rlmt.Port[i]; | ||
2342 | for (j = 0; j < pRPort->PortsChecked; j++) { | ||
2343 | if (SK_ADDR_EQUAL( | ||
2344 | pRPort->PortCheck[j].CheckAddr.a, pOldMacAddr->a)) { | ||
2345 | pRPort->PortCheck[j].CheckAddr = *pNewMacAddr; | ||
2346 | } | ||
2347 | } | ||
2348 | } | ||
2349 | |||
2350 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2351 | ("SK_RLMT_PORT_ADDR Event END.\n")) | ||
2352 | } /* SkRlmtEvtPortAddr */ | ||
2353 | |||
2354 | |||
2355 | /****************************************************************************** | ||
2356 | * | ||
2357 | * SkRlmtEvtStart - START | ||
2358 | * | ||
2359 | * Description: | ||
2360 | * This routine handles START events. | ||
2361 | * | ||
2362 | * Context: | ||
2363 | * runtime, pageable? | ||
2364 | * may be called after SK_INIT_IO | ||
2365 | * | ||
2366 | * Returns: | ||
2367 | * Nothing | ||
2368 | */ | ||
2369 | RLMT_STATIC void SkRlmtEvtStart( | ||
2370 | SK_AC *pAC, /* Adapter Context */ | ||
2371 | SK_IOC IoC, /* I/O Context */ | ||
2372 | SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ | ||
2373 | { | ||
2374 | SK_EVPARA Para2; | ||
2375 | SK_U32 PortIdx; | ||
2376 | SK_U32 PortNumber; | ||
2377 | |||
2378 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2379 | ("SK_RLMT_START Net %d Event BEGIN.\n", Para.Para32[0])) | ||
2380 | |||
2381 | if (Para.Para32[1] != (SK_U32)-1) { | ||
2382 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2383 | ("Bad Parameter.\n")) | ||
2384 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2385 | ("SK_RLMT_START Event EMPTY.\n")) | ||
2386 | return; | ||
2387 | } | ||
2388 | |||
2389 | if (Para.Para32[0] >= pAC->Rlmt.NumNets) { | ||
2390 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2391 | ("Bad NetNumber %d.\n", Para.Para32[0])) | ||
2392 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2393 | ("SK_RLMT_START Event EMPTY.\n")) | ||
2394 | return; | ||
2395 | } | ||
2396 | |||
2397 | if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState != SK_RLMT_RS_INIT) { | ||
2398 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2399 | ("SK_RLMT_START Event EMPTY.\n")) | ||
2400 | return; | ||
2401 | } | ||
2402 | |||
2403 | if (pAC->Rlmt.NetsStarted >= pAC->Rlmt.NumNets) { | ||
2404 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2405 | ("All nets should have been started.\n")) | ||
2406 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2407 | ("SK_RLMT_START Event EMPTY.\n")) | ||
2408 | return; | ||
2409 | } | ||
2410 | |||
2411 | if (pAC->Rlmt.Net[Para.Para32[0]].PrefPort >= | ||
2412 | pAC->Rlmt.Net[Para.Para32[0]].NumPorts) { | ||
2413 | SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E009, SKERR_RLMT_E009_MSG); | ||
2414 | |||
2415 | /* Change PrefPort to internal default. */ | ||
2416 | Para2.Para32[0] = 0xFFFFFFFF; | ||
2417 | Para2.Para32[1] = Para.Para32[0]; | ||
2418 | (void)SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE, Para2); | ||
2419 | } | ||
2420 | |||
2421 | PortIdx = pAC->Rlmt.Net[Para.Para32[0]].PrefPort; | ||
2422 | PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[PortIdx]->PortNumber; | ||
2423 | |||
2424 | pAC->Rlmt.Net[Para.Para32[0]].LinksUp = 0; | ||
2425 | pAC->Rlmt.Net[Para.Para32[0]].PortsUp = 0; | ||
2426 | pAC->Rlmt.Net[Para.Para32[0]].CheckingState = 0; | ||
2427 | pAC->Rlmt.Net[Para.Para32[0]].RlmtState = SK_RLMT_RS_NET_DOWN; | ||
2428 | |||
2429 | /* Start preferred port. */ | ||
2430 | SkRlmtPortStart(pAC, IoC, PortNumber); | ||
2431 | |||
2432 | /* Start Timer (for first port only). */ | ||
2433 | Para2.Para32[0] = PortNumber; | ||
2434 | Para2.Para32[1] = (SK_U32)-1; | ||
2435 | SkTimerStart(pAC, IoC, &pAC->Rlmt.Port[PortNumber].UpTimer, | ||
2436 | SK_RLMT_PORTSTART_TIM_VAL, SKGE_RLMT, SK_RLMT_PORTSTART_TIM, Para2); | ||
2437 | |||
2438 | pAC->Rlmt.NetsStarted++; | ||
2439 | |||
2440 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2441 | ("SK_RLMT_START Event END.\n")) | ||
2442 | } /* SkRlmtEvtStart */ | ||
2443 | |||
2444 | |||
2445 | /****************************************************************************** | ||
2446 | * | ||
2447 | * SkRlmtEvtStop - STOP | ||
2448 | * | ||
2449 | * Description: | ||
2450 | * This routine handles STOP events. | ||
2451 | * | ||
2452 | * Context: | ||
2453 | * runtime, pageable? | ||
2454 | * may be called after SK_INIT_IO | ||
2455 | * | ||
2456 | * Returns: | ||
2457 | * Nothing | ||
2458 | */ | ||
2459 | RLMT_STATIC void SkRlmtEvtStop( | ||
2460 | SK_AC *pAC, /* Adapter Context */ | ||
2461 | SK_IOC IoC, /* I/O Context */ | ||
2462 | SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ | ||
2463 | { | ||
2464 | SK_EVPARA Para2; | ||
2465 | SK_U32 PortNumber; | ||
2466 | SK_U32 i; | ||
2467 | |||
2468 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2469 | ("SK_RLMT_STOP Net %d Event BEGIN.\n", Para.Para32[0])) | ||
2470 | |||
2471 | if (Para.Para32[1] != (SK_U32)-1) { | ||
2472 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2473 | ("Bad Parameter.\n")) | ||
2474 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2475 | ("SK_RLMT_STOP Event EMPTY.\n")) | ||
2476 | return; | ||
2477 | } | ||
2478 | |||
2479 | if (Para.Para32[0] >= pAC->Rlmt.NumNets) { | ||
2480 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2481 | ("Bad NetNumber %d.\n", Para.Para32[0])) | ||
2482 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2483 | ("SK_RLMT_STOP Event EMPTY.\n")) | ||
2484 | return; | ||
2485 | } | ||
2486 | |||
2487 | if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState == SK_RLMT_RS_INIT) { | ||
2488 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2489 | ("SK_RLMT_STOP Event EMPTY.\n")) | ||
2490 | return; | ||
2491 | } | ||
2492 | |||
2493 | if (pAC->Rlmt.NetsStarted == 0) { | ||
2494 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2495 | ("All nets are stopped.\n")) | ||
2496 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2497 | ("SK_RLMT_STOP Event EMPTY.\n")) | ||
2498 | return; | ||
2499 | } | ||
2500 | |||
2501 | /* Stop RLMT timers. */ | ||
2502 | SkTimerStop(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].LocTimer); | ||
2503 | SkTimerStop(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].SegTimer); | ||
2504 | |||
2505 | /* Stop net. */ | ||
2506 | pAC->Rlmt.Net[Para.Para32[0]].RlmtState = SK_RLMT_RS_INIT; | ||
2507 | pAC->Rlmt.Net[Para.Para32[0]].RootIdSet = SK_FALSE; | ||
2508 | Para2.Para32[0] = SK_RLMT_NET_DOWN_FINAL; | ||
2509 | Para2.Para32[1] = Para.Para32[0]; /* Net# */ | ||
2510 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para2); | ||
2511 | |||
2512 | /* Stop ports. */ | ||
2513 | for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) { | ||
2514 | PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber; | ||
2515 | if (pAC->Rlmt.Port[PortNumber].PortState != SK_RLMT_PS_INIT) { | ||
2516 | SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].UpTimer); | ||
2517 | SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].DownRxTimer); | ||
2518 | SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].DownTxTimer); | ||
2519 | |||
2520 | pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_INIT; | ||
2521 | pAC->Rlmt.Port[PortNumber].RootIdSet = SK_FALSE; | ||
2522 | pAC->Rlmt.Port[PortNumber].PortStarted = SK_FALSE; | ||
2523 | Para2.Para32[0] = PortNumber; | ||
2524 | Para2.Para32[1] = (SK_U32)-1; | ||
2525 | SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para2); | ||
2526 | } | ||
2527 | } | ||
2528 | |||
2529 | pAC->Rlmt.NetsStarted--; | ||
2530 | |||
2531 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2532 | ("SK_RLMT_STOP Event END.\n")) | ||
2533 | } /* SkRlmtEvtStop */ | ||
2534 | |||
2535 | |||
2536 | /****************************************************************************** | ||
2537 | * | ||
2538 | * SkRlmtEvtTim - TIM | ||
2539 | * | ||
2540 | * Description: | ||
2541 | * This routine handles TIM events. | ||
2542 | * | ||
2543 | * Context: | ||
2544 | * runtime, pageable? | ||
2545 | * may be called after SK_INIT_IO | ||
2546 | * | ||
2547 | * Returns: | ||
2548 | * Nothing | ||
2549 | */ | ||
2550 | RLMT_STATIC void SkRlmtEvtTim( | ||
2551 | SK_AC *pAC, /* Adapter Context */ | ||
2552 | SK_IOC IoC, /* I/O Context */ | ||
2553 | SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ | ||
2554 | { | ||
2555 | SK_RLMT_PORT *pRPort; | ||
2556 | SK_U32 Timeout; | ||
2557 | SK_U32 NewTimeout; | ||
2558 | SK_U32 PortNumber; | ||
2559 | SK_U32 i; | ||
2560 | |||
2561 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2562 | ("SK_RLMT_TIM Event BEGIN.\n")) | ||
2563 | |||
2564 | if (Para.Para32[1] != (SK_U32)-1) { | ||
2565 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2566 | ("Bad Parameter.\n")) | ||
2567 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2568 | ("SK_RLMT_TIM Event EMPTY.\n")) | ||
2569 | return; | ||
2570 | } | ||
2571 | |||
2572 | if ((pAC->Rlmt.Net[Para.Para32[0]].RlmtMode & SK_RLMT_CHECK_OTHERS) == 0 || | ||
2573 | pAC->Rlmt.Net[Para.Para32[0]].LinksUp == 0) { | ||
2574 | /* Mode changed or all links down: No more link checking. */ | ||
2575 | return; | ||
2576 | } | ||
2577 | |||
2578 | #if 0 | ||
2579 | pAC->Rlmt.SwitchCheckCounter--; | ||
2580 | if (pAC->Rlmt.SwitchCheckCounter == 0) { | ||
2581 | pAC->Rlmt.SwitchCheckCounter; | ||
2582 | } | ||
2583 | #endif /* 0 */ | ||
2584 | |||
2585 | NewTimeout = SK_RLMT_DEF_TO_VAL; | ||
2586 | for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) { | ||
2587 | PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber; | ||
2588 | pRPort = &pAC->Rlmt.Port[PortNumber]; | ||
2589 | if (!pRPort->LinkDown) { | ||
2590 | Timeout = SkRlmtCheckPort(pAC, IoC, PortNumber); | ||
2591 | if (Timeout < NewTimeout) { | ||
2592 | NewTimeout = Timeout; | ||
2593 | } | ||
2594 | |||
2595 | /* | ||
2596 | * These counters should be set to 0 for all ports before the | ||
2597 | * first frame is sent in the next loop. | ||
2598 | */ | ||
2599 | pRPort->PacketsPerTimeSlot = 0; | ||
2600 | /* pRPort->DataPacketsPerTimeSlot = 0; */ | ||
2601 | pRPort->BpduPacketsPerTimeSlot = 0; | ||
2602 | } | ||
2603 | } | ||
2604 | pAC->Rlmt.Net[Para.Para32[0]].TimeoutValue = NewTimeout; | ||
2605 | |||
2606 | if (pAC->Rlmt.Net[Para.Para32[0]].LinksUp > 1) { | ||
2607 | /* | ||
2608 | * If checking remote ports, also send packets if | ||
2609 | * (LinksUp == 1) && | ||
2610 | * this port checks at least one (remote) port. | ||
2611 | */ | ||
2612 | |||
2613 | /* | ||
2614 | * Must be new loop, as SkRlmtCheckPort can request to | ||
2615 | * check segmentation when e.g. checking the last port. | ||
2616 | */ | ||
2617 | for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) { | ||
2618 | if (!pAC->Rlmt.Net[Para.Para32[0]].Port[i]->LinkDown) { | ||
2619 | SkRlmtSend(pAC, IoC, | ||
2620 | pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber); | ||
2621 | } | ||
2622 | } | ||
2623 | } | ||
2624 | |||
2625 | SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].LocTimer, | ||
2626 | pAC->Rlmt.Net[Para.Para32[0]].TimeoutValue, SKGE_RLMT, SK_RLMT_TIM, | ||
2627 | Para); | ||
2628 | |||
2629 | if (pAC->Rlmt.Net[Para.Para32[0]].LinksUp > 1 && | ||
2630 | (pAC->Rlmt.Net[Para.Para32[0]].RlmtMode & SK_RLMT_CHECK_SEG) && | ||
2631 | (pAC->Rlmt.Net[Para.Para32[0]].CheckingState & SK_RLMT_RCS_START_SEG)) { | ||
2632 | SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].SegTimer, | ||
2633 | SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para); | ||
2634 | pAC->Rlmt.Net[Para.Para32[0]].CheckingState &= ~SK_RLMT_RCS_START_SEG; | ||
2635 | pAC->Rlmt.Net[Para.Para32[0]].CheckingState |= | ||
2636 | SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG; | ||
2637 | } | ||
2638 | |||
2639 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2640 | ("SK_RLMT_TIM Event END.\n")) | ||
2641 | } /* SkRlmtEvtTim */ | ||
2642 | |||
2643 | |||
2644 | /****************************************************************************** | ||
2645 | * | ||
2646 | * SkRlmtEvtSegTim - SEG_TIM | ||
2647 | * | ||
2648 | * Description: | ||
2649 | * This routine handles SEG_TIM events. | ||
2650 | * | ||
2651 | * Context: | ||
2652 | * runtime, pageable? | ||
2653 | * may be called after SK_INIT_IO | ||
2654 | * | ||
2655 | * Returns: | ||
2656 | * Nothing | ||
2657 | */ | ||
2658 | RLMT_STATIC void SkRlmtEvtSegTim( | ||
2659 | SK_AC *pAC, /* Adapter Context */ | ||
2660 | SK_IOC IoC, /* I/O Context */ | ||
2661 | SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ | ||
2662 | { | ||
2663 | #ifdef xDEBUG | ||
2664 | int j; | ||
2665 | #endif /* DEBUG */ | ||
2666 | |||
2667 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2668 | ("SK_RLMT_SEG_TIM Event BEGIN.\n")) | ||
2669 | |||
2670 | if (Para.Para32[1] != (SK_U32)-1) { | ||
2671 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2672 | ("Bad Parameter.\n")) | ||
2673 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2674 | ("SK_RLMT_SEG_TIM Event EMPTY.\n")) | ||
2675 | return; | ||
2676 | } | ||
2677 | |||
2678 | #ifdef xDEBUG | ||
2679 | for (j = 0; j < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; j++) { | ||
2680 | SK_ADDR_PORT *pAPort; | ||
2681 | SK_U32 k; | ||
2682 | SK_U16 *InAddr; | ||
2683 | SK_U8 InAddr8[6]; | ||
2684 | |||
2685 | InAddr = (SK_U16 *)&InAddr8[0]; | ||
2686 | pAPort = pAC->Rlmt.Net[Para.Para32[0]].Port[j]->AddrPort; | ||
2687 | for (k = 0; k < pAPort->NextExactMatchRlmt; k++) { | ||
2688 | /* Get exact match address k from port j. */ | ||
2689 | XM_INADDR(IoC, pAC->Rlmt.Net[Para.Para32[0]].Port[j]->PortNumber, | ||
2690 | XM_EXM(k), InAddr); | ||
2691 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2692 | ("MC address %d on Port %u: %02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x.\n", | ||
2693 | k, pAC->Rlmt.Net[Para.Para32[0]].Port[j]->PortNumber, | ||
2694 | InAddr8[0], InAddr8[1], InAddr8[2], | ||
2695 | InAddr8[3], InAddr8[4], InAddr8[5], | ||
2696 | pAPort->Exact[k].a[0], pAPort->Exact[k].a[1], | ||
2697 | pAPort->Exact[k].a[2], pAPort->Exact[k].a[3], | ||
2698 | pAPort->Exact[k].a[4], pAPort->Exact[k].a[5])) | ||
2699 | } | ||
2700 | } | ||
2701 | #endif /* xDEBUG */ | ||
2702 | |||
2703 | SkRlmtCheckSeg(pAC, IoC, Para.Para32[0]); | ||
2704 | |||
2705 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2706 | ("SK_RLMT_SEG_TIM Event END.\n")) | ||
2707 | } /* SkRlmtEvtSegTim */ | ||
2708 | |||
2709 | |||
2710 | /****************************************************************************** | ||
2711 | * | ||
2712 | * SkRlmtEvtPacketRx - PACKET_RECEIVED | ||
2713 | * | ||
2714 | * Description: | ||
2715 | * This routine handles PACKET_RECEIVED events. | ||
2716 | * | ||
2717 | * Context: | ||
2718 | * runtime, pageable? | ||
2719 | * may be called after SK_INIT_IO | ||
2720 | * | ||
2721 | * Returns: | ||
2722 | * Nothing | ||
2723 | */ | ||
2724 | RLMT_STATIC void SkRlmtEvtPacketRx( | ||
2725 | SK_AC *pAC, /* Adapter Context */ | ||
2726 | SK_IOC IoC, /* I/O Context */ | ||
2727 | SK_EVPARA Para) /* SK_MBUF *pMb */ | ||
2728 | { | ||
2729 | SK_MBUF *pMb; | ||
2730 | SK_MBUF *pNextMb; | ||
2731 | SK_U32 NetNumber; | ||
2732 | |||
2733 | |||
2734 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2735 | ("SK_RLMT_PACKET_RECEIVED Event BEGIN.\n")) | ||
2736 | |||
2737 | /* Should we ignore frames during port switching? */ | ||
2738 | |||
2739 | #ifdef DEBUG | ||
2740 | pMb = Para.pParaPtr; | ||
2741 | if (pMb == NULL) { | ||
2742 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("No mbuf.\n")) | ||
2743 | } | ||
2744 | else if (pMb->pNext != NULL) { | ||
2745 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2746 | ("More than one mbuf or pMb->pNext not set.\n")) | ||
2747 | } | ||
2748 | #endif /* DEBUG */ | ||
2749 | |||
2750 | for (pMb = Para.pParaPtr; pMb != NULL; pMb = pNextMb) { | ||
2751 | pNextMb = pMb->pNext; | ||
2752 | pMb->pNext = NULL; | ||
2753 | |||
2754 | NetNumber = pAC->Rlmt.Port[pMb->PortIdx].Net->NetNumber; | ||
2755 | if (pAC->Rlmt.Net[NetNumber].RlmtState == SK_RLMT_RS_INIT) { | ||
2756 | SkDrvFreeRlmtMbuf(pAC, IoC, pMb); | ||
2757 | } | ||
2758 | else { | ||
2759 | SkRlmtPacketReceive(pAC, IoC, pMb); | ||
2760 | } | ||
2761 | } | ||
2762 | |||
2763 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2764 | ("SK_RLMT_PACKET_RECEIVED Event END.\n")) | ||
2765 | } /* SkRlmtEvtPacketRx */ | ||
2766 | |||
2767 | |||
2768 | /****************************************************************************** | ||
2769 | * | ||
2770 | * SkRlmtEvtStatsClear - STATS_CLEAR | ||
2771 | * | ||
2772 | * Description: | ||
2773 | * This routine handles STATS_CLEAR events. | ||
2774 | * | ||
2775 | * Context: | ||
2776 | * runtime, pageable? | ||
2777 | * may be called after SK_INIT_IO | ||
2778 | * | ||
2779 | * Returns: | ||
2780 | * Nothing | ||
2781 | */ | ||
2782 | RLMT_STATIC void SkRlmtEvtStatsClear( | ||
2783 | SK_AC *pAC, /* Adapter Context */ | ||
2784 | SK_IOC IoC, /* I/O Context */ | ||
2785 | SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ | ||
2786 | { | ||
2787 | SK_U32 i; | ||
2788 | SK_RLMT_PORT *pRPort; | ||
2789 | |||
2790 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2791 | ("SK_RLMT_STATS_CLEAR Event BEGIN.\n")) | ||
2792 | |||
2793 | if (Para.Para32[1] != (SK_U32)-1) { | ||
2794 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2795 | ("Bad Parameter.\n")) | ||
2796 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2797 | ("SK_RLMT_STATS_CLEAR Event EMPTY.\n")) | ||
2798 | return; | ||
2799 | } | ||
2800 | |||
2801 | if (Para.Para32[0] >= pAC->Rlmt.NumNets) { | ||
2802 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2803 | ("Bad NetNumber %d.\n", Para.Para32[0])) | ||
2804 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2805 | ("SK_RLMT_STATS_CLEAR Event EMPTY.\n")) | ||
2806 | return; | ||
2807 | } | ||
2808 | |||
2809 | /* Clear statistics for logical and physical ports. */ | ||
2810 | for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) { | ||
2811 | pRPort = | ||
2812 | &pAC->Rlmt.Port[pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber]; | ||
2813 | pRPort->TxHelloCts = 0; | ||
2814 | pRPort->RxHelloCts = 0; | ||
2815 | pRPort->TxSpHelloReqCts = 0; | ||
2816 | pRPort->RxSpHelloCts = 0; | ||
2817 | } | ||
2818 | |||
2819 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2820 | ("SK_RLMT_STATS_CLEAR Event END.\n")) | ||
2821 | } /* SkRlmtEvtStatsClear */ | ||
2822 | |||
2823 | |||
2824 | /****************************************************************************** | ||
2825 | * | ||
2826 | * SkRlmtEvtStatsUpdate - STATS_UPDATE | ||
2827 | * | ||
2828 | * Description: | ||
2829 | * This routine handles STATS_UPDATE events. | ||
2830 | * | ||
2831 | * Context: | ||
2832 | * runtime, pageable? | ||
2833 | * may be called after SK_INIT_IO | ||
2834 | * | ||
2835 | * Returns: | ||
2836 | * Nothing | ||
2837 | */ | ||
2838 | RLMT_STATIC void SkRlmtEvtStatsUpdate( | ||
2839 | SK_AC *pAC, /* Adapter Context */ | ||
2840 | SK_IOC IoC, /* I/O Context */ | ||
2841 | SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ | ||
2842 | { | ||
2843 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2844 | ("SK_RLMT_STATS_UPDATE Event BEGIN.\n")) | ||
2845 | |||
2846 | if (Para.Para32[1] != (SK_U32)-1) { | ||
2847 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2848 | ("Bad Parameter.\n")) | ||
2849 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2850 | ("SK_RLMT_STATS_UPDATE Event EMPTY.\n")) | ||
2851 | return; | ||
2852 | } | ||
2853 | |||
2854 | if (Para.Para32[0] >= pAC->Rlmt.NumNets) { | ||
2855 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2856 | ("Bad NetNumber %d.\n", Para.Para32[0])) | ||
2857 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2858 | ("SK_RLMT_STATS_UPDATE Event EMPTY.\n")) | ||
2859 | return; | ||
2860 | } | ||
2861 | |||
2862 | /* Update statistics - currently always up-to-date. */ | ||
2863 | |||
2864 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2865 | ("SK_RLMT_STATS_UPDATE Event END.\n")) | ||
2866 | } /* SkRlmtEvtStatsUpdate */ | ||
2867 | |||
2868 | |||
2869 | /****************************************************************************** | ||
2870 | * | ||
2871 | * SkRlmtEvtPrefportChange - PREFPORT_CHANGE | ||
2872 | * | ||
2873 | * Description: | ||
2874 | * This routine handles PREFPORT_CHANGE events. | ||
2875 | * | ||
2876 | * Context: | ||
2877 | * runtime, pageable? | ||
2878 | * may be called after SK_INIT_IO | ||
2879 | * | ||
2880 | * Returns: | ||
2881 | * Nothing | ||
2882 | */ | ||
2883 | RLMT_STATIC void SkRlmtEvtPrefportChange( | ||
2884 | SK_AC *pAC, /* Adapter Context */ | ||
2885 | SK_IOC IoC, /* I/O Context */ | ||
2886 | SK_EVPARA Para) /* SK_U32 PortIndex; SK_U32 NetNumber */ | ||
2887 | { | ||
2888 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2889 | ("SK_RLMT_PREFPORT_CHANGE to Port %d Event BEGIN.\n", Para.Para32[0])) | ||
2890 | |||
2891 | if (Para.Para32[1] >= pAC->Rlmt.NumNets) { | ||
2892 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2893 | ("Bad NetNumber %d.\n", Para.Para32[1])) | ||
2894 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2895 | ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n")) | ||
2896 | return; | ||
2897 | } | ||
2898 | |||
2899 | /* 0xFFFFFFFF == auto-mode. */ | ||
2900 | if (Para.Para32[0] == 0xFFFFFFFF) { | ||
2901 | pAC->Rlmt.Net[Para.Para32[1]].PrefPort = SK_RLMT_DEF_PREF_PORT; | ||
2902 | } | ||
2903 | else { | ||
2904 | if (Para.Para32[0] >= pAC->Rlmt.Net[Para.Para32[1]].NumPorts) { | ||
2905 | SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E010, SKERR_RLMT_E010_MSG); | ||
2906 | |||
2907 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2908 | ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n")) | ||
2909 | return; | ||
2910 | } | ||
2911 | |||
2912 | pAC->Rlmt.Net[Para.Para32[1]].PrefPort = Para.Para32[0]; | ||
2913 | } | ||
2914 | |||
2915 | pAC->Rlmt.Net[Para.Para32[1]].Preference = Para.Para32[0]; | ||
2916 | |||
2917 | if (pAC->Rlmt.Net[Para.Para32[1]].RlmtState != SK_RLMT_RS_INIT) { | ||
2918 | SkRlmtCheckSwitch(pAC, IoC, Para.Para32[1]); | ||
2919 | } | ||
2920 | |||
2921 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2922 | ("SK_RLMT_PREFPORT_CHANGE Event END.\n")) | ||
2923 | } /* SkRlmtEvtPrefportChange */ | ||
2924 | |||
2925 | |||
2926 | /****************************************************************************** | ||
2927 | * | ||
2928 | * SkRlmtEvtSetNets - SET_NETS | ||
2929 | * | ||
2930 | * Description: | ||
2931 | * This routine handles SET_NETS events. | ||
2932 | * | ||
2933 | * Context: | ||
2934 | * runtime, pageable? | ||
2935 | * may be called after SK_INIT_IO | ||
2936 | * | ||
2937 | * Returns: | ||
2938 | * Nothing | ||
2939 | */ | ||
2940 | RLMT_STATIC void SkRlmtEvtSetNets( | ||
2941 | SK_AC *pAC, /* Adapter Context */ | ||
2942 | SK_IOC IoC, /* I/O Context */ | ||
2943 | SK_EVPARA Para) /* SK_U32 NumNets; SK_U32 -1 */ | ||
2944 | { | ||
2945 | int i; | ||
2946 | |||
2947 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2948 | ("SK_RLMT_SET_NETS Event BEGIN.\n")) | ||
2949 | |||
2950 | if (Para.Para32[1] != (SK_U32)-1) { | ||
2951 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2952 | ("Bad Parameter.\n")) | ||
2953 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2954 | ("SK_RLMT_SET_NETS Event EMPTY.\n")) | ||
2955 | return; | ||
2956 | } | ||
2957 | |||
2958 | if (Para.Para32[0] == 0 || Para.Para32[0] > SK_MAX_NETS || | ||
2959 | Para.Para32[0] > (SK_U32)pAC->GIni.GIMacsFound) { | ||
2960 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2961 | ("Bad number of nets: %d.\n", Para.Para32[0])) | ||
2962 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2963 | ("SK_RLMT_SET_NETS Event EMPTY.\n")) | ||
2964 | return; | ||
2965 | } | ||
2966 | |||
2967 | if (Para.Para32[0] == pAC->Rlmt.NumNets) { /* No change. */ | ||
2968 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2969 | ("SK_RLMT_SET_NETS Event EMPTY.\n")) | ||
2970 | return; | ||
2971 | } | ||
2972 | |||
2973 | /* Entering and leaving dual mode only allowed while nets are stopped. */ | ||
2974 | if (pAC->Rlmt.NetsStarted > 0) { | ||
2975 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2976 | ("Changing dual mode only allowed while all nets are stopped.\n")) | ||
2977 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
2978 | ("SK_RLMT_SET_NETS Event EMPTY.\n")) | ||
2979 | return; | ||
2980 | } | ||
2981 | |||
2982 | if (Para.Para32[0] == 1) { | ||
2983 | if (pAC->Rlmt.NumNets > 1) { | ||
2984 | /* Clear logical MAC addr from second net's active port. */ | ||
2985 | (void)SkAddrOverride(pAC, IoC, pAC->Rlmt.Net[1].Port[pAC->Addr. | ||
2986 | Net[1].ActivePort]->PortNumber, NULL, SK_ADDR_CLEAR_LOGICAL); | ||
2987 | pAC->Rlmt.Net[1].NumPorts = 0; | ||
2988 | } | ||
2989 | |||
2990 | pAC->Rlmt.NumNets = Para.Para32[0]; | ||
2991 | for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) { | ||
2992 | pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT; | ||
2993 | pAC->Rlmt.Net[i].RootIdSet = SK_FALSE; | ||
2994 | pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF; /* "Automatic" */ | ||
2995 | pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT; | ||
2996 | /* Just assuming. */ | ||
2997 | pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort; | ||
2998 | pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE; | ||
2999 | pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL; | ||
3000 | pAC->Rlmt.Net[i].NetNumber = i; | ||
3001 | } | ||
3002 | |||
3003 | pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[0]; | ||
3004 | pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound; | ||
3005 | |||
3006 | SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para); | ||
3007 | |||
3008 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
3009 | ("RLMT: Changed to one net with two ports.\n")) | ||
3010 | } | ||
3011 | else if (Para.Para32[0] == 2) { | ||
3012 | pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[1]; | ||
3013 | pAC->Rlmt.Net[1].NumPorts = pAC->GIni.GIMacsFound - 1; | ||
3014 | pAC->Rlmt.Net[0].NumPorts = | ||
3015 | pAC->GIni.GIMacsFound - pAC->Rlmt.Net[1].NumPorts; | ||
3016 | |||
3017 | pAC->Rlmt.NumNets = Para.Para32[0]; | ||
3018 | for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) { | ||
3019 | pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT; | ||
3020 | pAC->Rlmt.Net[i].RootIdSet = SK_FALSE; | ||
3021 | pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF; /* "Automatic" */ | ||
3022 | pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT; | ||
3023 | /* Just assuming. */ | ||
3024 | pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort; | ||
3025 | pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE; | ||
3026 | pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL; | ||
3027 | |||
3028 | pAC->Rlmt.Net[i].NetNumber = i; | ||
3029 | } | ||
3030 | |||
3031 | /* Set logical MAC addr on second net's active port. */ | ||
3032 | (void)SkAddrOverride(pAC, IoC, pAC->Rlmt.Net[1].Port[pAC->Addr. | ||
3033 | Net[1].ActivePort]->PortNumber, NULL, SK_ADDR_SET_LOGICAL); | ||
3034 | |||
3035 | SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para); | ||
3036 | |||
3037 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
3038 | ("RLMT: Changed to two nets with one port each.\n")) | ||
3039 | } | ||
3040 | else { | ||
3041 | /* Not implemented for more than two nets. */ | ||
3042 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
3043 | ("SetNets not implemented for more than two nets.\n")) | ||
3044 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
3045 | ("SK_RLMT_SET_NETS Event EMPTY.\n")) | ||
3046 | return; | ||
3047 | } | ||
3048 | |||
3049 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
3050 | ("SK_RLMT_SET_NETS Event END.\n")) | ||
3051 | } /* SkRlmtSetNets */ | ||
3052 | |||
3053 | |||
3054 | /****************************************************************************** | ||
3055 | * | ||
3056 | * SkRlmtEvtModeChange - MODE_CHANGE | ||
3057 | * | ||
3058 | * Description: | ||
3059 | * This routine handles MODE_CHANGE events. | ||
3060 | * | ||
3061 | * Context: | ||
3062 | * runtime, pageable? | ||
3063 | * may be called after SK_INIT_IO | ||
3064 | * | ||
3065 | * Returns: | ||
3066 | * Nothing | ||
3067 | */ | ||
3068 | RLMT_STATIC void SkRlmtEvtModeChange( | ||
3069 | SK_AC *pAC, /* Adapter Context */ | ||
3070 | SK_IOC IoC, /* I/O Context */ | ||
3071 | SK_EVPARA Para) /* SK_U32 NewMode; SK_U32 NetNumber */ | ||
3072 | { | ||
3073 | SK_EVPARA Para2; | ||
3074 | SK_U32 i; | ||
3075 | SK_U32 PrevRlmtMode; | ||
3076 | |||
3077 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
3078 | ("SK_RLMT_MODE_CHANGE Event BEGIN.\n")) | ||
3079 | |||
3080 | if (Para.Para32[1] >= pAC->Rlmt.NumNets) { | ||
3081 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
3082 | ("Bad NetNumber %d.\n", Para.Para32[1])) | ||
3083 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
3084 | ("SK_RLMT_MODE_CHANGE Event EMPTY.\n")) | ||
3085 | return; | ||
3086 | } | ||
3087 | |||
3088 | Para.Para32[0] |= SK_RLMT_CHECK_LINK; | ||
3089 | |||
3090 | if ((pAC->Rlmt.Net[Para.Para32[1]].NumPorts == 1) && | ||
3091 | Para.Para32[0] != SK_RLMT_MODE_CLS) { | ||
3092 | pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = SK_RLMT_MODE_CLS; | ||
3093 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
3094 | ("Forced RLMT mode to CLS on single port net.\n")) | ||
3095 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
3096 | ("SK_RLMT_MODE_CHANGE Event EMPTY.\n")) | ||
3097 | return; | ||
3098 | } | ||
3099 | |||
3100 | /* Update RLMT mode. */ | ||
3101 | PrevRlmtMode = pAC->Rlmt.Net[Para.Para32[1]].RlmtMode; | ||
3102 | pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = Para.Para32[0]; | ||
3103 | |||
3104 | if ((PrevRlmtMode & SK_RLMT_CHECK_LOC_LINK) != | ||
3105 | (pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) { | ||
3106 | /* SK_RLMT_CHECK_LOC_LINK bit changed. */ | ||
3107 | if ((PrevRlmtMode & SK_RLMT_CHECK_OTHERS) == 0 && | ||
3108 | pAC->Rlmt.Net[Para.Para32[1]].NumPorts > 1 && | ||
3109 | pAC->Rlmt.Net[Para.Para32[1]].PortsUp >= 1) { | ||
3110 | /* 20001207 RA: Was "PortsUp == 1". */ | ||
3111 | Para2.Para32[0] = Para.Para32[1]; | ||
3112 | Para2.Para32[1] = (SK_U32)-1; | ||
3113 | SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[1]].LocTimer, | ||
3114 | pAC->Rlmt.Net[Para.Para32[1]].TimeoutValue, | ||
3115 | SKGE_RLMT, SK_RLMT_TIM, Para2); | ||
3116 | } | ||
3117 | } | ||
3118 | |||
3119 | if ((PrevRlmtMode & SK_RLMT_CHECK_SEG) != | ||
3120 | (pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_SEG)) { | ||
3121 | /* SK_RLMT_CHECK_SEG bit changed. */ | ||
3122 | for (i = 0; i < pAC->Rlmt.Net[Para.Para32[1]].NumPorts; i++) { | ||
3123 | (void)SkAddrMcClear(pAC, IoC, | ||
3124 | pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber, | ||
3125 | SK_ADDR_PERMANENT | SK_MC_SW_ONLY); | ||
3126 | |||
3127 | /* Add RLMT MC address. */ | ||
3128 | (void)SkAddrMcAdd(pAC, IoC, | ||
3129 | pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber, | ||
3130 | &SkRlmtMcAddr, SK_ADDR_PERMANENT); | ||
3131 | |||
3132 | if ((pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & | ||
3133 | SK_RLMT_CHECK_SEG) != 0) { | ||
3134 | /* Add BPDU MC address. */ | ||
3135 | (void)SkAddrMcAdd(pAC, IoC, | ||
3136 | pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber, | ||
3137 | &BridgeMcAddr, SK_ADDR_PERMANENT); | ||
3138 | |||
3139 | if (pAC->Rlmt.Net[Para.Para32[1]].RlmtState != SK_RLMT_RS_INIT) { | ||
3140 | if (!pAC->Rlmt.Net[Para.Para32[1]].Port[i]->LinkDown && | ||
3141 | (Para2.pParaPtr = SkRlmtBuildSpanningTreePacket( | ||
3142 | pAC, IoC, i)) != NULL) { | ||
3143 | pAC->Rlmt.Net[Para.Para32[1]].Port[i]->RootIdSet = | ||
3144 | SK_FALSE; | ||
3145 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2); | ||
3146 | } | ||
3147 | } | ||
3148 | } | ||
3149 | (void)SkAddrMcUpdate(pAC, IoC, | ||
3150 | pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber); | ||
3151 | } /* for ... */ | ||
3152 | |||
3153 | if ((pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_SEG) != 0) { | ||
3154 | Para2.Para32[0] = Para.Para32[1]; | ||
3155 | Para2.Para32[1] = (SK_U32)-1; | ||
3156 | SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[1]].SegTimer, | ||
3157 | SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para2); | ||
3158 | } | ||
3159 | } /* SK_RLMT_CHECK_SEG bit changed. */ | ||
3160 | |||
3161 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
3162 | ("SK_RLMT_MODE_CHANGE Event END.\n")) | ||
3163 | } /* SkRlmtEvtModeChange */ | ||
3164 | |||
3165 | |||
3166 | /****************************************************************************** | ||
3167 | * | ||
3168 | * SkRlmtEvent - a PORT- or an RLMT-specific event happened | ||
3169 | * | ||
3170 | * Description: | ||
3171 | * This routine calls subroutines to handle PORT- and RLMT-specific events. | ||
3172 | * | ||
3173 | * Context: | ||
3174 | * runtime, pageable? | ||
3175 | * may be called after SK_INIT_IO | ||
3176 | * | ||
3177 | * Returns: | ||
3178 | * 0 | ||
3179 | */ | ||
3180 | int SkRlmtEvent( | ||
3181 | SK_AC *pAC, /* Adapter Context */ | ||
3182 | SK_IOC IoC, /* I/O Context */ | ||
3183 | SK_U32 Event, /* Event code */ | ||
3184 | SK_EVPARA Para) /* Event-specific parameter */ | ||
3185 | { | ||
3186 | switch (Event) { | ||
3187 | |||
3188 | /* ----- PORT events ----- */ | ||
3189 | |||
3190 | case SK_RLMT_PORTSTART_TIM: /* From RLMT via TIME. */ | ||
3191 | SkRlmtEvtPortStartTim(pAC, IoC, Para); | ||
3192 | break; | ||
3193 | case SK_RLMT_LINK_UP: /* From SIRQ. */ | ||
3194 | SkRlmtEvtLinkUp(pAC, IoC, Para); | ||
3195 | break; | ||
3196 | case SK_RLMT_PORTUP_TIM: /* From RLMT via TIME. */ | ||
3197 | SkRlmtEvtPortUpTim(pAC, IoC, Para); | ||
3198 | break; | ||
3199 | case SK_RLMT_PORTDOWN: /* From RLMT. */ | ||
3200 | case SK_RLMT_PORTDOWN_RX_TIM: /* From RLMT via TIME. */ | ||
3201 | case SK_RLMT_PORTDOWN_TX_TIM: /* From RLMT via TIME. */ | ||
3202 | SkRlmtEvtPortDownX(pAC, IoC, Event, Para); | ||
3203 | break; | ||
3204 | case SK_RLMT_LINK_DOWN: /* From SIRQ. */ | ||
3205 | SkRlmtEvtLinkDown(pAC, IoC, Para); | ||
3206 | break; | ||
3207 | case SK_RLMT_PORT_ADDR: /* From ADDR. */ | ||
3208 | SkRlmtEvtPortAddr(pAC, IoC, Para); | ||
3209 | break; | ||
3210 | |||
3211 | /* ----- RLMT events ----- */ | ||
3212 | |||
3213 | case SK_RLMT_START: /* From DRV. */ | ||
3214 | SkRlmtEvtStart(pAC, IoC, Para); | ||
3215 | break; | ||
3216 | case SK_RLMT_STOP: /* From DRV. */ | ||
3217 | SkRlmtEvtStop(pAC, IoC, Para); | ||
3218 | break; | ||
3219 | case SK_RLMT_TIM: /* From RLMT via TIME. */ | ||
3220 | SkRlmtEvtTim(pAC, IoC, Para); | ||
3221 | break; | ||
3222 | case SK_RLMT_SEG_TIM: | ||
3223 | SkRlmtEvtSegTim(pAC, IoC, Para); | ||
3224 | break; | ||
3225 | case SK_RLMT_PACKET_RECEIVED: /* From DRV. */ | ||
3226 | SkRlmtEvtPacketRx(pAC, IoC, Para); | ||
3227 | break; | ||
3228 | case SK_RLMT_STATS_CLEAR: /* From PNMI. */ | ||
3229 | SkRlmtEvtStatsClear(pAC, IoC, Para); | ||
3230 | break; | ||
3231 | case SK_RLMT_STATS_UPDATE: /* From PNMI. */ | ||
3232 | SkRlmtEvtStatsUpdate(pAC, IoC, Para); | ||
3233 | break; | ||
3234 | case SK_RLMT_PREFPORT_CHANGE: /* From PNMI. */ | ||
3235 | SkRlmtEvtPrefportChange(pAC, IoC, Para); | ||
3236 | break; | ||
3237 | case SK_RLMT_MODE_CHANGE: /* From PNMI. */ | ||
3238 | SkRlmtEvtModeChange(pAC, IoC, Para); | ||
3239 | break; | ||
3240 | case SK_RLMT_SET_NETS: /* From DRV. */ | ||
3241 | SkRlmtEvtSetNets(pAC, IoC, Para); | ||
3242 | break; | ||
3243 | |||
3244 | /* ----- Unknown events ----- */ | ||
3245 | |||
3246 | default: /* Create error log entry. */ | ||
3247 | SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, | ||
3248 | ("Unknown RLMT Event %d.\n", Event)) | ||
3249 | SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E003, SKERR_RLMT_E003_MSG); | ||
3250 | break; | ||
3251 | } /* switch() */ | ||
3252 | |||
3253 | return (0); | ||
3254 | } /* SkRlmtEvent */ | ||
3255 | |||
3256 | #ifdef __cplusplus | ||
3257 | } | ||
3258 | #endif /* __cplusplus */ | ||