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