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