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