1 /******************************************************************************
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.
9 ******************************************************************************/
11 /******************************************************************************
13 * (C)Copyright 1998-2002 SysKonnect GmbH.
14 * (C)Copyright 2002-2003 Marvell.
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.
21 * The information in this file is provided "AS IS" without warranty.
23 ******************************************************************************/
25 /******************************************************************************
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).
33 * Include File Hierarchy:
38 ******************************************************************************/
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) */
49 #endif /* cplusplus */
51 #include "h/skdrv1st.h"
52 #include "h/skdrv2nd.h"
54 /* defines ********************************************************************/
56 #ifndef SK_HWAC_LINK_LED
57 #define SK_HWAC_LINK_LED(a,b,c,d)
58 #endif /* !defined(SK_HWAC_LINK_LED) */
61 #define RLMT_STATIC static
65 #ifndef SK_LITTLE_ENDIAN
71 #else /* SK_LITTLE_ENDIAN */
77 #endif /* SK_LITTLE_ENDIAN */
81 /* ----- Private timeout values ----- */
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. */
90 /* Assume tick counter increment is 1 - may be set OS-dependent. */
92 #define SK_TICK_INCR SK_CONSTU64(1)
93 #endif /* !defined(SK_TICK_INCR) */
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.
99 #define SK_RLMT_BC_DELTA (1 + ((SK_TICKS_PER_SEC >> 7) > SK_TICK_INCR ? \
100 (SK_TICKS_PER_SEC >> 7) : SK_TICK_INCR))
102 /* ----- Private RLMT defaults ----- */
104 #define SK_RLMT_DEF_PREF_PORT 0 /* "Lower" port. */
105 #define SK_RLMT_DEF_MODE SK_RLMT_CHECK_LINK /* Default RLMT Mode. */
107 /* ----- Private RLMT checking states ----- */
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. */
114 /* ----- Private PORT checking states ----- */
116 #define SK_RLMT_PCS_TX 1 /* Port Check State: check tx. */
117 #define SK_RLMT_PCS_RX 2 /* Port Check State: check rx. */
119 /* ----- Private PORT events ----- */
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 ... */
128 /* ----- Private RLMT events ----- */
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. */
134 #define TO_SHORTEN(tim) ((tim) / 2)
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."
159 /* LLC field values. */
160 #define LLC_COMMAND_RESPONSE_BIT 1
161 #define LLC_TEST_COMMAND 0xE3
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
177 /* RLMT SPT Flag values. */
178 #define SK_RLMT_SPT_FLAG_CHANGE 0x01
179 #define SK_RLMT_SPT_FLAG_CHANGE_ACK 0x80
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. */
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. */
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
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)
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. */
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); \
232 #endif /* SK_LITTLE_ENDIAN */
235 #define SK_U16_TO_NETWORK_ORDER(Val,Addr) (*(SK_U16*)(Addr) = (SK_U16)(Val))
236 #endif /* SK_BIG_ENDIAN */
238 #define AUTONEG_FAILED SK_FALSE
239 #define AUTONEG_SUCCESS SK_TRUE
242 /* typedefs *******************************************************************/
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
];
253 SK_U8 RlmtPacketType
[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
];
260 typedef struct s_SpTreeRlmtPacket
{
261 SK_U8 DstAddr
[SK_MAC_ADDR_LEN
];
262 SK_U8 SrcAddr
[SK_MAC_ADDR_LEN
];
268 SK_U8 ProtocolVersionId
;
272 SK_U8 RootPathCost
[4];
278 SK_U8 ForwardDelay
[2];
281 /* global variables ***********************************************************/
283 SK_MAC_ADDR SkRlmtMcAddr
= {{0x01, 0x00, 0x5A, 0x52, 0x4C, 0x4D}};
284 SK_MAC_ADDR BridgeMcAddr
= {{0x01, 0x80, 0xC2, 0x00, 0x00, 0x00}};
285 SK_MAC_ADDR BcAddr
= {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
287 /* local variables ************************************************************/
291 /* functions ******************************************************************/
293 RLMT_STATIC
void SkRlmtCheckSwitch(
297 RLMT_STATIC
void SkRlmtCheckSeg(
301 RLMT_STATIC
void SkRlmtEvtSetNets(
306 /******************************************************************************
308 * SkRlmtInit - initialize data, set state to init
315 * This routine initializes all RLMT-related variables to a known state.
316 * The initial state is SK_RLMT_RS_INIT.
317 * All ports are initialized to SK_RLMT_PS_INIT.
329 * Determine the adapter's random value.
330 * Set the hw registers, the "logical MAC address", the
331 * RLMT multicast address, and eventually the BPDU multicast address.
340 SK_AC
*pAC
, /* Adapter Context */
341 SK_IOC IoC
, /* I/O Context */
342 int Level
) /* Initialization Level */
347 SK_MAC_ADDR VirtualMacAddress
;
348 SK_MAC_ADDR PhysicalAMacAddress
;
349 SK_BOOL VirtualMacAddressSet
;
350 SK_BOOL PhysicalAMacAddressSet
;
352 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_INIT
,
353 ("RLMT Init level %d.\n", Level
))
356 case SK_INIT_DATA
: /* Initialize data structures. */
357 SK_MEMSET((char *)&pAC
->Rlmt
, 0, sizeof(SK_RLMT
));
359 for (i
= 0; i
< SK_MAX_MACS
; i
++) {
360 pAC
->Rlmt
.Port
[i
].PortState
= SK_RLMT_PS_INIT
;
361 pAC
->Rlmt
.Port
[i
].LinkDown
= SK_TRUE
;
362 pAC
->Rlmt
.Port
[i
].PortDown
= SK_TRUE
;
363 pAC
->Rlmt
.Port
[i
].PortStarted
= SK_FALSE
;
364 pAC
->Rlmt
.Port
[i
].PortNoRx
= SK_FALSE
;
365 pAC
->Rlmt
.Port
[i
].RootIdSet
= SK_FALSE
;
366 pAC
->Rlmt
.Port
[i
].PortNumber
= i
;
367 pAC
->Rlmt
.Port
[i
].Net
= &pAC
->Rlmt
.Net
[0];
368 pAC
->Rlmt
.Port
[i
].AddrPort
= &pAC
->Addr
.Port
[i
];
371 pAC
->Rlmt
.NumNets
= 1;
372 for (i
= 0; i
< SK_MAX_NETS
; i
++) {
373 pAC
->Rlmt
.Net
[i
].RlmtState
= SK_RLMT_RS_INIT
;
374 pAC
->Rlmt
.Net
[i
].RootIdSet
= SK_FALSE
;
375 pAC
->Rlmt
.Net
[i
].PrefPort
= SK_RLMT_DEF_PREF_PORT
;
376 pAC
->Rlmt
.Net
[i
].Preference
= 0xFFFFFFFF; /* Automatic. */
378 pAC
->Rlmt
.Net
[i
].ActivePort
= pAC
->Rlmt
.Net
[i
].PrefPort
;
379 pAC
->Rlmt
.Net
[i
].RlmtMode
= SK_RLMT_DEF_MODE
;
380 pAC
->Rlmt
.Net
[i
].TimeoutValue
= SK_RLMT_DEF_TO_VAL
;
381 pAC
->Rlmt
.Net
[i
].NetNumber
= i
;
384 pAC
->Rlmt
.Net
[0].Port
[0] = &pAC
->Rlmt
.Port
[0];
385 pAC
->Rlmt
.Net
[0].Port
[1] = &pAC
->Rlmt
.Port
[1];
387 pAC
->Rlmt
.Net
[1].Port
[0] = &pAC
->Rlmt
.Port
[1];
388 #endif /* SK_MAX_NETS > 1 */
391 case SK_INIT_IO
: /* GIMacsFound first available here. */
392 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_INIT
,
393 ("RLMT: %d MACs were detected.\n", pAC
->GIni
.GIMacsFound
))
395 pAC
->Rlmt
.Net
[0].NumPorts
= pAC
->GIni
.GIMacsFound
;
397 /* Initialize HW registers? */
398 if (pAC
->GIni
.GIMacsFound
== 1) {
399 Para
.Para32
[0] = SK_RLMT_MODE_CLS
;
401 (void)SkRlmtEvent(pAC
, IoC
, SK_RLMT_MODE_CHANGE
, Para
);
406 /* Ensure RLMT is set to one net. */
407 if (pAC
->Rlmt
.NumNets
> 1) {
410 SkRlmtEvtSetNets(pAC
, IoC
, Para
);
413 for (i
= 0; i
< (SK_U32
)pAC
->GIni
.GIMacsFound
; i
++) {
414 Random
= SkOsGetTime(pAC
);
415 *(SK_U32
*)&pAC
->Rlmt
.Port
[i
].Random
= *(SK_U32
*)&Random
;
417 for (j
= 0; j
< 4; j
++) {
418 pAC
->Rlmt
.Port
[i
].Random
[j
] ^= pAC
->Rlmt
.Port
[i
].AddrPort
->
419 CurrentMacAddress
.a
[SK_MAC_ADDR_LEN
- 1 - j
];
422 (void)SkAddrMcClear(pAC
, IoC
, i
, SK_ADDR_PERMANENT
| SK_MC_SW_ONLY
);
424 /* Add RLMT MC address. */
425 (void)SkAddrMcAdd(pAC
, IoC
, i
, &SkRlmtMcAddr
, SK_ADDR_PERMANENT
);
427 if (pAC
->Rlmt
.Net
[0].RlmtMode
& SK_RLMT_CHECK_SEG
) {
428 /* Add BPDU MC address. */
429 (void)SkAddrMcAdd(pAC
, IoC
, i
, &BridgeMcAddr
, SK_ADDR_PERMANENT
);
432 (void)SkAddrMcUpdate(pAC
, IoC
, i
);
435 VirtualMacAddressSet
= SK_FALSE
;
436 /* Read virtual MAC address from Control Register File. */
437 for (j
= 0; j
< SK_MAC_ADDR_LEN
; j
++) {
439 SK_IN8(IoC
, B2_MAC_1
+ j
, &VirtualMacAddress
.a
[j
]);
440 VirtualMacAddressSet
|= VirtualMacAddress
.a
[j
];
443 PhysicalAMacAddressSet
= SK_FALSE
;
444 /* Read physical MAC address for MAC A from Control Register File. */
445 for (j
= 0; j
< SK_MAC_ADDR_LEN
; j
++) {
447 SK_IN8(IoC
, B2_MAC_2
+ j
, &PhysicalAMacAddress
.a
[j
]);
448 PhysicalAMacAddressSet
|= PhysicalAMacAddress
.a
[j
];
451 /* check if the two mac addresses contain reasonable values */
452 if (!VirtualMacAddressSet
|| !PhysicalAMacAddressSet
) {
454 pAC
->Rlmt
.RlmtOff
= SK_TRUE
;
457 /* if the two mac addresses are equal switch off the RLMT_PRE_LOOKAHEAD
458 and the RLMT_LOOKAHEAD macros */
459 else if (SK_ADDR_EQUAL(PhysicalAMacAddress
.a
, VirtualMacAddress
.a
)) {
461 pAC
->Rlmt
.RlmtOff
= SK_TRUE
;
464 pAC
->Rlmt
.RlmtOff
= SK_FALSE
;
475 /******************************************************************************
477 * SkRlmtBuildCheckChain - build the check chain
480 * This routine builds the local check chain:
481 * - Each port that is up checks the next port.
482 * - The last port that is up checks the first port that is up.
485 * - Currently only local ports are considered when building the chain.
486 * - Currently the SuspectState is just reset;
487 * it would be better to save it ...
495 RLMT_STATIC
void SkRlmtBuildCheckChain(
496 SK_AC
*pAC
, /* Adapter Context */
497 SK_U32 NetIdx
) /* Net Number */
501 SK_RLMT_PORT
* FirstMacUp
;
502 SK_RLMT_PORT
* PrevMacUp
;
507 if (!(pAC
->Rlmt
.Net
[NetIdx
].RlmtMode
& SK_RLMT_CHECK_LOC_LINK
)) {
508 for (i
= 0; i
< pAC
->Rlmt
.Net
[i
].NumPorts
; i
++) {
509 pAC
->Rlmt
.Net
[NetIdx
].Port
[i
]->PortsChecked
= 0;
514 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
515 ("SkRlmtBuildCheckChain.\n"))
519 for (i
= 0; i
< pAC
->Rlmt
.Net
[NetIdx
].NumPorts
; i
++) {
520 pAC
->Rlmt
.Net
[NetIdx
].Port
[i
]->PortsChecked
= 0;
521 pAC
->Rlmt
.Net
[NetIdx
].Port
[i
]->PortsSuspect
= 0;
522 pAC
->Rlmt
.Net
[NetIdx
].Port
[i
]->CheckingState
&=
523 ~(SK_RLMT_PCS_RX
| SK_RLMT_PCS_TX
);
526 * If more than two links are detected we should consider
527 * checking at least two other ports:
528 * 1. the next port that is not LinkDown and
529 * 2. the next port that is not PortDown.
531 if (!pAC
->Rlmt
.Net
[NetIdx
].Port
[i
]->LinkDown
) {
532 if (NumMacsUp
== 0) {
533 FirstMacUp
= pAC
->Rlmt
.Net
[NetIdx
].Port
[i
];
536 PrevMacUp
->PortCheck
[
537 pAC
->Rlmt
.Net
[NetIdx
].Port
[i
]->PortsChecked
].CheckAddr
=
538 pAC
->Rlmt
.Net
[NetIdx
].Port
[i
]->AddrPort
->CurrentMacAddress
;
539 PrevMacUp
->PortCheck
[
540 PrevMacUp
->PortsChecked
].SuspectTx
= SK_FALSE
;
541 PrevMacUp
->PortsChecked
++;
543 PrevMacUp
= pAC
->Rlmt
.Net
[NetIdx
].Port
[i
];
549 PrevMacUp
->PortCheck
[PrevMacUp
->PortsChecked
].CheckAddr
=
550 FirstMacUp
->AddrPort
->CurrentMacAddress
;
551 PrevMacUp
->PortCheck
[PrevMacUp
->PortsChecked
].SuspectTx
=
553 PrevMacUp
->PortsChecked
++;
557 for (i
= 0; i
< pAC
->Rlmt
.Net
[NetIdx
].NumPorts
; i
++) {
558 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
559 ("Port %d checks %d other ports: %2X.\n", i
,
560 pAC
->Rlmt
.Net
[NetIdx
].Port
[i
]->PortsChecked
,
561 pAC
->Rlmt
.Net
[NetIdx
].Port
[i
]->PortCheck
[0].CheckAddr
.a
[5]))
566 } /* SkRlmtBuildCheckChain */
569 /******************************************************************************
571 * SkRlmtBuildPacket - build an RLMT packet
574 * This routine sets up an RLMT packet.
580 * NULL or pointer to RLMT mbuf
582 RLMT_STATIC SK_MBUF
*SkRlmtBuildPacket(
583 SK_AC
*pAC
, /* Adapter Context */
584 SK_IOC IoC
, /* I/O Context */
585 SK_U32 PortNumber
, /* Sending port */
586 SK_U16 PacketType
, /* RLMT packet type */
587 SK_MAC_ADDR
*SrcAddr
, /* Source address */
588 SK_MAC_ADDR
*DestAddr
) /* Destination address */
593 SK_RLMT_PACKET
*pPacket
;
599 for (i
= 0; i
< SK_MAC_ADDR_LEN
; ++i
) {
600 CheckSrc
|= SrcAddr
->a
[i
];
601 CheckDest
|= DestAddr
->a
[i
];
604 if ((CheckSrc
== 0) || (CheckDest
== 0)) {
605 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_ERR
,
606 ("SkRlmtBuildPacket: Invalid %s%saddr.\n",
607 (CheckSrc
== 0 ? "Src" : ""), (CheckDest
== 0 ? "Dest" : "")))
611 if ((pMb
= SkDrvAllocRlmtMbuf(pAC
, IoC
, SK_RLMT_MAX_PACKET_SIZE
)) != NULL
) {
612 pPacket
= (SK_RLMT_PACKET
*)pMb
->pData
;
613 for (i
= 0; i
< SK_MAC_ADDR_LEN
; i
++) {
614 pPacket
->DstAddr
[i
] = DestAddr
->a
[i
];
615 pPacket
->SrcAddr
[i
] = SrcAddr
->a
[i
];
617 pPacket
->DSap
= SK_RLMT_DSAP
;
618 pPacket
->SSap
= SK_RLMT_SSAP
;
619 pPacket
->Ctrl
= SK_RLMT_CTRL
;
620 pPacket
->Indicator
[0] = SK_RLMT_INDICATOR0
;
621 pPacket
->Indicator
[1] = SK_RLMT_INDICATOR1
;
622 pPacket
->Indicator
[2] = SK_RLMT_INDICATOR2
;
623 pPacket
->Indicator
[3] = SK_RLMT_INDICATOR3
;
624 pPacket
->Indicator
[4] = SK_RLMT_INDICATOR4
;
625 pPacket
->Indicator
[5] = SK_RLMT_INDICATOR5
;
626 pPacket
->Indicator
[6] = SK_RLMT_INDICATOR6
;
628 SK_U16_TO_NETWORK_ORDER(PacketType
, &pPacket
->RlmtPacketType
[0]);
630 for (i
= 0; i
< 4; i
++) {
631 pPacket
->Random
[i
] = pAC
->Rlmt
.Port
[PortNumber
].Random
[i
];
634 SK_U16_TO_NETWORK_ORDER(
635 SK_RLMT_PACKET_VERSION
, &pPacket
->RlmtPacketVersion
[0]);
637 for (i
= 0; i
< SK_PACKET_DATA_LEN
; i
++) {
638 pPacket
->Data
[i
] = 0x00;
641 Length
= SK_RLMT_MAX_PACKET_SIZE
; /* Or smaller. */
642 pMb
->Length
= Length
;
643 pMb
->PortIdx
= PortNumber
;
645 SK_U16_TO_NETWORK_ORDER(Length
, &pPacket
->TypeLen
[0]);
647 if (PacketType
== SK_PACKET_ALIVE
) {
648 pAC
->Rlmt
.Port
[PortNumber
].TxHelloCts
++;
653 } /* SkRlmtBuildPacket */
656 /******************************************************************************
658 * SkRlmtBuildSpanningTreePacket - build spanning tree check packet
661 * This routine sets up a BPDU packet for spanning tree check.
667 * NULL or pointer to RLMT mbuf
669 RLMT_STATIC SK_MBUF
*SkRlmtBuildSpanningTreePacket(
670 SK_AC
*pAC
, /* Adapter Context */
671 SK_IOC IoC
, /* I/O Context */
672 SK_U32 PortNumber
) /* Sending port */
677 SK_SPTREE_PACKET
*pSPacket
;
679 if ((pMb
= SkDrvAllocRlmtMbuf(pAC
, IoC
, SK_RLMT_MAX_PACKET_SIZE
)) !=
681 pSPacket
= (SK_SPTREE_PACKET
*)pMb
->pData
;
682 for (i
= 0; i
< SK_MAC_ADDR_LEN
; i
++) {
683 pSPacket
->DstAddr
[i
] = BridgeMcAddr
.a
[i
];
684 pSPacket
->SrcAddr
[i
] =
685 pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
.a
[i
];
687 pSPacket
->DSap
= SK_RLMT_SPT_DSAP
;
688 pSPacket
->SSap
= SK_RLMT_SPT_SSAP
;
689 pSPacket
->Ctrl
= SK_RLMT_SPT_CTRL
;
691 pSPacket
->ProtocolId
[0] = SK_RLMT_SPT_PROTOCOL_ID0
;
692 pSPacket
->ProtocolId
[1] = SK_RLMT_SPT_PROTOCOL_ID1
;
693 pSPacket
->ProtocolVersionId
= SK_RLMT_SPT_PROTOCOL_VERSION_ID
;
694 pSPacket
->BpduType
= SK_RLMT_SPT_BPDU_TYPE
;
695 pSPacket
->Flags
= SK_RLMT_SPT_FLAGS
;
696 pSPacket
->RootId
[0] = SK_RLMT_SPT_ROOT_ID0
;
697 pSPacket
->RootId
[1] = SK_RLMT_SPT_ROOT_ID1
;
698 pSPacket
->RootPathCost
[0] = SK_RLMT_SPT_ROOT_PATH_COST0
;
699 pSPacket
->RootPathCost
[1] = SK_RLMT_SPT_ROOT_PATH_COST1
;
700 pSPacket
->RootPathCost
[2] = SK_RLMT_SPT_ROOT_PATH_COST2
;
701 pSPacket
->RootPathCost
[3] = SK_RLMT_SPT_ROOT_PATH_COST3
;
702 pSPacket
->BridgeId
[0] = SK_RLMT_SPT_BRIDGE_ID0
;
703 pSPacket
->BridgeId
[1] = SK_RLMT_SPT_BRIDGE_ID1
;
706 * Use logical MAC address as bridge ID and filter these packets
709 for (i
= 0; i
< SK_MAC_ADDR_LEN
; i
++) {
710 pSPacket
->BridgeId
[i
+ 2] = pSPacket
->RootId
[i
+ 2] =
711 pAC
->Addr
.Net
[pAC
->Rlmt
.Port
[PortNumber
].Net
->NetNumber
].
712 CurrentMacAddress
.a
[i
];
714 pSPacket
->PortId
[0] = SK_RLMT_SPT_PORT_ID0
;
715 pSPacket
->PortId
[1] = SK_RLMT_SPT_PORT_ID1
;
716 pSPacket
->MessageAge
[0] = SK_RLMT_SPT_MSG_AGE0
;
717 pSPacket
->MessageAge
[1] = SK_RLMT_SPT_MSG_AGE1
;
718 pSPacket
->MaxAge
[0] = SK_RLMT_SPT_MAX_AGE0
;
719 pSPacket
->MaxAge
[1] = SK_RLMT_SPT_MAX_AGE1
;
720 pSPacket
->HelloTime
[0] = SK_RLMT_SPT_HELLO_TIME0
;
721 pSPacket
->HelloTime
[1] = SK_RLMT_SPT_HELLO_TIME1
;
722 pSPacket
->ForwardDelay
[0] = SK_RLMT_SPT_FWD_DELAY0
;
723 pSPacket
->ForwardDelay
[1] = SK_RLMT_SPT_FWD_DELAY1
;
725 Length
= SK_RLMT_MAX_PACKET_SIZE
; /* Or smaller. */
726 pMb
->Length
= Length
;
727 pMb
->PortIdx
= PortNumber
;
729 SK_U16_TO_NETWORK_ORDER(Length
, &pSPacket
->TypeLen
[0]);
731 pAC
->Rlmt
.Port
[PortNumber
].TxSpHelloReqCts
++;
735 } /* SkRlmtBuildSpanningTreePacket */
738 /******************************************************************************
740 * SkRlmtSend - build and send check packets
743 * Depending on the RLMT state and the checking state, several packets
744 * are sent through the indicated port.
752 RLMT_STATIC
void SkRlmtSend(
753 SK_AC
*pAC
, /* Adapter Context */
754 SK_IOC IoC
, /* I/O Context */
755 SK_U32 PortNumber
) /* Sending port */
759 SK_RLMT_PORT
*pRPort
;
761 pRPort
= &pAC
->Rlmt
.Port
[PortNumber
];
762 if (pAC
->Rlmt
.Port
[PortNumber
].Net
->RlmtMode
& SK_RLMT_CHECK_LOC_LINK
) {
763 if (pRPort
->CheckingState
& (SK_RLMT_PCS_TX
| SK_RLMT_PCS_RX
)) {
764 /* Port is suspicious. Send the RLMT packet to the RLMT mc addr. */
765 if ((Para
.pParaPtr
= SkRlmtBuildPacket(pAC
, IoC
, PortNumber
,
766 SK_PACKET_ALIVE
, &pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
,
767 &SkRlmtMcAddr
)) != NULL
) {
768 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_RLMT_SEND
, Para
);
773 * Send a directed RLMT packet to all ports that are
774 * checked by the indicated port.
776 for (j
= 0; j
< pRPort
->PortsChecked
; j
++) {
777 if ((Para
.pParaPtr
= SkRlmtBuildPacket(pAC
, IoC
, PortNumber
,
778 SK_PACKET_ALIVE
, &pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
,
779 &pRPort
->PortCheck
[j
].CheckAddr
)) != NULL
) {
780 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_RLMT_SEND
, Para
);
786 if ((pAC
->Rlmt
.Port
[PortNumber
].Net
->RlmtMode
& SK_RLMT_CHECK_SEG
) &&
787 (pAC
->Rlmt
.Port
[PortNumber
].Net
->CheckingState
& SK_RLMT_RCS_SEND_SEG
)) {
789 * Send a BPDU packet to make a connected switch tell us
790 * the correct root bridge.
793 SkRlmtBuildSpanningTreePacket(pAC
, IoC
, PortNumber
)) != NULL
) {
794 pAC
->Rlmt
.Port
[PortNumber
].Net
->CheckingState
&= ~SK_RLMT_RCS_SEND_SEG
;
795 pRPort
->RootIdSet
= SK_FALSE
;
797 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_RLMT_SEND
, Para
);
798 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_TX
,
799 ("SkRlmtSend: BPDU Packet on Port %u.\n", PortNumber
))
806 /******************************************************************************
808 * SkRlmtPortReceives - check if port is (going) down and bring it up
811 * This routine checks if a port who received a non-BPDU packet
812 * needs to go up or needs to be stopped going down.
820 RLMT_STATIC
void SkRlmtPortReceives(
821 SK_AC
*pAC
, /* Adapter Context */
822 SK_IOC IoC
, /* I/O Context */
823 SK_U32 PortNumber
) /* Port to check */
825 SK_RLMT_PORT
*pRPort
;
828 pRPort
= &pAC
->Rlmt
.Port
[PortNumber
];
829 pRPort
->PortNoRx
= SK_FALSE
;
831 if ((pRPort
->PortState
== SK_RLMT_PS_DOWN
) &&
832 !(pRPort
->CheckingState
& SK_RLMT_PCS_TX
)) {
834 * Port is marked down (rx), but received a non-BPDU packet.
837 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
838 ("SkRlmtPacketReceive: Received on PortDown.\n"))
840 pRPort
->PortState
= SK_RLMT_PS_GOING_UP
;
841 pRPort
->GuTimeStamp
= SkOsGetTime(pAC
);
842 Para
.Para32
[0] = PortNumber
;
843 Para
.Para32
[1] = (SK_U32
)-1;
844 SkTimerStart(pAC
, IoC
, &pRPort
->UpTimer
, SK_RLMT_PORTUP_TIM_VAL
,
845 SKGE_RLMT
, SK_RLMT_PORTUP_TIM
, Para
);
846 pRPort
->CheckingState
&= ~SK_RLMT_PCS_RX
;
847 /* pAC->Rlmt.CheckSwitch = SK_TRUE; */
848 SkRlmtCheckSwitch(pAC
, IoC
, pRPort
->Net
->NetNumber
);
849 } /* PortDown && !SuspectTx */
850 else if (pRPort
->CheckingState
& SK_RLMT_PCS_RX
) {
851 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
852 ("SkRlmtPacketReceive: Stop bringing port down.\n"))
853 SkTimerStop(pAC
, IoC
, &pRPort
->DownRxTimer
);
854 pRPort
->CheckingState
&= ~SK_RLMT_PCS_RX
;
855 /* pAC->Rlmt.CheckSwitch = SK_TRUE; */
856 SkRlmtCheckSwitch(pAC
, IoC
, pRPort
->Net
->NetNumber
);
857 } /* PortGoingDown */
860 } /* SkRlmtPortReceives */
863 /******************************************************************************
865 * SkRlmtPacketReceive - receive a packet for closer examination
868 * This routine examines a packet more closely than SK_RLMT_LOOKAHEAD.
876 RLMT_STATIC
void SkRlmtPacketReceive(
877 SK_AC
*pAC
, /* Adapter Context */
878 SK_IOC IoC
, /* I/O Context */
879 SK_MBUF
*pMb
) /* Received packet */
882 extern void DumpData(char *p
, int size
);
888 SK_ADDR_PORT
*pAPort
;
889 SK_RLMT_PORT
*pRPort
;
890 SK_RLMT_PACKET
*pRPacket
;
891 SK_SPTREE_PACKET
*pSPacket
;
894 PortNumber
= pMb
->PortIdx
;
895 pAPort
= &pAC
->Addr
.Port
[PortNumber
];
896 pRPort
= &pAC
->Rlmt
.Port
[PortNumber
];
898 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
899 ("SkRlmtPacketReceive: PortNumber == %d.\n", PortNumber
))
901 pRPacket
= (SK_RLMT_PACKET
*)pMb
->pData
;
902 pSPacket
= (SK_SPTREE_PACKET
*)pRPacket
;
905 DumpData((char *)pRPacket
, 32);
908 if ((pRPort
->PacketsPerTimeSlot
- pRPort
->BpduPacketsPerTimeSlot
) != 0) {
909 SkRlmtPortReceives(pAC
, IoC
, PortNumber
);
912 /* Check destination address. */
914 if (!SK_ADDR_EQUAL(pAPort
->CurrentMacAddress
.a
, pRPacket
->DstAddr
) &&
915 !SK_ADDR_EQUAL(SkRlmtMcAddr
.a
, pRPacket
->DstAddr
) &&
916 !SK_ADDR_EQUAL(BridgeMcAddr
.a
, pRPacket
->DstAddr
)) {
918 /* Not sent to current MAC or registered MC address => Trash it. */
919 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
920 ("SkRlmtPacketReceive: Not for me.\n"))
922 SkDrvFreeRlmtMbuf(pAC
, IoC
, pMb
);
925 else if (SK_ADDR_EQUAL(pAPort
->CurrentMacAddress
.a
, pRPacket
->SrcAddr
)) {
928 * Was sent by same port (may happen during port switching
929 * or in case of duplicate MAC addresses).
933 * Check for duplicate address here:
934 * If Packet.Random != My.Random => DupAddr.
936 for (i
= 3; i
>= 0; i
--) {
937 if (pRPort
->Random
[i
] != pRPacket
->Random
[i
]) {
943 * CAUTION: Do not check for duplicate MAC address in RLMT Alive Reply
944 * packets (they have the LLC_COMMAND_RESPONSE_BIT set in
947 if (i
>= 0 && pRPacket
->DSap
== SK_RLMT_DSAP
&&
948 pRPacket
->Ctrl
== SK_RLMT_CTRL
&&
949 pRPacket
->SSap
== SK_RLMT_SSAP
&&
950 pRPacket
->Indicator
[0] == SK_RLMT_INDICATOR0
&&
951 pRPacket
->Indicator
[1] == SK_RLMT_INDICATOR1
&&
952 pRPacket
->Indicator
[2] == SK_RLMT_INDICATOR2
&&
953 pRPacket
->Indicator
[3] == SK_RLMT_INDICATOR3
&&
954 pRPacket
->Indicator
[4] == SK_RLMT_INDICATOR4
&&
955 pRPacket
->Indicator
[5] == SK_RLMT_INDICATOR5
&&
956 pRPacket
->Indicator
[6] == SK_RLMT_INDICATOR6
) {
957 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
958 ("SkRlmtPacketReceive: Duplicate MAC Address.\n"))
960 /* Error Log entry. */
961 SK_ERR_LOG(pAC
, SK_ERRCL_COMM
, SKERR_RLMT_E006
, SKERR_RLMT_E006_MSG
);
964 /* Simply trash it. */
965 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
966 ("SkRlmtPacketReceive: Sent by me.\n"))
969 SkDrvFreeRlmtMbuf(pAC
, IoC
, pMb
);
973 /* Check SuspectTx entries. */
974 if (pRPort
->PortsSuspect
> 0) {
975 for (j
= 0; j
< pRPort
->PortsChecked
; j
++) {
976 if (pRPort
->PortCheck
[j
].SuspectTx
&&
978 pRPacket
->SrcAddr
, pRPort
->PortCheck
[j
].CheckAddr
.a
)) {
979 pRPort
->PortCheck
[j
].SuspectTx
= SK_FALSE
;
980 pRPort
->PortsSuspect
--;
986 /* Determine type of packet. */
987 if (pRPacket
->DSap
== SK_RLMT_DSAP
&&
988 pRPacket
->Ctrl
== SK_RLMT_CTRL
&&
989 (pRPacket
->SSap
& ~LLC_COMMAND_RESPONSE_BIT
) == SK_RLMT_SSAP
&&
990 pRPacket
->Indicator
[0] == SK_RLMT_INDICATOR0
&&
991 pRPacket
->Indicator
[1] == SK_RLMT_INDICATOR1
&&
992 pRPacket
->Indicator
[2] == SK_RLMT_INDICATOR2
&&
993 pRPacket
->Indicator
[3] == SK_RLMT_INDICATOR3
&&
994 pRPacket
->Indicator
[4] == SK_RLMT_INDICATOR4
&&
995 pRPacket
->Indicator
[5] == SK_RLMT_INDICATOR5
&&
996 pRPacket
->Indicator
[6] == SK_RLMT_INDICATOR6
) {
998 /* It's an RLMT packet. */
999 PacketType
= (SK_U16
)((pRPacket
->RlmtPacketType
[0] << 8) |
1000 pRPacket
->RlmtPacketType
[1]);
1002 switch (PacketType
) {
1003 case SK_PACKET_ANNOUNCE
: /* Not yet used. */
1005 /* Build the check chain. */
1006 SkRlmtBuildCheckChain(pAC
);
1009 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
1010 ("SkRlmtPacketReceive: Announce.\n"))
1012 SkDrvFreeRlmtMbuf(pAC
, IoC
, pMb
);
1015 case SK_PACKET_ALIVE
:
1016 if (pRPacket
->SSap
& LLC_COMMAND_RESPONSE_BIT
) {
1017 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
1018 ("SkRlmtPacketReceive: Alive Reply.\n"))
1020 if (!(pAC
->Addr
.Port
[PortNumber
].PromMode
& SK_PROM_MODE_LLC
) ||
1022 pRPacket
->DstAddr
, pAPort
->CurrentMacAddress
.a
)) {
1023 /* Obviously we could send something. */
1024 if (pRPort
->CheckingState
& SK_RLMT_PCS_TX
) {
1025 pRPort
->CheckingState
&= ~SK_RLMT_PCS_TX
;
1026 SkTimerStop(pAC
, IoC
, &pRPort
->DownTxTimer
);
1029 if ((pRPort
->PortState
== SK_RLMT_PS_DOWN
) &&
1030 !(pRPort
->CheckingState
& SK_RLMT_PCS_RX
)) {
1031 pRPort
->PortState
= SK_RLMT_PS_GOING_UP
;
1032 pRPort
->GuTimeStamp
= SkOsGetTime(pAC
);
1034 SkTimerStop(pAC
, IoC
, &pRPort
->DownTxTimer
);
1036 Para
.Para32
[0] = PortNumber
;
1037 Para
.Para32
[1] = (SK_U32
)-1;
1038 SkTimerStart(pAC
, IoC
, &pRPort
->UpTimer
,
1039 SK_RLMT_PORTUP_TIM_VAL
, SKGE_RLMT
,
1040 SK_RLMT_PORTUP_TIM
, Para
);
1044 /* Mark sending port as alive? */
1045 SkDrvFreeRlmtMbuf(pAC
, IoC
, pMb
);
1047 else { /* Alive Request Packet. */
1048 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
1049 ("SkRlmtPacketReceive: Alive Request.\n"))
1051 pRPort
->RxHelloCts
++;
1054 for (i
= 0; i
< SK_MAC_ADDR_LEN
; i
++) {
1055 pRPacket
->DstAddr
[i
] = pRPacket
->SrcAddr
[i
];
1056 pRPacket
->SrcAddr
[i
] =
1057 pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
.a
[i
];
1059 pRPacket
->SSap
|= LLC_COMMAND_RESPONSE_BIT
;
1061 Para
.pParaPtr
= pMb
;
1062 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_RLMT_SEND
, Para
);
1066 case SK_PACKET_CHECK_TX
:
1067 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
1068 ("SkRlmtPacketReceive: Check your tx line.\n"))
1070 /* A port checking us requests us to check our tx line. */
1071 pRPort
->CheckingState
|= SK_RLMT_PCS_TX
;
1073 /* Start PortDownTx timer. */
1074 Para
.Para32
[0] = PortNumber
;
1075 Para
.Para32
[1] = (SK_U32
)-1;
1076 SkTimerStart(pAC
, IoC
, &pRPort
->DownTxTimer
,
1077 SK_RLMT_PORTDOWN_TIM_VAL
, SKGE_RLMT
,
1078 SK_RLMT_PORTDOWN_TX_TIM
, Para
);
1080 SkDrvFreeRlmtMbuf(pAC
, IoC
, pMb
);
1082 if ((Para
.pParaPtr
= SkRlmtBuildPacket(pAC
, IoC
, PortNumber
,
1083 SK_PACKET_ALIVE
, &pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
,
1084 &SkRlmtMcAddr
)) != NULL
) {
1085 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_RLMT_SEND
, Para
);
1089 case SK_PACKET_ADDR_CHANGED
:
1090 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
1091 ("SkRlmtPacketReceive: Address Change.\n"))
1093 /* Build the check chain. */
1094 SkRlmtBuildCheckChain(pAC
, pRPort
->Net
->NetNumber
);
1095 SkDrvFreeRlmtMbuf(pAC
, IoC
, pMb
);
1099 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
1100 ("SkRlmtPacketReceive: Unknown RLMT packet.\n"))
1103 SkDrvFreeRlmtMbuf(pAC
, IoC
, pMb
);
1106 else if (pSPacket
->DSap
== SK_RLMT_SPT_DSAP
&&
1107 pSPacket
->Ctrl
== SK_RLMT_SPT_CTRL
&&
1108 (pSPacket
->SSap
& ~LLC_COMMAND_RESPONSE_BIT
) == SK_RLMT_SPT_SSAP
) {
1109 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
1110 ("SkRlmtPacketReceive: BPDU Packet.\n"))
1112 /* Spanning Tree packet. */
1113 pRPort
->RxSpHelloCts
++;
1115 if (!SK_ADDR_EQUAL(&pSPacket
->RootId
[2], &pAC
->Addr
.Net
[pAC
->Rlmt
.
1116 Port
[PortNumber
].Net
->NetNumber
].CurrentMacAddress
.a
[0])) {
1118 * Check segmentation if a new root bridge is set and
1119 * the segmentation check is not currently running.
1121 if (!SK_ADDR_EQUAL(&pSPacket
->RootId
[2], &pRPort
->Root
.Id
[2]) &&
1122 (pAC
->Rlmt
.Port
[PortNumber
].Net
->LinksUp
> 1) &&
1123 (pAC
->Rlmt
.Port
[PortNumber
].Net
->RlmtMode
& SK_RLMT_CHECK_SEG
)
1124 != 0 && (pAC
->Rlmt
.Port
[PortNumber
].Net
->CheckingState
&
1125 SK_RLMT_RCS_SEG
) == 0) {
1126 pAC
->Rlmt
.Port
[PortNumber
].Net
->CheckingState
|=
1127 SK_RLMT_RCS_START_SEG
| SK_RLMT_RCS_SEND_SEG
;
1130 /* Store tree view of this port. */
1131 for (i
= 0; i
< 8; i
++) {
1132 pRPort
->Root
.Id
[i
] = pSPacket
->RootId
[i
];
1134 pRPort
->RootIdSet
= SK_TRUE
;
1136 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_DUMP
,
1137 ("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n",
1139 pRPort
->Root
.Id
[0], pRPort
->Root
.Id
[1],
1140 pRPort
->Root
.Id
[2], pRPort
->Root
.Id
[3],
1141 pRPort
->Root
.Id
[4], pRPort
->Root
.Id
[5],
1142 pRPort
->Root
.Id
[6], pRPort
->Root
.Id
[7]))
1145 SkDrvFreeRlmtMbuf(pAC
, IoC
, pMb
);
1146 if ((pAC
->Rlmt
.Port
[PortNumber
].Net
->CheckingState
&
1147 SK_RLMT_RCS_REPORT_SEG
) != 0) {
1148 SkRlmtCheckSeg(pAC
, IoC
, pAC
->Rlmt
.Port
[PortNumber
].Net
->NetNumber
);
1152 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
1153 ("SkRlmtPacketReceive: Unknown Packet Type.\n"))
1155 /* Unknown packet. */
1156 SkDrvFreeRlmtMbuf(pAC
, IoC
, pMb
);
1159 } /* SkRlmtPacketReceive */
1162 /******************************************************************************
1164 * SkRlmtCheckPort - check if a port works
1167 * This routine checks if a port whose link is up received something
1168 * and if it seems to transmit successfully.
1170 * # PortState: PsInit, PsLinkDown, PsDown, PsGoingUp, PsUp
1171 * # PortCheckingState (Bitfield): ChkTx, ChkRx, ChkSeg
1172 * # RlmtCheckingState (Bitfield): ChkSeg, StartChkSeg, ReportSeg
1174 * if (Rx - RxBpdu == 0) { # No rx.
1175 * if (state == PsUp) {
1176 * PortCheckingState |= ChkRx
1178 * if (ModeCheckSeg && (Timeout ==
1179 * TO_SHORTEN(RLMT_DEFAULT_TIMEOUT))) {
1180 * RlmtCheckingState |= ChkSeg)
1181 * PortCheckingState |= ChkSeg
1183 * NewTimeout = TO_SHORTEN(Timeout)
1184 * if (NewTimeout < RLMT_MIN_TIMEOUT) {
1185 * NewTimeout = RLMT_MIN_TIMEOUT
1186 * PortState = PsDown
1190 * else { # something was received
1191 * # Set counter to 0 at LinkDown?
1192 * # No - rx may be reported after LinkDown ???
1193 * PortCheckingState &= ~ChkRx
1194 * NewTimeout = RLMT_DEFAULT_TIMEOUT
1197 * is my tx line bad? --
1198 * send RLMT multicast and report
1199 * back internally? (only possible
1200 * between ports on same adapter)
1204 * - tx line of port set to check me
1206 * - no other port/adapter available or set
1208 * - adapter checking me has a longer
1210 * ??? anything that can be done here?
1215 * runtime, pageable?
1218 * New timeout value.
1220 RLMT_STATIC SK_U32
SkRlmtCheckPort(
1221 SK_AC
*pAC
, /* Adapter Context */
1222 SK_IOC IoC
, /* I/O Context */
1223 SK_U32 PortNumber
) /* Port to check */
1227 SK_RLMT_PORT
*pRPort
;
1230 pRPort
= &pAC
->Rlmt
.Port
[PortNumber
];
1232 if ((pRPort
->PacketsPerTimeSlot
- pRPort
->BpduPacketsPerTimeSlot
) == 0) {
1233 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1234 ("SkRlmtCheckPort %d: No (%d) receives in last time slot.\n",
1235 PortNumber
, pRPort
->PacketsPerTimeSlot
))
1238 * Check segmentation if there was no receive at least twice
1239 * in a row (PortNoRx is already set) and the segmentation
1240 * check is not currently running.
1243 if (pRPort
->PortNoRx
&& (pAC
->Rlmt
.Port
[PortNumber
].Net
->LinksUp
> 1) &&
1244 (pAC
->Rlmt
.Port
[PortNumber
].Net
->RlmtMode
& SK_RLMT_CHECK_SEG
) &&
1245 !(pAC
->Rlmt
.Port
[PortNumber
].Net
->CheckingState
& SK_RLMT_RCS_SEG
)) {
1246 pAC
->Rlmt
.Port
[PortNumber
].Net
->CheckingState
|=
1247 SK_RLMT_RCS_START_SEG
| SK_RLMT_RCS_SEND_SEG
;
1250 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1251 ("SkRlmtCheckPort: PortsSuspect %d, PcsRx %d.\n",
1252 pRPort
->PortsSuspect
, pRPort
->CheckingState
& SK_RLMT_PCS_RX
))
1254 if (pRPort
->PortState
!= SK_RLMT_PS_DOWN
) {
1255 NewTimeout
= TO_SHORTEN(pAC
->Rlmt
.Port
[PortNumber
].Net
->TimeoutValue
);
1256 if (NewTimeout
< SK_RLMT_MIN_TO_VAL
) {
1257 NewTimeout
= SK_RLMT_MIN_TO_VAL
;
1260 if (!(pRPort
->CheckingState
& SK_RLMT_PCS_RX
)) {
1261 Para
.Para32
[0] = PortNumber
;
1262 pRPort
->CheckingState
|= SK_RLMT_PCS_RX
;
1265 * What shall we do if the port checked by this one receives
1266 * our request frames? What's bad - our rx line or his tx line?
1268 Para
.Para32
[1] = (SK_U32
)-1;
1269 SkTimerStart(pAC
, IoC
, &pRPort
->DownRxTimer
,
1270 SK_RLMT_PORTDOWN_TIM_VAL
, SKGE_RLMT
,
1271 SK_RLMT_PORTDOWN_RX_TIM
, Para
);
1273 for (i
= 0; i
< pRPort
->PortsChecked
; i
++) {
1274 if (pRPort
->PortCheck
[i
].SuspectTx
) {
1277 pRPort
->PortCheck
[i
].SuspectTx
= SK_TRUE
;
1278 pRPort
->PortsSuspect
++;
1279 if ((Para
.pParaPtr
=
1280 SkRlmtBuildPacket(pAC
, IoC
, PortNumber
, SK_PACKET_CHECK_TX
,
1281 &pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
,
1282 &pRPort
->PortCheck
[i
].CheckAddr
)) != NULL
) {
1283 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_RLMT_SEND
, Para
);
1288 else { /* PortDown -- or all partners suspect. */
1289 NewTimeout
= SK_RLMT_DEF_TO_VAL
;
1291 pRPort
->PortNoRx
= SK_TRUE
;
1293 else { /* A non-BPDU packet was received. */
1294 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1295 ("SkRlmtCheckPort %d: %d (%d) receives in last time slot.\n",
1297 pRPort
->PacketsPerTimeSlot
- pRPort
->BpduPacketsPerTimeSlot
,
1298 pRPort
->PacketsPerTimeSlot
))
1300 SkRlmtPortReceives(pAC
, IoC
, PortNumber
);
1301 if (pAC
->Rlmt
.CheckSwitch
) {
1302 SkRlmtCheckSwitch(pAC
, IoC
, pRPort
->Net
->NetNumber
);
1305 NewTimeout
= SK_RLMT_DEF_TO_VAL
;
1308 return (NewTimeout
);
1309 } /* SkRlmtCheckPort */
1312 /******************************************************************************
1314 * SkRlmtSelectBcRx - select new active port, criteria 1 (CLP)
1317 * This routine selects the port that received a broadcast frame
1318 * substantially later than all other ports.
1321 * runtime, pageable?
1326 RLMT_STATIC SK_BOOL
SkRlmtSelectBcRx(
1327 SK_AC
*pAC
, /* Adapter Context */
1328 SK_IOC IoC
, /* I/O Context */
1329 SK_U32 Active
, /* Active port */
1330 SK_U32 PrefPort
, /* Preferred port */
1331 SK_U32
*pSelect
) /* New active port */
1337 BcTimeStamp
= 0; /* Not totally necessary, but feeling better. */
1338 PortFound
= SK_FALSE
;
1340 /* Select port with the latest TimeStamp. */
1341 for (i
= 0; i
< (SK_U32
)pAC
->GIni
.GIMacsFound
; i
++) {
1343 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1344 ("TimeStamp Port %d (Down: %d, NoRx: %d): %08x %08x.\n",
1346 pAC
->Rlmt
.Port
[i
].PortDown
, pAC
->Rlmt
.Port
[i
].PortNoRx
,
1347 *((SK_U32
*)(&pAC
->Rlmt
.Port
[i
].BcTimeStamp
) + OFFS_HI32
),
1348 *((SK_U32
*)(&pAC
->Rlmt
.Port
[i
].BcTimeStamp
) + OFFS_LO32
)))
1350 if (!pAC
->Rlmt
.Port
[i
].PortDown
&& !pAC
->Rlmt
.Port
[i
].PortNoRx
) {
1351 if (!PortFound
|| pAC
->Rlmt
.Port
[i
].BcTimeStamp
> BcTimeStamp
) {
1352 BcTimeStamp
= pAC
->Rlmt
.Port
[i
].BcTimeStamp
;
1354 PortFound
= SK_TRUE
;
1360 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1361 ("Port %d received the last broadcast.\n", *pSelect
))
1363 /* Look if another port's time stamp is similar. */
1364 for (i
= 0; i
< (SK_U32
)pAC
->GIni
.GIMacsFound
; i
++) {
1365 if (i
== *pSelect
) {
1368 if (!pAC
->Rlmt
.Port
[i
].PortDown
&& !pAC
->Rlmt
.Port
[i
].PortNoRx
&&
1369 (pAC
->Rlmt
.Port
[i
].BcTimeStamp
>
1370 BcTimeStamp
- SK_RLMT_BC_DELTA
||
1371 pAC
->Rlmt
.Port
[i
].BcTimeStamp
+
1372 SK_RLMT_BC_DELTA
> BcTimeStamp
)) {
1373 PortFound
= SK_FALSE
;
1375 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1376 ("Port %d received a broadcast at a similar time.\n", i
))
1384 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1385 ("SK_RLMT_SELECT_BCRX found Port %d receiving the substantially "
1386 "latest broadcast (%u).\n",
1388 BcTimeStamp
- pAC
->Rlmt
.Port
[1 - *pSelect
].BcTimeStamp
))
1393 } /* SkRlmtSelectBcRx */
1396 /******************************************************************************
1398 * SkRlmtSelectNotSuspect - select new active port, criteria 2 (CLP)
1401 * This routine selects a good port (it is PortUp && !SuspectRx).
1404 * runtime, pageable?
1409 RLMT_STATIC SK_BOOL
SkRlmtSelectNotSuspect(
1410 SK_AC
*pAC
, /* Adapter Context */
1411 SK_IOC IoC
, /* I/O Context */
1412 SK_U32 Active
, /* Active port */
1413 SK_U32 PrefPort
, /* Preferred port */
1414 SK_U32
*pSelect
) /* New active port */
1419 PortFound
= SK_FALSE
;
1421 /* Select first port that is PortUp && !SuspectRx. */
1422 for (i
= 0; i
< (SK_U32
)pAC
->GIni
.GIMacsFound
; i
++) {
1423 if (!pAC
->Rlmt
.Port
[i
].PortDown
&&
1424 !(pAC
->Rlmt
.Port
[i
].CheckingState
& SK_RLMT_PCS_RX
)) {
1426 if (!pAC
->Rlmt
.Port
[Active
].PortDown
&&
1427 !(pAC
->Rlmt
.Port
[Active
].CheckingState
& SK_RLMT_PCS_RX
)) {
1430 if (!pAC
->Rlmt
.Port
[PrefPort
].PortDown
&&
1431 !(pAC
->Rlmt
.Port
[PrefPort
].CheckingState
& SK_RLMT_PCS_RX
)) {
1432 *pSelect
= PrefPort
;
1434 PortFound
= SK_TRUE
;
1435 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1436 ("SK_RLMT_SELECT_NOTSUSPECT found Port %d up and not check RX.\n",
1442 } /* SkRlmtSelectNotSuspect */
1445 /******************************************************************************
1447 * SkRlmtSelectUp - select new active port, criteria 3, 4 (CLP)
1450 * This routine selects a port that is up.
1453 * runtime, pageable?
1458 RLMT_STATIC SK_BOOL
SkRlmtSelectUp(
1459 SK_AC
*pAC
, /* Adapter Context */
1460 SK_IOC IoC
, /* I/O Context */
1461 SK_U32 Active
, /* Active port */
1462 SK_U32 PrefPort
, /* Preferred port */
1463 SK_U32
*pSelect
, /* New active port */
1464 SK_BOOL AutoNegDone
) /* Successfully auto-negotiated? */
1469 PortFound
= SK_FALSE
;
1471 /* Select first port that is PortUp. */
1472 for (i
= 0; i
< (SK_U32
)pAC
->GIni
.GIMacsFound
; i
++) {
1473 if (pAC
->Rlmt
.Port
[i
].PortState
== SK_RLMT_PS_UP
&&
1474 pAC
->GIni
.GP
[i
].PAutoNegFail
!= AutoNegDone
) {
1476 if (pAC
->Rlmt
.Port
[Active
].PortState
== SK_RLMT_PS_UP
&&
1477 pAC
->GIni
.GP
[Active
].PAutoNegFail
!= AutoNegDone
) {
1480 if (pAC
->Rlmt
.Port
[PrefPort
].PortState
== SK_RLMT_PS_UP
&&
1481 pAC
->GIni
.GP
[PrefPort
].PAutoNegFail
!= AutoNegDone
) {
1482 *pSelect
= PrefPort
;
1484 PortFound
= SK_TRUE
;
1485 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1486 ("SK_RLMT_SELECT_UP found Port %d up.\n", *pSelect
))
1491 } /* SkRlmtSelectUp */
1494 /******************************************************************************
1496 * SkRlmtSelectGoingUp - select new active port, criteria 5, 6 (CLP)
1499 * This routine selects the port that is going up for the longest time.
1502 * runtime, pageable?
1507 RLMT_STATIC SK_BOOL
SkRlmtSelectGoingUp(
1508 SK_AC
*pAC
, /* Adapter Context */
1509 SK_IOC IoC
, /* I/O Context */
1510 SK_U32 Active
, /* Active port */
1511 SK_U32 PrefPort
, /* Preferred port */
1512 SK_U32
*pSelect
, /* New active port */
1513 SK_BOOL AutoNegDone
) /* Successfully auto-negotiated? */
1520 PortFound
= SK_FALSE
;
1522 /* Select port that is PortGoingUp for the longest time. */
1523 for (i
= 0; i
< (SK_U32
)pAC
->GIni
.GIMacsFound
; i
++) {
1524 if (pAC
->Rlmt
.Port
[i
].PortState
== SK_RLMT_PS_GOING_UP
&&
1525 pAC
->GIni
.GP
[i
].PAutoNegFail
!= AutoNegDone
) {
1526 GuTimeStamp
= pAC
->Rlmt
.Port
[i
].GuTimeStamp
;
1528 PortFound
= SK_TRUE
;
1537 for (i
= *pSelect
+ 1; i
< (SK_U32
)pAC
->GIni
.GIMacsFound
; i
++) {
1538 if (pAC
->Rlmt
.Port
[i
].PortState
== SK_RLMT_PS_GOING_UP
&&
1539 pAC
->Rlmt
.Port
[i
].GuTimeStamp
< GuTimeStamp
&&
1540 pAC
->GIni
.GP
[i
].PAutoNegFail
!= AutoNegDone
) {
1541 GuTimeStamp
= pAC
->Rlmt
.Port
[i
].GuTimeStamp
;
1546 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1547 ("SK_RLMT_SELECT_GOINGUP found Port %d going up.\n", *pSelect
))
1549 } /* SkRlmtSelectGoingUp */
1552 /******************************************************************************
1554 * SkRlmtSelectDown - select new active port, criteria 7, 8 (CLP)
1557 * This routine selects a port that is down.
1560 * runtime, pageable?
1565 RLMT_STATIC SK_BOOL
SkRlmtSelectDown(
1566 SK_AC
*pAC
, /* Adapter Context */
1567 SK_IOC IoC
, /* I/O Context */
1568 SK_U32 Active
, /* Active port */
1569 SK_U32 PrefPort
, /* Preferred port */
1570 SK_U32
*pSelect
, /* New active port */
1571 SK_BOOL AutoNegDone
) /* Successfully auto-negotiated? */
1576 PortFound
= SK_FALSE
;
1578 /* Select first port that is PortDown. */
1579 for (i
= 0; i
< (SK_U32
)pAC
->GIni
.GIMacsFound
; i
++) {
1580 if (pAC
->Rlmt
.Port
[i
].PortState
== SK_RLMT_PS_DOWN
&&
1581 pAC
->GIni
.GP
[i
].PAutoNegFail
!= AutoNegDone
) {
1583 if (pAC
->Rlmt
.Port
[Active
].PortState
== SK_RLMT_PS_DOWN
&&
1584 pAC
->GIni
.GP
[Active
].PAutoNegFail
!= AutoNegDone
) {
1587 if (pAC
->Rlmt
.Port
[PrefPort
].PortState
== SK_RLMT_PS_DOWN
&&
1588 pAC
->GIni
.GP
[PrefPort
].PAutoNegFail
!= AutoNegDone
) {
1589 *pSelect
= PrefPort
;
1591 PortFound
= SK_TRUE
;
1592 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1593 ("SK_RLMT_SELECT_DOWN found Port %d down.\n", *pSelect
))
1598 } /* SkRlmtSelectDown */
1601 /******************************************************************************
1603 * SkRlmtCheckSwitch - select new active port and switch to it
1606 * This routine decides which port should be the active one and queues
1607 * port switching if necessary.
1610 * runtime, pageable?
1615 RLMT_STATIC
void SkRlmtCheckSwitch(
1616 SK_AC
*pAC
, /* Adapter Context */
1617 SK_IOC IoC
, /* I/O Context */
1618 SK_U32 NetIdx
) /* Net index */
1626 Active
= pAC
->Rlmt
.Net
[NetIdx
].ActivePort
; /* Index of active port. */
1627 PrefPort
= pAC
->Rlmt
.Net
[NetIdx
].PrefPort
; /* Index of preferred port. */
1628 PortFound
= SK_FALSE
;
1629 pAC
->Rlmt
.CheckSwitch
= SK_FALSE
;
1631 #if 0 /* RW 2001/10/18 - active port becomes always prefered one */
1632 if (pAC
->Rlmt
.Net
[NetIdx
].Preference
== 0xFFFFFFFF) { /* Automatic */
1633 /* disable auto-fail back */
1638 if (pAC
->Rlmt
.Net
[NetIdx
].LinksUp
== 0) {
1639 /* Last link went down - shut down the net. */
1640 pAC
->Rlmt
.Net
[NetIdx
].RlmtState
= SK_RLMT_RS_NET_DOWN
;
1641 Para
.Para32
[0] = SK_RLMT_NET_DOWN_TEMP
;
1642 Para
.Para32
[1] = NetIdx
;
1643 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_NET_DOWN
, Para
);
1645 Para
.Para32
[0] = pAC
->Rlmt
.Net
[NetIdx
].
1646 Port
[pAC
->Rlmt
.Net
[NetIdx
].ActivePort
]->PortNumber
;
1647 Para
.Para32
[1] = NetIdx
;
1648 SkEventQueue(pAC
, SKGE_PNMI
, SK_PNMI_EVT_RLMT_ACTIVE_DOWN
, Para
);
1650 } /* pAC->Rlmt.LinksUp == 0 */
1651 else if (pAC
->Rlmt
.Net
[NetIdx
].LinksUp
== 1 &&
1652 pAC
->Rlmt
.Net
[NetIdx
].RlmtState
== SK_RLMT_RS_NET_DOWN
) {
1653 /* First link came up - get the net up. */
1654 pAC
->Rlmt
.Net
[NetIdx
].RlmtState
= SK_RLMT_RS_NET_UP
;
1657 * If pAC->Rlmt.ActivePort != Para.Para32[0],
1658 * the DRV switches to the port that came up.
1660 for (i
= 0; i
< pAC
->Rlmt
.Net
[NetIdx
].NumPorts
; i
++) {
1661 if (!pAC
->Rlmt
.Net
[NetIdx
].Port
[i
]->LinkDown
) {
1662 if (!pAC
->Rlmt
.Net
[NetIdx
].Port
[Active
]->LinkDown
) {
1665 if (!pAC
->Rlmt
.Net
[NetIdx
].Port
[PrefPort
]->LinkDown
) {
1668 PortFound
= SK_TRUE
;
1674 Para
.Para32
[0] = pAC
->Rlmt
.Net
[NetIdx
].Port
[i
]->PortNumber
;
1675 Para
.Para32
[1] = NetIdx
;
1676 SkEventQueue(pAC
, SKGE_PNMI
, SK_PNMI_EVT_RLMT_ACTIVE_UP
, Para
);
1678 pAC
->Rlmt
.Net
[NetIdx
].ActivePort
= i
;
1679 Para
.Para32
[0] = pAC
->Rlmt
.Net
[NetIdx
].Port
[i
]->PortNumber
;
1680 Para
.Para32
[1] = NetIdx
;
1681 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_NET_UP
, Para
);
1683 if ((pAC
->Rlmt
.Net
[NetIdx
].RlmtMode
& SK_RLMT_TRANSPARENT
) == 0 &&
1684 (Para
.pParaPtr
= SkRlmtBuildPacket(pAC
, IoC
,
1685 pAC
->Rlmt
.Net
[NetIdx
].Port
[i
]->PortNumber
,
1686 SK_PACKET_ANNOUNCE
, &pAC
->Addr
.Net
[NetIdx
].
1687 CurrentMacAddress
, &SkRlmtMcAddr
)) != NULL
) {
1689 * Send announce packet to RLMT multicast address to force
1690 * switches to learn the new location of the logical MAC address.
1692 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_RLMT_SEND
, Para
);
1696 SK_ERR_LOG(pAC
, SK_ERRCL_SW
, SKERR_RLMT_E007
, SKERR_RLMT_E007_MSG
);
1700 } /* LinksUp == 1 && RlmtState == SK_RLMT_RS_NET_DOWN */
1701 else { /* Cannot be reached in dual-net mode. */
1702 Para
.Para32
[0] = Active
;
1706 * If RLMT Mode != CheckLinkState
1707 * select port that received a broadcast frame substantially later
1708 * than all other ports
1709 * else select first port that is not SuspectRx
1710 * else select first port that is PortUp
1711 * else select port that is PortGoingUp for the longest time
1712 * else select first port that is PortDown
1715 * For the preselected port:
1716 * If ActivePort is equal in quality, select ActivePort.
1718 * If PrefPort is equal in quality, select PrefPort.
1720 * If ActivePort != SelectedPort,
1721 * If old ActivePort is LinkDown,
1726 /* check of ChgBcPrio flag added */
1727 if ((pAC
->Rlmt
.Net
[0].RlmtMode
!= SK_RLMT_MODE_CLS
) &&
1728 (!pAC
->Rlmt
.Net
[0].ChgBcPrio
)) {
1731 PortFound
= SkRlmtSelectBcRx(
1732 pAC
, IoC
, Active
, PrefPort
, &Para
.Para32
[1]);
1736 PortFound
= SkRlmtSelectNotSuspect(
1737 pAC
, IoC
, Active
, PrefPort
, &Para
.Para32
[1]);
1739 } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
1741 /* with changed priority for last broadcast received */
1742 if ((pAC
->Rlmt
.Net
[0].RlmtMode
!= SK_RLMT_MODE_CLS
) &&
1743 (pAC
->Rlmt
.Net
[0].ChgBcPrio
)) {
1745 PortFound
= SkRlmtSelectNotSuspect(
1746 pAC
, IoC
, Active
, PrefPort
, &Para
.Para32
[1]);
1750 PortFound
= SkRlmtSelectBcRx(
1751 pAC
, IoC
, Active
, PrefPort
, &Para
.Para32
[1]);
1753 } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
1756 PortFound
= SkRlmtSelectUp(
1757 pAC
, IoC
, Active
, PrefPort
, &Para
.Para32
[1], AUTONEG_SUCCESS
);
1761 PortFound
= SkRlmtSelectUp(
1762 pAC
, IoC
, Active
, PrefPort
, &Para
.Para32
[1], AUTONEG_FAILED
);
1766 PortFound
= SkRlmtSelectGoingUp(
1767 pAC
, IoC
, Active
, PrefPort
, &Para
.Para32
[1], AUTONEG_SUCCESS
);
1771 PortFound
= SkRlmtSelectGoingUp(
1772 pAC
, IoC
, Active
, PrefPort
, &Para
.Para32
[1], AUTONEG_FAILED
);
1775 if (pAC
->Rlmt
.Net
[0].RlmtMode
!= SK_RLMT_MODE_CLS
) {
1777 PortFound
= SkRlmtSelectDown(pAC
, IoC
,
1778 Active
, PrefPort
, &Para
.Para32
[1], AUTONEG_SUCCESS
);
1782 PortFound
= SkRlmtSelectDown(pAC
, IoC
,
1783 Active
, PrefPort
, &Para
.Para32
[1], AUTONEG_FAILED
);
1785 } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
1789 if (Para
.Para32
[1] != Active
) {
1790 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1791 ("Active: %d, Para1: %d.\n", Active
, Para
.Para32
[1]))
1792 pAC
->Rlmt
.Net
[NetIdx
].ActivePort
= Para
.Para32
[1];
1793 Para
.Para32
[0] = pAC
->Rlmt
.Net
[NetIdx
].
1794 Port
[Para
.Para32
[0]]->PortNumber
;
1795 Para
.Para32
[1] = pAC
->Rlmt
.Net
[NetIdx
].
1796 Port
[Para
.Para32
[1]]->PortNumber
;
1797 SK_HWAC_LINK_LED(pAC
, IoC
, Para
.Para32
[1], SK_LED_ACTIVE
);
1798 if (pAC
->Rlmt
.Port
[Active
].LinkDown
) {
1799 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_SWITCH_HARD
, Para
);
1802 SK_HWAC_LINK_LED(pAC
, IoC
, Para
.Para32
[0], SK_LED_STANDBY
);
1803 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_SWITCH_SOFT
, Para
);
1805 Para
.Para32
[1] = NetIdx
;
1807 pAC
->Rlmt
.Net
[NetIdx
].Port
[Para
.Para32
[0]]->PortNumber
;
1808 SkEventQueue(pAC
, SKGE_PNMI
, SK_PNMI_EVT_RLMT_ACTIVE_DOWN
, Para
);
1809 Para
.Para32
[0] = pAC
->Rlmt
.Net
[NetIdx
].
1810 Port
[pAC
->Rlmt
.Net
[NetIdx
].ActivePort
]->PortNumber
;
1811 SkEventQueue(pAC
, SKGE_PNMI
, SK_PNMI_EVT_RLMT_ACTIVE_UP
, Para
);
1812 if ((pAC
->Rlmt
.Net
[NetIdx
].RlmtMode
& SK_RLMT_TRANSPARENT
) == 0 &&
1813 (Para
.pParaPtr
= SkRlmtBuildPacket(pAC
, IoC
, Para
.Para32
[0],
1814 SK_PACKET_ANNOUNCE
, &pAC
->Addr
.Net
[NetIdx
].CurrentMacAddress
,
1815 &SkRlmtMcAddr
)) != NULL
) {
1817 * Send announce packet to RLMT multicast address to force
1818 * switches to learn the new location of the logical
1821 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_RLMT_SEND
, Para
);
1822 } /* (Para.pParaPtr = SkRlmtBuildPacket(...)) != NULL */
1823 } /* Para.Para32[1] != Active */
1826 SK_ERR_LOG(pAC
, SK_ERRCL_SW
, SKERR_RLMT_E004
, SKERR_RLMT_E004_MSG
);
1828 } /* LinksUp > 1 || LinksUp == 1 && RlmtState != SK_RLMT_RS_NET_DOWN */
1830 } /* SkRlmtCheckSwitch */
1833 /******************************************************************************
1835 * SkRlmtCheckSeg - Report if segmentation is detected
1838 * This routine checks if the ports see different root bridges and reports
1839 * segmentation in such a case.
1842 * runtime, pageable?
1847 RLMT_STATIC
void SkRlmtCheckSeg(
1848 SK_AC
*pAC
, /* Adapter Context */
1849 SK_IOC IoC
, /* I/O Context */
1850 SK_U32 NetIdx
) /* Net number */
1857 pNet
= &pAC
->Rlmt
.Net
[NetIdx
];
1858 pNet
->RootIdSet
= SK_FALSE
;
1861 for (i
= 0; i
< pNet
->NumPorts
; i
++) {
1862 if (pNet
->Port
[i
]->LinkDown
|| !pNet
->Port
[i
]->RootIdSet
) {
1866 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_DUMP
,
1867 ("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n", i
,
1868 pNet
->Port
[i
]->Root
.Id
[0], pNet
->Port
[i
]->Root
.Id
[1],
1869 pNet
->Port
[i
]->Root
.Id
[2], pNet
->Port
[i
]->Root
.Id
[3],
1870 pNet
->Port
[i
]->Root
.Id
[4], pNet
->Port
[i
]->Root
.Id
[5],
1871 pNet
->Port
[i
]->Root
.Id
[6], pNet
->Port
[i
]->Root
.Id
[7]))
1873 if (!pNet
->RootIdSet
) {
1874 pNet
->Root
= pNet
->Port
[i
]->Root
;
1875 pNet
->RootIdSet
= SK_TRUE
;
1879 for (j
= 0; j
< 8; j
++) {
1880 Equal
&= pNet
->Port
[i
]->Root
.Id
[j
] == pNet
->Root
.Id
[j
];
1887 SK_ERR_LOG(pAC
, SK_ERRCL_COMM
, SKERR_RLMT_E005
, SKERR_RLMT_E005_MSG
);
1888 Para
.Para32
[0] = NetIdx
;
1889 Para
.Para32
[1] = (SK_U32
)-1;
1890 SkEventQueue(pAC
, SKGE_PNMI
, SK_PNMI_EVT_RLMT_SEGMENTATION
, Para
);
1892 pNet
->CheckingState
&= ~SK_RLMT_RCS_REPORT_SEG
;
1894 /* 2000-03-06 RA: New. */
1895 Para
.Para32
[0] = NetIdx
;
1896 Para
.Para32
[1] = (SK_U32
)-1;
1897 SkTimerStart(pAC
, IoC
, &pNet
->SegTimer
, SK_RLMT_SEG_TO_VAL
,
1898 SKGE_RLMT
, SK_RLMT_SEG_TIM
, Para
);
1901 } /* for (i = 0; i < pNet->NumPorts; i++) */
1903 /* 2000-03-06 RA: Moved here. */
1904 /* Segmentation check not running anymore. */
1905 pNet
->CheckingState
&= ~SK_RLMT_RCS_SEG
;
1907 } /* SkRlmtCheckSeg */
1910 /******************************************************************************
1912 * SkRlmtPortStart - initialize port variables and start port
1915 * This routine initializes a port's variables and issues a PORT_START
1916 * to the HWAC module. This handles retries if the start fails or the
1917 * link eventually goes down.
1920 * runtime, pageable?
1925 RLMT_STATIC
void SkRlmtPortStart(
1926 SK_AC
*pAC
, /* Adapter Context */
1927 SK_IOC IoC
, /* I/O Context */
1928 SK_U32 PortNumber
) /* Port number */
1932 pAC
->Rlmt
.Port
[PortNumber
].PortState
= SK_RLMT_PS_LINK_DOWN
;
1933 pAC
->Rlmt
.Port
[PortNumber
].PortStarted
= SK_TRUE
;
1934 pAC
->Rlmt
.Port
[PortNumber
].LinkDown
= SK_TRUE
;
1935 pAC
->Rlmt
.Port
[PortNumber
].PortDown
= SK_TRUE
;
1936 pAC
->Rlmt
.Port
[PortNumber
].CheckingState
= 0;
1937 pAC
->Rlmt
.Port
[PortNumber
].RootIdSet
= SK_FALSE
;
1938 Para
.Para32
[0] = PortNumber
;
1939 Para
.Para32
[1] = (SK_U32
)-1;
1940 SkEventQueue(pAC
, SKGE_HWAC
, SK_HWEV_PORT_START
, Para
);
1941 } /* SkRlmtPortStart */
1944 /******************************************************************************
1946 * SkRlmtEvtPortStartTim - PORT_START_TIM
1949 * This routine handles PORT_START_TIM events.
1952 * runtime, pageable?
1953 * may be called after SK_INIT_IO
1958 RLMT_STATIC
void SkRlmtEvtPortStartTim(
1959 SK_AC
*pAC
, /* Adapter Context */
1960 SK_IOC IoC
, /* I/O Context */
1961 SK_EVPARA Para
) /* SK_U32 PortNumber; SK_U32 -1 */
1965 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1966 ("SK_RLMT_PORTSTART_TIMEOUT Port %d Event BEGIN.\n", Para
.Para32
[0]))
1968 if (Para
.Para32
[1] != (SK_U32
)-1) {
1969 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1970 ("Bad Parameter.\n"))
1971 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1972 ("SK_RLMT_PORTSTART_TIMEOUT Event EMPTY.\n"))
1977 * Used to start non-preferred ports if the preferred one
1979 * This timeout needs only be set when starting the first
1982 if (pAC
->Rlmt
.Port
[Para
.Para32
[0]].LinkDown
) {
1983 /* PORT_START failed. */
1984 for (i
= 0; i
< pAC
->Rlmt
.Port
[Para
.Para32
[0]].Net
->NumPorts
; i
++) {
1985 if (!pAC
->Rlmt
.Port
[Para
.Para32
[0]].Net
->Port
[i
]->PortStarted
) {
1986 SkRlmtPortStart(pAC
, IoC
,
1987 pAC
->Rlmt
.Port
[Para
.Para32
[0]].Net
->Port
[i
]->PortNumber
);
1992 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1993 ("SK_RLMT_PORTSTART_TIMEOUT Event END.\n"))
1994 } /* SkRlmtEvtPortStartTim */
1997 /******************************************************************************
1999 * SkRlmtEvtLinkUp - LINK_UP
2002 * This routine handles LLINK_UP events.
2005 * runtime, pageable?
2006 * may be called after SK_INIT_IO
2011 RLMT_STATIC
void SkRlmtEvtLinkUp(
2012 SK_AC
*pAC
, /* Adapter Context */
2013 SK_IOC IoC
, /* I/O Context */
2014 SK_EVPARA Para
) /* SK_U32 PortNumber; SK_U32 Undefined */
2017 SK_RLMT_PORT
*pRPort
;
2020 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2021 ("SK_RLMT_LINK_UP Port %d Event BEGIN.\n", Para
.Para32
[0]))
2023 pRPort
= &pAC
->Rlmt
.Port
[Para
.Para32
[0]];
2024 if (!pRPort
->PortStarted
) {
2025 SK_ERR_LOG(pAC
, SK_ERRCL_SW
, SKERR_RLMT_E008
, SKERR_RLMT_E008_MSG
);
2027 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2028 ("SK_RLMT_LINK_UP Event EMPTY.\n"))
2032 if (!pRPort
->LinkDown
) {
2033 /* RA;:;: Any better solution? */
2034 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2035 ("SK_RLMT_LINK_UP Event EMPTY.\n"))
2039 SkTimerStop(pAC
, IoC
, &pRPort
->UpTimer
);
2040 SkTimerStop(pAC
, IoC
, &pRPort
->DownRxTimer
);
2041 SkTimerStop(pAC
, IoC
, &pRPort
->DownTxTimer
);
2043 /* Do something if timer already fired? */
2045 pRPort
->LinkDown
= SK_FALSE
;
2046 pRPort
->PortState
= SK_RLMT_PS_GOING_UP
;
2047 pRPort
->GuTimeStamp
= SkOsGetTime(pAC
);
2048 pRPort
->BcTimeStamp
= 0;
2049 pRPort
->Net
->LinksUp
++;
2050 if (pRPort
->Net
->LinksUp
== 1) {
2051 SK_HWAC_LINK_LED(pAC
, IoC
, Para
.Para32
[0], SK_LED_ACTIVE
);
2054 SK_HWAC_LINK_LED(pAC
, IoC
, Para
.Para32
[0], SK_LED_STANDBY
);
2057 for (i
= 0; i
< pRPort
->Net
->NumPorts
; i
++) {
2058 if (!pRPort
->Net
->Port
[i
]->PortStarted
) {
2059 SkRlmtPortStart(pAC
, IoC
, pRPort
->Net
->Port
[i
]->PortNumber
);
2063 SkRlmtCheckSwitch(pAC
, IoC
, pRPort
->Net
->NetNumber
);
2065 if (pRPort
->Net
->LinksUp
>= 2) {
2066 if (pRPort
->Net
->RlmtMode
& SK_RLMT_CHECK_LOC_LINK
) {
2067 /* Build the check chain. */
2068 SkRlmtBuildCheckChain(pAC
, pRPort
->Net
->NetNumber
);
2072 /* If the first link comes up, start the periodical RLMT timeout. */
2073 if (pRPort
->Net
->NumPorts
> 1 && pRPort
->Net
->LinksUp
== 1 &&
2074 (pRPort
->Net
->RlmtMode
& SK_RLMT_CHECK_OTHERS
) != 0) {
2075 Para2
.Para32
[0] = pRPort
->Net
->NetNumber
;
2076 Para2
.Para32
[1] = (SK_U32
)-1;
2077 SkTimerStart(pAC
, IoC
, &pRPort
->Net
->LocTimer
,
2078 pRPort
->Net
->TimeoutValue
, SKGE_RLMT
, SK_RLMT_TIM
, Para2
);
2082 Para2
.Para32
[1] = (SK_U32
)-1;
2083 SkTimerStart(pAC
, IoC
, &pRPort
->UpTimer
, SK_RLMT_PORTUP_TIM_VAL
,
2084 SKGE_RLMT
, SK_RLMT_PORTUP_TIM
, Para2
);
2086 /* Later: if (pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_LOC_LINK) && */
2087 if ((pRPort
->Net
->RlmtMode
& SK_RLMT_TRANSPARENT
) == 0 &&
2088 (pRPort
->Net
->RlmtMode
& SK_RLMT_CHECK_LINK
) != 0 &&
2090 SkRlmtBuildPacket(pAC
, IoC
, Para
.Para32
[0], SK_PACKET_ANNOUNCE
,
2091 &pAC
->Addr
.Port
[Para
.Para32
[0]].CurrentMacAddress
, &SkRlmtMcAddr
)
2093 /* Send "new" packet to RLMT multicast address. */
2094 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_RLMT_SEND
, Para2
);
2097 if (pRPort
->Net
->RlmtMode
& SK_RLMT_CHECK_SEG
) {
2098 if ((Para2
.pParaPtr
=
2099 SkRlmtBuildSpanningTreePacket(pAC
, IoC
, Para
.Para32
[0])) != NULL
) {
2100 pAC
->Rlmt
.Port
[Para
.Para32
[0]].RootIdSet
= SK_FALSE
;
2101 pRPort
->Net
->CheckingState
|=
2102 SK_RLMT_RCS_SEG
| SK_RLMT_RCS_REPORT_SEG
;
2104 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_RLMT_SEND
, Para2
);
2106 Para
.Para32
[1] = (SK_U32
)-1;
2107 SkTimerStart(pAC
, IoC
, &pRPort
->Net
->SegTimer
,
2108 SK_RLMT_SEG_TO_VAL
, SKGE_RLMT
, SK_RLMT_SEG_TIM
, Para
);
2112 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2113 ("SK_RLMT_LINK_UP Event END.\n"))
2114 } /* SkRlmtEvtLinkUp */
2117 /******************************************************************************
2119 * SkRlmtEvtPortUpTim - PORT_UP_TIM
2122 * This routine handles PORT_UP_TIM events.
2125 * runtime, pageable?
2126 * may be called after SK_INIT_IO
2131 RLMT_STATIC
void SkRlmtEvtPortUpTim(
2132 SK_AC
*pAC
, /* Adapter Context */
2133 SK_IOC IoC
, /* I/O Context */
2134 SK_EVPARA Para
) /* SK_U32 PortNumber; SK_U32 -1 */
2136 SK_RLMT_PORT
*pRPort
;
2138 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2139 ("SK_RLMT_PORTUP_TIM Port %d Event BEGIN.\n", Para
.Para32
[0]))
2141 if (Para
.Para32
[1] != (SK_U32
)-1) {
2142 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2143 ("Bad Parameter.\n"))
2144 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2145 ("SK_RLMT_PORTUP_TIM Event EMPTY.\n"))
2149 pRPort
= &pAC
->Rlmt
.Port
[Para
.Para32
[0]];
2150 if (pRPort
->LinkDown
|| (pRPort
->PortState
== SK_RLMT_PS_UP
)) {
2151 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2152 ("SK_RLMT_PORTUP_TIM Port %d Event EMPTY.\n", Para
.Para32
[0]))
2156 pRPort
->PortDown
= SK_FALSE
;
2157 pRPort
->PortState
= SK_RLMT_PS_UP
;
2158 pRPort
->Net
->PortsUp
++;
2159 if (pRPort
->Net
->RlmtState
!= SK_RLMT_RS_INIT
) {
2160 if (pAC
->Rlmt
.NumNets
<= 1) {
2161 SkRlmtCheckSwitch(pAC
, IoC
, pRPort
->Net
->NetNumber
);
2163 SkEventQueue(pAC
, SKGE_PNMI
, SK_PNMI_EVT_RLMT_PORT_UP
, Para
);
2166 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2167 ("SK_RLMT_PORTUP_TIM Event END.\n"))
2168 } /* SkRlmtEvtPortUpTim */
2171 /******************************************************************************
2173 * SkRlmtEvtPortDownTim - PORT_DOWN_*
2176 * This routine handles PORT_DOWN_* events.
2179 * runtime, pageable?
2180 * may be called after SK_INIT_IO
2185 RLMT_STATIC
void SkRlmtEvtPortDownX(
2186 SK_AC
*pAC
, /* Adapter Context */
2187 SK_IOC IoC
, /* I/O Context */
2188 SK_U32 Event
, /* Event code */
2189 SK_EVPARA Para
) /* SK_U32 PortNumber; SK_U32 -1 */
2191 SK_RLMT_PORT
*pRPort
;
2193 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2194 ("SK_RLMT_PORTDOWN* Port %d Event (%d) BEGIN.\n",
2195 Para
.Para32
[0], Event
))
2197 if (Para
.Para32
[1] != (SK_U32
)-1) {
2198 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2199 ("Bad Parameter.\n"))
2200 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2201 ("SK_RLMT_PORTDOWN* Event EMPTY.\n"))
2205 pRPort
= &pAC
->Rlmt
.Port
[Para
.Para32
[0]];
2206 if (!pRPort
->PortStarted
|| (Event
== SK_RLMT_PORTDOWN_TX_TIM
&&
2207 !(pRPort
->CheckingState
& SK_RLMT_PCS_TX
))) {
2208 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2209 ("SK_RLMT_PORTDOWN* Event (%d) EMPTY.\n", Event
))
2213 /* Stop port's timers. */
2214 SkTimerStop(pAC
, IoC
, &pRPort
->UpTimer
);
2215 SkTimerStop(pAC
, IoC
, &pRPort
->DownRxTimer
);
2216 SkTimerStop(pAC
, IoC
, &pRPort
->DownTxTimer
);
2218 if (pRPort
->PortState
!= SK_RLMT_PS_LINK_DOWN
) {
2219 pRPort
->PortState
= SK_RLMT_PS_DOWN
;
2222 if (!pRPort
->PortDown
) {
2223 pRPort
->Net
->PortsUp
--;
2224 pRPort
->PortDown
= SK_TRUE
;
2225 SkEventQueue(pAC
, SKGE_PNMI
, SK_PNMI_EVT_RLMT_PORT_DOWN
, Para
);
2228 pRPort
->PacketsPerTimeSlot
= 0;
2229 /* pRPort->DataPacketsPerTimeSlot = 0; */
2230 pRPort
->BpduPacketsPerTimeSlot
= 0;
2231 pRPort
->BcTimeStamp
= 0;
2234 * RA;:;: To be checked:
2235 * - actions at RLMT_STOP: We should not switch anymore.
2237 if (pRPort
->Net
->RlmtState
!= SK_RLMT_RS_INIT
) {
2238 if (Para
.Para32
[0] ==
2239 pRPort
->Net
->Port
[pRPort
->Net
->ActivePort
]->PortNumber
) {
2240 /* Active Port went down. */
2241 SkRlmtCheckSwitch(pAC
, IoC
, pRPort
->Net
->NetNumber
);
2245 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2246 ("SK_RLMT_PORTDOWN* Event (%d) END.\n", Event
))
2247 } /* SkRlmtEvtPortDownX */
2250 /******************************************************************************
2252 * SkRlmtEvtLinkDown - LINK_DOWN
2255 * This routine handles LINK_DOWN events.
2258 * runtime, pageable?
2259 * may be called after SK_INIT_IO
2264 RLMT_STATIC
void SkRlmtEvtLinkDown(
2265 SK_AC
*pAC
, /* Adapter Context */
2266 SK_IOC IoC
, /* I/O Context */
2267 SK_EVPARA Para
) /* SK_U32 PortNumber; SK_U32 Undefined */
2269 SK_RLMT_PORT
*pRPort
;
2271 pRPort
= &pAC
->Rlmt
.Port
[Para
.Para32
[0]];
2272 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2273 ("SK_RLMT_LINK_DOWN Port %d Event BEGIN.\n", Para
.Para32
[0]))
2275 if (!pAC
->Rlmt
.Port
[Para
.Para32
[0]].LinkDown
) {
2276 pRPort
->Net
->LinksUp
--;
2277 pRPort
->LinkDown
= SK_TRUE
;
2278 pRPort
->PortState
= SK_RLMT_PS_LINK_DOWN
;
2279 SK_HWAC_LINK_LED(pAC
, IoC
, Para
.Para32
[0], SK_LED_OFF
);
2281 if ((pRPort
->Net
->RlmtMode
& SK_RLMT_CHECK_LOC_LINK
) != 0) {
2282 /* Build the check chain. */
2283 SkRlmtBuildCheckChain(pAC
, pRPort
->Net
->NetNumber
);
2286 /* Ensure that port is marked down. */
2287 Para
.Para32
[1] = -1;
2288 (void)SkRlmtEvent(pAC
, IoC
, SK_RLMT_PORTDOWN
, Para
);
2291 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2292 ("SK_RLMT_LINK_DOWN Event END.\n"))
2293 } /* SkRlmtEvtLinkDown */
2296 /******************************************************************************
2298 * SkRlmtEvtPortAddr - PORT_ADDR
2301 * This routine handles PORT_ADDR events.
2304 * runtime, pageable?
2305 * may be called after SK_INIT_IO
2310 RLMT_STATIC
void SkRlmtEvtPortAddr(
2311 SK_AC
*pAC
, /* Adapter Context */
2312 SK_IOC IoC
, /* I/O Context */
2313 SK_EVPARA Para
) /* SK_U32 PortNumber; SK_U32 -1 */
2316 SK_RLMT_PORT
*pRPort
;
2317 SK_MAC_ADDR
*pOldMacAddr
;
2318 SK_MAC_ADDR
*pNewMacAddr
;
2320 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2321 ("SK_RLMT_PORT_ADDR Port %d Event BEGIN.\n", Para
.Para32
[0]))
2323 if (Para
.Para32
[1] != (SK_U32
)-1) {
2324 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2325 ("Bad Parameter.\n"))
2326 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2327 ("SK_RLMT_PORT_ADDR Event EMPTY.\n"))
2331 /* Port's physical MAC address changed. */
2332 pOldMacAddr
= &pAC
->Addr
.Port
[Para
.Para32
[0]].PreviousMacAddress
;
2333 pNewMacAddr
= &pAC
->Addr
.Port
[Para
.Para32
[0]].CurrentMacAddress
;
2336 * NOTE: This is not scalable for solutions where ports are
2337 * checked remotely. There, we need to send an RLMT
2338 * address change packet - and how do we ensure delivery?
2340 for (i
= 0; i
< (SK_U32
)pAC
->GIni
.GIMacsFound
; i
++) {
2341 pRPort
= &pAC
->Rlmt
.Port
[i
];
2342 for (j
= 0; j
< pRPort
->PortsChecked
; j
++) {
2344 pRPort
->PortCheck
[j
].CheckAddr
.a
, pOldMacAddr
->a
)) {
2345 pRPort
->PortCheck
[j
].CheckAddr
= *pNewMacAddr
;
2350 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2351 ("SK_RLMT_PORT_ADDR Event END.\n"))
2352 } /* SkRlmtEvtPortAddr */
2355 /******************************************************************************
2357 * SkRlmtEvtStart - START
2360 * This routine handles START events.
2363 * runtime, pageable?
2364 * may be called after SK_INIT_IO
2369 RLMT_STATIC
void SkRlmtEvtStart(
2370 SK_AC
*pAC
, /* Adapter Context */
2371 SK_IOC IoC
, /* I/O Context */
2372 SK_EVPARA Para
) /* SK_U32 NetNumber; SK_U32 -1 */
2378 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2379 ("SK_RLMT_START Net %d Event BEGIN.\n", Para
.Para32
[0]))
2381 if (Para
.Para32
[1] != (SK_U32
)-1) {
2382 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2383 ("Bad Parameter.\n"))
2384 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2385 ("SK_RLMT_START Event EMPTY.\n"))
2389 if (Para
.Para32
[0] >= pAC
->Rlmt
.NumNets
) {
2390 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2391 ("Bad NetNumber %d.\n", Para
.Para32
[0]))
2392 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2393 ("SK_RLMT_START Event EMPTY.\n"))
2397 if (pAC
->Rlmt
.Net
[Para
.Para32
[0]].RlmtState
!= SK_RLMT_RS_INIT
) {
2398 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2399 ("SK_RLMT_START Event EMPTY.\n"))
2403 if (pAC
->Rlmt
.NetsStarted
>= pAC
->Rlmt
.NumNets
) {
2404 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2405 ("All nets should have been started.\n"))
2406 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2407 ("SK_RLMT_START Event EMPTY.\n"))
2411 if (pAC
->Rlmt
.Net
[Para
.Para32
[0]].PrefPort
>=
2412 pAC
->Rlmt
.Net
[Para
.Para32
[0]].NumPorts
) {
2413 SK_ERR_LOG(pAC
, SK_ERRCL_SW
, SKERR_RLMT_E009
, SKERR_RLMT_E009_MSG
);
2415 /* Change PrefPort to internal default. */
2416 Para2
.Para32
[0] = 0xFFFFFFFF;
2417 Para2
.Para32
[1] = Para
.Para32
[0];
2418 (void)SkRlmtEvent(pAC
, IoC
, SK_RLMT_PREFPORT_CHANGE
, Para2
);
2421 PortIdx
= pAC
->Rlmt
.Net
[Para
.Para32
[0]].PrefPort
;
2422 PortNumber
= pAC
->Rlmt
.Net
[Para
.Para32
[0]].Port
[PortIdx
]->PortNumber
;
2424 pAC
->Rlmt
.Net
[Para
.Para32
[0]].LinksUp
= 0;
2425 pAC
->Rlmt
.Net
[Para
.Para32
[0]].PortsUp
= 0;
2426 pAC
->Rlmt
.Net
[Para
.Para32
[0]].CheckingState
= 0;
2427 pAC
->Rlmt
.Net
[Para
.Para32
[0]].RlmtState
= SK_RLMT_RS_NET_DOWN
;
2429 /* Start preferred port. */
2430 SkRlmtPortStart(pAC
, IoC
, PortNumber
);
2432 /* Start Timer (for first port only). */
2433 Para2
.Para32
[0] = PortNumber
;
2434 Para2
.Para32
[1] = (SK_U32
)-1;
2435 SkTimerStart(pAC
, IoC
, &pAC
->Rlmt
.Port
[PortNumber
].UpTimer
,
2436 SK_RLMT_PORTSTART_TIM_VAL
, SKGE_RLMT
, SK_RLMT_PORTSTART_TIM
, Para2
);
2438 pAC
->Rlmt
.NetsStarted
++;
2440 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2441 ("SK_RLMT_START Event END.\n"))
2442 } /* SkRlmtEvtStart */
2445 /******************************************************************************
2447 * SkRlmtEvtStop - STOP
2450 * This routine handles STOP events.
2453 * runtime, pageable?
2454 * may be called after SK_INIT_IO
2459 RLMT_STATIC
void SkRlmtEvtStop(
2460 SK_AC
*pAC
, /* Adapter Context */
2461 SK_IOC IoC
, /* I/O Context */
2462 SK_EVPARA Para
) /* SK_U32 NetNumber; SK_U32 -1 */
2468 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2469 ("SK_RLMT_STOP Net %d Event BEGIN.\n", Para
.Para32
[0]))
2471 if (Para
.Para32
[1] != (SK_U32
)-1) {
2472 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2473 ("Bad Parameter.\n"))
2474 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2475 ("SK_RLMT_STOP Event EMPTY.\n"))
2479 if (Para
.Para32
[0] >= pAC
->Rlmt
.NumNets
) {
2480 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2481 ("Bad NetNumber %d.\n", Para
.Para32
[0]))
2482 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2483 ("SK_RLMT_STOP Event EMPTY.\n"))
2487 if (pAC
->Rlmt
.Net
[Para
.Para32
[0]].RlmtState
== SK_RLMT_RS_INIT
) {
2488 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2489 ("SK_RLMT_STOP Event EMPTY.\n"))
2493 if (pAC
->Rlmt
.NetsStarted
== 0) {
2494 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2495 ("All nets are stopped.\n"))
2496 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2497 ("SK_RLMT_STOP Event EMPTY.\n"))
2501 /* Stop RLMT timers. */
2502 SkTimerStop(pAC
, IoC
, &pAC
->Rlmt
.Net
[Para
.Para32
[0]].LocTimer
);
2503 SkTimerStop(pAC
, IoC
, &pAC
->Rlmt
.Net
[Para
.Para32
[0]].SegTimer
);
2506 pAC
->Rlmt
.Net
[Para
.Para32
[0]].RlmtState
= SK_RLMT_RS_INIT
;
2507 pAC
->Rlmt
.Net
[Para
.Para32
[0]].RootIdSet
= SK_FALSE
;
2508 Para2
.Para32
[0] = SK_RLMT_NET_DOWN_FINAL
;
2509 Para2
.Para32
[1] = Para
.Para32
[0]; /* Net# */
2510 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_NET_DOWN
, Para2
);
2513 for (i
= 0; i
< pAC
->Rlmt
.Net
[Para
.Para32
[0]].NumPorts
; i
++) {
2514 PortNumber
= pAC
->Rlmt
.Net
[Para
.Para32
[0]].Port
[i
]->PortNumber
;
2515 if (pAC
->Rlmt
.Port
[PortNumber
].PortState
!= SK_RLMT_PS_INIT
) {
2516 SkTimerStop(pAC
, IoC
, &pAC
->Rlmt
.Port
[PortNumber
].UpTimer
);
2517 SkTimerStop(pAC
, IoC
, &pAC
->Rlmt
.Port
[PortNumber
].DownRxTimer
);
2518 SkTimerStop(pAC
, IoC
, &pAC
->Rlmt
.Port
[PortNumber
].DownTxTimer
);
2520 pAC
->Rlmt
.Port
[PortNumber
].PortState
= SK_RLMT_PS_INIT
;
2521 pAC
->Rlmt
.Port
[PortNumber
].RootIdSet
= SK_FALSE
;
2522 pAC
->Rlmt
.Port
[PortNumber
].PortStarted
= SK_FALSE
;
2523 Para2
.Para32
[0] = PortNumber
;
2524 Para2
.Para32
[1] = (SK_U32
)-1;
2525 SkEventQueue(pAC
, SKGE_HWAC
, SK_HWEV_PORT_STOP
, Para2
);
2529 pAC
->Rlmt
.NetsStarted
--;
2531 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2532 ("SK_RLMT_STOP Event END.\n"))
2533 } /* SkRlmtEvtStop */
2536 /******************************************************************************
2538 * SkRlmtEvtTim - TIM
2541 * This routine handles TIM events.
2544 * runtime, pageable?
2545 * may be called after SK_INIT_IO
2550 RLMT_STATIC
void SkRlmtEvtTim(
2551 SK_AC
*pAC
, /* Adapter Context */
2552 SK_IOC IoC
, /* I/O Context */
2553 SK_EVPARA Para
) /* SK_U32 NetNumber; SK_U32 -1 */
2555 SK_RLMT_PORT
*pRPort
;
2561 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2562 ("SK_RLMT_TIM Event BEGIN.\n"))
2564 if (Para
.Para32
[1] != (SK_U32
)-1) {
2565 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2566 ("Bad Parameter.\n"))
2567 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2568 ("SK_RLMT_TIM Event EMPTY.\n"))
2572 if ((pAC
->Rlmt
.Net
[Para
.Para32
[0]].RlmtMode
& SK_RLMT_CHECK_OTHERS
) == 0 ||
2573 pAC
->Rlmt
.Net
[Para
.Para32
[0]].LinksUp
== 0) {
2574 /* Mode changed or all links down: No more link checking. */
2579 pAC
->Rlmt
.SwitchCheckCounter
--;
2580 if (pAC
->Rlmt
.SwitchCheckCounter
== 0) {
2581 pAC
->Rlmt
.SwitchCheckCounter
;
2585 NewTimeout
= SK_RLMT_DEF_TO_VAL
;
2586 for (i
= 0; i
< pAC
->Rlmt
.Net
[Para
.Para32
[0]].NumPorts
; i
++) {
2587 PortNumber
= pAC
->Rlmt
.Net
[Para
.Para32
[0]].Port
[i
]->PortNumber
;
2588 pRPort
= &pAC
->Rlmt
.Port
[PortNumber
];
2589 if (!pRPort
->LinkDown
) {
2590 Timeout
= SkRlmtCheckPort(pAC
, IoC
, PortNumber
);
2591 if (Timeout
< NewTimeout
) {
2592 NewTimeout
= Timeout
;
2596 * These counters should be set to 0 for all ports before the
2597 * first frame is sent in the next loop.
2599 pRPort
->PacketsPerTimeSlot
= 0;
2600 /* pRPort->DataPacketsPerTimeSlot = 0; */
2601 pRPort
->BpduPacketsPerTimeSlot
= 0;
2604 pAC
->Rlmt
.Net
[Para
.Para32
[0]].TimeoutValue
= NewTimeout
;
2606 if (pAC
->Rlmt
.Net
[Para
.Para32
[0]].LinksUp
> 1) {
2608 * If checking remote ports, also send packets if
2610 * this port checks at least one (remote) port.
2614 * Must be new loop, as SkRlmtCheckPort can request to
2615 * check segmentation when e.g. checking the last port.
2617 for (i
= 0; i
< pAC
->Rlmt
.Net
[Para
.Para32
[0]].NumPorts
; i
++) {
2618 if (!pAC
->Rlmt
.Net
[Para
.Para32
[0]].Port
[i
]->LinkDown
) {
2619 SkRlmtSend(pAC
, IoC
,
2620 pAC
->Rlmt
.Net
[Para
.Para32
[0]].Port
[i
]->PortNumber
);
2625 SkTimerStart(pAC
, IoC
, &pAC
->Rlmt
.Net
[Para
.Para32
[0]].LocTimer
,
2626 pAC
->Rlmt
.Net
[Para
.Para32
[0]].TimeoutValue
, SKGE_RLMT
, SK_RLMT_TIM
,
2629 if (pAC
->Rlmt
.Net
[Para
.Para32
[0]].LinksUp
> 1 &&
2630 (pAC
->Rlmt
.Net
[Para
.Para32
[0]].RlmtMode
& SK_RLMT_CHECK_SEG
) &&
2631 (pAC
->Rlmt
.Net
[Para
.Para32
[0]].CheckingState
& SK_RLMT_RCS_START_SEG
)) {
2632 SkTimerStart(pAC
, IoC
, &pAC
->Rlmt
.Net
[Para
.Para32
[0]].SegTimer
,
2633 SK_RLMT_SEG_TO_VAL
, SKGE_RLMT
, SK_RLMT_SEG_TIM
, Para
);
2634 pAC
->Rlmt
.Net
[Para
.Para32
[0]].CheckingState
&= ~SK_RLMT_RCS_START_SEG
;
2635 pAC
->Rlmt
.Net
[Para
.Para32
[0]].CheckingState
|=
2636 SK_RLMT_RCS_SEG
| SK_RLMT_RCS_REPORT_SEG
;
2639 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2640 ("SK_RLMT_TIM Event END.\n"))
2641 } /* SkRlmtEvtTim */
2644 /******************************************************************************
2646 * SkRlmtEvtSegTim - SEG_TIM
2649 * This routine handles SEG_TIM events.
2652 * runtime, pageable?
2653 * may be called after SK_INIT_IO
2658 RLMT_STATIC
void SkRlmtEvtSegTim(
2659 SK_AC
*pAC
, /* Adapter Context */
2660 SK_IOC IoC
, /* I/O Context */
2661 SK_EVPARA Para
) /* SK_U32 NetNumber; SK_U32 -1 */
2667 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2668 ("SK_RLMT_SEG_TIM Event BEGIN.\n"))
2670 if (Para
.Para32
[1] != (SK_U32
)-1) {
2671 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2672 ("Bad Parameter.\n"))
2673 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2674 ("SK_RLMT_SEG_TIM Event EMPTY.\n"))
2679 for (j
= 0; j
< pAC
->Rlmt
.Net
[Para
.Para32
[0]].NumPorts
; j
++) {
2680 SK_ADDR_PORT
*pAPort
;
2685 InAddr
= (SK_U16
*)&InAddr8
[0];
2686 pAPort
= pAC
->Rlmt
.Net
[Para
.Para32
[0]].Port
[j
]->AddrPort
;
2687 for (k
= 0; k
< pAPort
->NextExactMatchRlmt
; k
++) {
2688 /* Get exact match address k from port j. */
2689 XM_INADDR(IoC
, pAC
->Rlmt
.Net
[Para
.Para32
[0]].Port
[j
]->PortNumber
,
2691 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2692 ("MC address %d on Port %u: %02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x.\n",
2693 k
, pAC
->Rlmt
.Net
[Para
.Para32
[0]].Port
[j
]->PortNumber
,
2694 InAddr8
[0], InAddr8
[1], InAddr8
[2],
2695 InAddr8
[3], InAddr8
[4], InAddr8
[5],
2696 pAPort
->Exact
[k
].a
[0], pAPort
->Exact
[k
].a
[1],
2697 pAPort
->Exact
[k
].a
[2], pAPort
->Exact
[k
].a
[3],
2698 pAPort
->Exact
[k
].a
[4], pAPort
->Exact
[k
].a
[5]))
2703 SkRlmtCheckSeg(pAC
, IoC
, Para
.Para32
[0]);
2705 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2706 ("SK_RLMT_SEG_TIM Event END.\n"))
2707 } /* SkRlmtEvtSegTim */
2710 /******************************************************************************
2712 * SkRlmtEvtPacketRx - PACKET_RECEIVED
2715 * This routine handles PACKET_RECEIVED events.
2718 * runtime, pageable?
2719 * may be called after SK_INIT_IO
2724 RLMT_STATIC
void SkRlmtEvtPacketRx(
2725 SK_AC
*pAC
, /* Adapter Context */
2726 SK_IOC IoC
, /* I/O Context */
2727 SK_EVPARA Para
) /* SK_MBUF *pMb */
2734 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2735 ("SK_RLMT_PACKET_RECEIVED Event BEGIN.\n"))
2737 /* Should we ignore frames during port switching? */
2740 pMb
= Para
.pParaPtr
;
2742 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
, ("No mbuf.\n"))
2744 else if (pMb
->pNext
!= NULL
) {
2745 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2746 ("More than one mbuf or pMb->pNext not set.\n"))
2750 for (pMb
= Para
.pParaPtr
; pMb
!= NULL
; pMb
= pNextMb
) {
2751 pNextMb
= pMb
->pNext
;
2754 NetNumber
= pAC
->Rlmt
.Port
[pMb
->PortIdx
].Net
->NetNumber
;
2755 if (pAC
->Rlmt
.Net
[NetNumber
].RlmtState
== SK_RLMT_RS_INIT
) {
2756 SkDrvFreeRlmtMbuf(pAC
, IoC
, pMb
);
2759 SkRlmtPacketReceive(pAC
, IoC
, pMb
);
2763 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2764 ("SK_RLMT_PACKET_RECEIVED Event END.\n"))
2765 } /* SkRlmtEvtPacketRx */
2768 /******************************************************************************
2770 * SkRlmtEvtStatsClear - STATS_CLEAR
2773 * This routine handles STATS_CLEAR events.
2776 * runtime, pageable?
2777 * may be called after SK_INIT_IO
2782 RLMT_STATIC
void SkRlmtEvtStatsClear(
2783 SK_AC
*pAC
, /* Adapter Context */
2784 SK_IOC IoC
, /* I/O Context */
2785 SK_EVPARA Para
) /* SK_U32 NetNumber; SK_U32 -1 */
2788 SK_RLMT_PORT
*pRPort
;
2790 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2791 ("SK_RLMT_STATS_CLEAR Event BEGIN.\n"))
2793 if (Para
.Para32
[1] != (SK_U32
)-1) {
2794 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2795 ("Bad Parameter.\n"))
2796 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2797 ("SK_RLMT_STATS_CLEAR Event EMPTY.\n"))
2801 if (Para
.Para32
[0] >= pAC
->Rlmt
.NumNets
) {
2802 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2803 ("Bad NetNumber %d.\n", Para
.Para32
[0]))
2804 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2805 ("SK_RLMT_STATS_CLEAR Event EMPTY.\n"))
2809 /* Clear statistics for logical and physical ports. */
2810 for (i
= 0; i
< pAC
->Rlmt
.Net
[Para
.Para32
[0]].NumPorts
; i
++) {
2812 &pAC
->Rlmt
.Port
[pAC
->Rlmt
.Net
[Para
.Para32
[0]].Port
[i
]->PortNumber
];
2813 pRPort
->TxHelloCts
= 0;
2814 pRPort
->RxHelloCts
= 0;
2815 pRPort
->TxSpHelloReqCts
= 0;
2816 pRPort
->RxSpHelloCts
= 0;
2819 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2820 ("SK_RLMT_STATS_CLEAR Event END.\n"))
2821 } /* SkRlmtEvtStatsClear */
2824 /******************************************************************************
2826 * SkRlmtEvtStatsUpdate - STATS_UPDATE
2829 * This routine handles STATS_UPDATE events.
2832 * runtime, pageable?
2833 * may be called after SK_INIT_IO
2838 RLMT_STATIC
void SkRlmtEvtStatsUpdate(
2839 SK_AC
*pAC
, /* Adapter Context */
2840 SK_IOC IoC
, /* I/O Context */
2841 SK_EVPARA Para
) /* SK_U32 NetNumber; SK_U32 -1 */
2843 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2844 ("SK_RLMT_STATS_UPDATE Event BEGIN.\n"))
2846 if (Para
.Para32
[1] != (SK_U32
)-1) {
2847 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2848 ("Bad Parameter.\n"))
2849 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2850 ("SK_RLMT_STATS_UPDATE Event EMPTY.\n"))
2854 if (Para
.Para32
[0] >= pAC
->Rlmt
.NumNets
) {
2855 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2856 ("Bad NetNumber %d.\n", Para
.Para32
[0]))
2857 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2858 ("SK_RLMT_STATS_UPDATE Event EMPTY.\n"))
2862 /* Update statistics - currently always up-to-date. */
2864 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2865 ("SK_RLMT_STATS_UPDATE Event END.\n"))
2866 } /* SkRlmtEvtStatsUpdate */
2869 /******************************************************************************
2871 * SkRlmtEvtPrefportChange - PREFPORT_CHANGE
2874 * This routine handles PREFPORT_CHANGE events.
2877 * runtime, pageable?
2878 * may be called after SK_INIT_IO
2883 RLMT_STATIC
void SkRlmtEvtPrefportChange(
2884 SK_AC
*pAC
, /* Adapter Context */
2885 SK_IOC IoC
, /* I/O Context */
2886 SK_EVPARA Para
) /* SK_U32 PortIndex; SK_U32 NetNumber */
2888 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2889 ("SK_RLMT_PREFPORT_CHANGE to Port %d Event BEGIN.\n", Para
.Para32
[0]))
2891 if (Para
.Para32
[1] >= pAC
->Rlmt
.NumNets
) {
2892 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2893 ("Bad NetNumber %d.\n", Para
.Para32
[1]))
2894 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2895 ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n"))
2899 /* 0xFFFFFFFF == auto-mode. */
2900 if (Para
.Para32
[0] == 0xFFFFFFFF) {
2901 pAC
->Rlmt
.Net
[Para
.Para32
[1]].PrefPort
= SK_RLMT_DEF_PREF_PORT
;
2904 if (Para
.Para32
[0] >= pAC
->Rlmt
.Net
[Para
.Para32
[1]].NumPorts
) {
2905 SK_ERR_LOG(pAC
, SK_ERRCL_SW
, SKERR_RLMT_E010
, SKERR_RLMT_E010_MSG
);
2907 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2908 ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n"))
2912 pAC
->Rlmt
.Net
[Para
.Para32
[1]].PrefPort
= Para
.Para32
[0];
2915 pAC
->Rlmt
.Net
[Para
.Para32
[1]].Preference
= Para
.Para32
[0];
2917 if (pAC
->Rlmt
.Net
[Para
.Para32
[1]].RlmtState
!= SK_RLMT_RS_INIT
) {
2918 SkRlmtCheckSwitch(pAC
, IoC
, Para
.Para32
[1]);
2921 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2922 ("SK_RLMT_PREFPORT_CHANGE Event END.\n"))
2923 } /* SkRlmtEvtPrefportChange */
2926 /******************************************************************************
2928 * SkRlmtEvtSetNets - SET_NETS
2931 * This routine handles SET_NETS events.
2934 * runtime, pageable?
2935 * may be called after SK_INIT_IO
2940 RLMT_STATIC
void SkRlmtEvtSetNets(
2941 SK_AC
*pAC
, /* Adapter Context */
2942 SK_IOC IoC
, /* I/O Context */
2943 SK_EVPARA Para
) /* SK_U32 NumNets; SK_U32 -1 */
2947 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2948 ("SK_RLMT_SET_NETS Event BEGIN.\n"))
2950 if (Para
.Para32
[1] != (SK_U32
)-1) {
2951 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2952 ("Bad Parameter.\n"))
2953 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2954 ("SK_RLMT_SET_NETS Event EMPTY.\n"))
2958 if (Para
.Para32
[0] == 0 || Para
.Para32
[0] > SK_MAX_NETS
||
2959 Para
.Para32
[0] > (SK_U32
)pAC
->GIni
.GIMacsFound
) {
2960 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2961 ("Bad number of nets: %d.\n", Para
.Para32
[0]))
2962 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2963 ("SK_RLMT_SET_NETS Event EMPTY.\n"))
2967 if (Para
.Para32
[0] == pAC
->Rlmt
.NumNets
) { /* No change. */
2968 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2969 ("SK_RLMT_SET_NETS Event EMPTY.\n"))
2973 /* Entering and leaving dual mode only allowed while nets are stopped. */
2974 if (pAC
->Rlmt
.NetsStarted
> 0) {
2975 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2976 ("Changing dual mode only allowed while all nets are stopped.\n"))
2977 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2978 ("SK_RLMT_SET_NETS Event EMPTY.\n"))
2982 if (Para
.Para32
[0] == 1) {
2983 if (pAC
->Rlmt
.NumNets
> 1) {
2984 /* Clear logical MAC addr from second net's active port. */
2985 (void)SkAddrOverride(pAC
, IoC
, pAC
->Rlmt
.Net
[1].Port
[pAC
->Addr
.
2986 Net
[1].ActivePort
]->PortNumber
, NULL
, SK_ADDR_CLEAR_LOGICAL
);
2987 pAC
->Rlmt
.Net
[1].NumPorts
= 0;
2990 pAC
->Rlmt
.NumNets
= Para
.Para32
[0];
2991 for (i
= 0; (SK_U32
)i
< pAC
->Rlmt
.NumNets
; i
++) {
2992 pAC
->Rlmt
.Net
[i
].RlmtState
= SK_RLMT_RS_INIT
;
2993 pAC
->Rlmt
.Net
[i
].RootIdSet
= SK_FALSE
;
2994 pAC
->Rlmt
.Net
[i
].Preference
= 0xFFFFFFFF; /* "Automatic" */
2995 pAC
->Rlmt
.Net
[i
].PrefPort
= SK_RLMT_DEF_PREF_PORT
;
2996 /* Just assuming. */
2997 pAC
->Rlmt
.Net
[i
].ActivePort
= pAC
->Rlmt
.Net
[i
].PrefPort
;
2998 pAC
->Rlmt
.Net
[i
].RlmtMode
= SK_RLMT_DEF_MODE
;
2999 pAC
->Rlmt
.Net
[i
].TimeoutValue
= SK_RLMT_DEF_TO_VAL
;
3000 pAC
->Rlmt
.Net
[i
].NetNumber
= i
;
3003 pAC
->Rlmt
.Port
[1].Net
= &pAC
->Rlmt
.Net
[0];
3004 pAC
->Rlmt
.Net
[0].NumPorts
= pAC
->GIni
.GIMacsFound
;
3006 SkEventQueue(pAC
, SKGE_PNMI
, SK_PNMI_EVT_RLMT_SET_NETS
, Para
);
3008 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
3009 ("RLMT: Changed to one net with two ports.\n"))
3011 else if (Para
.Para32
[0] == 2) {
3012 pAC
->Rlmt
.Port
[1].Net
= &pAC
->Rlmt
.Net
[1];
3013 pAC
->Rlmt
.Net
[1].NumPorts
= pAC
->GIni
.GIMacsFound
- 1;
3014 pAC
->Rlmt
.Net
[0].NumPorts
=
3015 pAC
->GIni
.GIMacsFound
- pAC
->Rlmt
.Net
[1].NumPorts
;
3017 pAC
->Rlmt
.NumNets
= Para
.Para32
[0];
3018 for (i
= 0; (SK_U32
)i
< pAC
->Rlmt
.NumNets
; i
++) {
3019 pAC
->Rlmt
.Net
[i
].RlmtState
= SK_RLMT_RS_INIT
;
3020 pAC
->Rlmt
.Net
[i
].RootIdSet
= SK_FALSE
;
3021 pAC
->Rlmt
.Net
[i
].Preference
= 0xFFFFFFFF; /* "Automatic" */
3022 pAC
->Rlmt
.Net
[i
].PrefPort
= SK_RLMT_DEF_PREF_PORT
;
3023 /* Just assuming. */
3024 pAC
->Rlmt
.Net
[i
].ActivePort
= pAC
->Rlmt
.Net
[i
].PrefPort
;
3025 pAC
->Rlmt
.Net
[i
].RlmtMode
= SK_RLMT_DEF_MODE
;
3026 pAC
->Rlmt
.Net
[i
].TimeoutValue
= SK_RLMT_DEF_TO_VAL
;
3028 pAC
->Rlmt
.Net
[i
].NetNumber
= i
;
3031 /* Set logical MAC addr on second net's active port. */
3032 (void)SkAddrOverride(pAC
, IoC
, pAC
->Rlmt
.Net
[1].Port
[pAC
->Addr
.
3033 Net
[1].ActivePort
]->PortNumber
, NULL
, SK_ADDR_SET_LOGICAL
);
3035 SkEventQueue(pAC
, SKGE_PNMI
, SK_PNMI_EVT_RLMT_SET_NETS
, Para
);
3037 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
3038 ("RLMT: Changed to two nets with one port each.\n"))
3041 /* Not implemented for more than two nets. */
3042 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
3043 ("SetNets not implemented for more than two nets.\n"))
3044 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
3045 ("SK_RLMT_SET_NETS Event EMPTY.\n"))
3049 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
3050 ("SK_RLMT_SET_NETS Event END.\n"))
3051 } /* SkRlmtSetNets */
3054 /******************************************************************************
3056 * SkRlmtEvtModeChange - MODE_CHANGE
3059 * This routine handles MODE_CHANGE events.
3062 * runtime, pageable?
3063 * may be called after SK_INIT_IO
3068 RLMT_STATIC
void SkRlmtEvtModeChange(
3069 SK_AC
*pAC
, /* Adapter Context */
3070 SK_IOC IoC
, /* I/O Context */
3071 SK_EVPARA Para
) /* SK_U32 NewMode; SK_U32 NetNumber */
3075 SK_U32 PrevRlmtMode
;
3077 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
3078 ("SK_RLMT_MODE_CHANGE Event BEGIN.\n"))
3080 if (Para
.Para32
[1] >= pAC
->Rlmt
.NumNets
) {
3081 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
3082 ("Bad NetNumber %d.\n", Para
.Para32
[1]))
3083 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
3084 ("SK_RLMT_MODE_CHANGE Event EMPTY.\n"))
3088 Para
.Para32
[0] |= SK_RLMT_CHECK_LINK
;
3090 if ((pAC
->Rlmt
.Net
[Para
.Para32
[1]].NumPorts
== 1) &&
3091 Para
.Para32
[0] != SK_RLMT_MODE_CLS
) {
3092 pAC
->Rlmt
.Net
[Para
.Para32
[1]].RlmtMode
= SK_RLMT_MODE_CLS
;
3093 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
3094 ("Forced RLMT mode to CLS on single port net.\n"))
3095 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
3096 ("SK_RLMT_MODE_CHANGE Event EMPTY.\n"))
3100 /* Update RLMT mode. */
3101 PrevRlmtMode
= pAC
->Rlmt
.Net
[Para
.Para32
[1]].RlmtMode
;
3102 pAC
->Rlmt
.Net
[Para
.Para32
[1]].RlmtMode
= Para
.Para32
[0];
3104 if ((PrevRlmtMode
& SK_RLMT_CHECK_LOC_LINK
) !=
3105 (pAC
->Rlmt
.Net
[Para
.Para32
[1]].RlmtMode
& SK_RLMT_CHECK_LOC_LINK
)) {
3106 /* SK_RLMT_CHECK_LOC_LINK bit changed. */
3107 if ((PrevRlmtMode
& SK_RLMT_CHECK_OTHERS
) == 0 &&
3108 pAC
->Rlmt
.Net
[Para
.Para32
[1]].NumPorts
> 1 &&
3109 pAC
->Rlmt
.Net
[Para
.Para32
[1]].PortsUp
>= 1) {
3110 /* 20001207 RA: Was "PortsUp == 1". */
3111 Para2
.Para32
[0] = Para
.Para32
[1];
3112 Para2
.Para32
[1] = (SK_U32
)-1;
3113 SkTimerStart(pAC
, IoC
, &pAC
->Rlmt
.Net
[Para
.Para32
[1]].LocTimer
,
3114 pAC
->Rlmt
.Net
[Para
.Para32
[1]].TimeoutValue
,
3115 SKGE_RLMT
, SK_RLMT_TIM
, Para2
);
3119 if ((PrevRlmtMode
& SK_RLMT_CHECK_SEG
) !=
3120 (pAC
->Rlmt
.Net
[Para
.Para32
[1]].RlmtMode
& SK_RLMT_CHECK_SEG
)) {
3121 /* SK_RLMT_CHECK_SEG bit changed. */
3122 for (i
= 0; i
< pAC
->Rlmt
.Net
[Para
.Para32
[1]].NumPorts
; i
++) {
3123 (void)SkAddrMcClear(pAC
, IoC
,
3124 pAC
->Rlmt
.Net
[Para
.Para32
[1]].Port
[i
]->PortNumber
,
3125 SK_ADDR_PERMANENT
| SK_MC_SW_ONLY
);
3127 /* Add RLMT MC address. */
3128 (void)SkAddrMcAdd(pAC
, IoC
,
3129 pAC
->Rlmt
.Net
[Para
.Para32
[1]].Port
[i
]->PortNumber
,
3130 &SkRlmtMcAddr
, SK_ADDR_PERMANENT
);
3132 if ((pAC
->Rlmt
.Net
[Para
.Para32
[1]].RlmtMode
&
3133 SK_RLMT_CHECK_SEG
) != 0) {
3134 /* Add BPDU MC address. */
3135 (void)SkAddrMcAdd(pAC
, IoC
,
3136 pAC
->Rlmt
.Net
[Para
.Para32
[1]].Port
[i
]->PortNumber
,
3137 &BridgeMcAddr
, SK_ADDR_PERMANENT
);
3139 if (pAC
->Rlmt
.Net
[Para
.Para32
[1]].RlmtState
!= SK_RLMT_RS_INIT
) {
3140 if (!pAC
->Rlmt
.Net
[Para
.Para32
[1]].Port
[i
]->LinkDown
&&
3141 (Para2
.pParaPtr
= SkRlmtBuildSpanningTreePacket(
3142 pAC
, IoC
, i
)) != NULL
) {
3143 pAC
->Rlmt
.Net
[Para
.Para32
[1]].Port
[i
]->RootIdSet
=
3145 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_RLMT_SEND
, Para2
);
3149 (void)SkAddrMcUpdate(pAC
, IoC
,
3150 pAC
->Rlmt
.Net
[Para
.Para32
[1]].Port
[i
]->PortNumber
);
3153 if ((pAC
->Rlmt
.Net
[Para
.Para32
[1]].RlmtMode
& SK_RLMT_CHECK_SEG
) != 0) {
3154 Para2
.Para32
[0] = Para
.Para32
[1];
3155 Para2
.Para32
[1] = (SK_U32
)-1;
3156 SkTimerStart(pAC
, IoC
, &pAC
->Rlmt
.Net
[Para
.Para32
[1]].SegTimer
,
3157 SK_RLMT_SEG_TO_VAL
, SKGE_RLMT
, SK_RLMT_SEG_TIM
, Para2
);
3159 } /* SK_RLMT_CHECK_SEG bit changed. */
3161 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
3162 ("SK_RLMT_MODE_CHANGE Event END.\n"))
3163 } /* SkRlmtEvtModeChange */
3166 /******************************************************************************
3168 * SkRlmtEvent - a PORT- or an RLMT-specific event happened
3171 * This routine calls subroutines to handle PORT- and RLMT-specific events.
3174 * runtime, pageable?
3175 * may be called after SK_INIT_IO
3181 SK_AC
*pAC
, /* Adapter Context */
3182 SK_IOC IoC
, /* I/O Context */
3183 SK_U32 Event
, /* Event code */
3184 SK_EVPARA Para
) /* Event-specific parameter */
3188 /* ----- PORT events ----- */
3190 case SK_RLMT_PORTSTART_TIM
: /* From RLMT via TIME. */
3191 SkRlmtEvtPortStartTim(pAC
, IoC
, Para
);
3193 case SK_RLMT_LINK_UP
: /* From SIRQ. */
3194 SkRlmtEvtLinkUp(pAC
, IoC
, Para
);
3196 case SK_RLMT_PORTUP_TIM
: /* From RLMT via TIME. */
3197 SkRlmtEvtPortUpTim(pAC
, IoC
, Para
);
3199 case SK_RLMT_PORTDOWN
: /* From RLMT. */
3200 case SK_RLMT_PORTDOWN_RX_TIM
: /* From RLMT via TIME. */
3201 case SK_RLMT_PORTDOWN_TX_TIM
: /* From RLMT via TIME. */
3202 SkRlmtEvtPortDownX(pAC
, IoC
, Event
, Para
);
3204 case SK_RLMT_LINK_DOWN
: /* From SIRQ. */
3205 SkRlmtEvtLinkDown(pAC
, IoC
, Para
);
3207 case SK_RLMT_PORT_ADDR
: /* From ADDR. */
3208 SkRlmtEvtPortAddr(pAC
, IoC
, Para
);
3211 /* ----- RLMT events ----- */
3213 case SK_RLMT_START
: /* From DRV. */
3214 SkRlmtEvtStart(pAC
, IoC
, Para
);
3216 case SK_RLMT_STOP
: /* From DRV. */
3217 SkRlmtEvtStop(pAC
, IoC
, Para
);
3219 case SK_RLMT_TIM
: /* From RLMT via TIME. */
3220 SkRlmtEvtTim(pAC
, IoC
, Para
);
3222 case SK_RLMT_SEG_TIM
:
3223 SkRlmtEvtSegTim(pAC
, IoC
, Para
);
3225 case SK_RLMT_PACKET_RECEIVED
: /* From DRV. */
3226 SkRlmtEvtPacketRx(pAC
, IoC
, Para
);
3228 case SK_RLMT_STATS_CLEAR
: /* From PNMI. */
3229 SkRlmtEvtStatsClear(pAC
, IoC
, Para
);
3231 case SK_RLMT_STATS_UPDATE
: /* From PNMI. */
3232 SkRlmtEvtStatsUpdate(pAC
, IoC
, Para
);
3234 case SK_RLMT_PREFPORT_CHANGE
: /* From PNMI. */
3235 SkRlmtEvtPrefportChange(pAC
, IoC
, Para
);
3237 case SK_RLMT_MODE_CHANGE
: /* From PNMI. */
3238 SkRlmtEvtModeChange(pAC
, IoC
, Para
);
3240 case SK_RLMT_SET_NETS
: /* From DRV. */
3241 SkRlmtEvtSetNets(pAC
, IoC
, Para
);
3244 /* ----- Unknown events ----- */
3246 default: /* Create error log entry. */
3247 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
3248 ("Unknown RLMT Event %d.\n", Event
))
3249 SK_ERR_LOG(pAC
, SK_ERRCL_SW
, SKERR_RLMT_E003
, SKERR_RLMT_E003_MSG
);
3258 #endif /* __cplusplus */