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