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}};
286 /* local variables ************************************************************/
290 /* functions ******************************************************************/
292 RLMT_STATIC
void SkRlmtCheckSwitch(
296 RLMT_STATIC
void SkRlmtCheckSeg(
300 RLMT_STATIC
void SkRlmtEvtSetNets(
305 /******************************************************************************
307 * SkRlmtInit - initialize data, set state to init
314 * This routine initializes all RLMT-related variables to a known state.
315 * The initial state is SK_RLMT_RS_INIT.
316 * All ports are initialized to SK_RLMT_PS_INIT.
328 * Determine the adapter's random value.
329 * Set the hw registers, the "logical MAC address", the
330 * RLMT multicast address, and eventually the BPDU multicast address.
339 SK_AC
*pAC
, /* Adapter Context */
340 SK_IOC IoC
, /* I/O Context */
341 int Level
) /* Initialization Level */
346 SK_MAC_ADDR VirtualMacAddress
;
347 SK_MAC_ADDR PhysicalAMacAddress
;
348 SK_BOOL VirtualMacAddressSet
;
349 SK_BOOL PhysicalAMacAddressSet
;
351 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_INIT
,
352 ("RLMT Init level %d.\n", Level
))
355 case SK_INIT_DATA
: /* Initialize data structures. */
356 SK_MEMSET((char *)&pAC
->Rlmt
, 0, sizeof(SK_RLMT
));
358 for (i
= 0; i
< SK_MAX_MACS
; i
++) {
359 pAC
->Rlmt
.Port
[i
].PortState
= SK_RLMT_PS_INIT
;
360 pAC
->Rlmt
.Port
[i
].LinkDown
= SK_TRUE
;
361 pAC
->Rlmt
.Port
[i
].PortDown
= SK_TRUE
;
362 pAC
->Rlmt
.Port
[i
].PortStarted
= SK_FALSE
;
363 pAC
->Rlmt
.Port
[i
].PortNoRx
= SK_FALSE
;
364 pAC
->Rlmt
.Port
[i
].RootIdSet
= SK_FALSE
;
365 pAC
->Rlmt
.Port
[i
].PortNumber
= i
;
366 pAC
->Rlmt
.Port
[i
].Net
= &pAC
->Rlmt
.Net
[0];
367 pAC
->Rlmt
.Port
[i
].AddrPort
= &pAC
->Addr
.Port
[i
];
370 pAC
->Rlmt
.NumNets
= 1;
371 for (i
= 0; i
< SK_MAX_NETS
; i
++) {
372 pAC
->Rlmt
.Net
[i
].RlmtState
= SK_RLMT_RS_INIT
;
373 pAC
->Rlmt
.Net
[i
].RootIdSet
= SK_FALSE
;
374 pAC
->Rlmt
.Net
[i
].PrefPort
= SK_RLMT_DEF_PREF_PORT
;
375 pAC
->Rlmt
.Net
[i
].Preference
= 0xFFFFFFFF; /* Automatic. */
377 pAC
->Rlmt
.Net
[i
].ActivePort
= pAC
->Rlmt
.Net
[i
].PrefPort
;
378 pAC
->Rlmt
.Net
[i
].RlmtMode
= SK_RLMT_DEF_MODE
;
379 pAC
->Rlmt
.Net
[i
].TimeoutValue
= SK_RLMT_DEF_TO_VAL
;
380 pAC
->Rlmt
.Net
[i
].NetNumber
= i
;
383 pAC
->Rlmt
.Net
[0].Port
[0] = &pAC
->Rlmt
.Port
[0];
384 pAC
->Rlmt
.Net
[0].Port
[1] = &pAC
->Rlmt
.Port
[1];
386 pAC
->Rlmt
.Net
[1].Port
[0] = &pAC
->Rlmt
.Port
[1];
387 #endif /* SK_MAX_NETS > 1 */
390 case SK_INIT_IO
: /* GIMacsFound first available here. */
391 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_INIT
,
392 ("RLMT: %d MACs were detected.\n", pAC
->GIni
.GIMacsFound
))
394 pAC
->Rlmt
.Net
[0].NumPorts
= pAC
->GIni
.GIMacsFound
;
396 /* Initialize HW registers? */
397 if (pAC
->GIni
.GIMacsFound
== 1) {
398 Para
.Para32
[0] = SK_RLMT_MODE_CLS
;
400 (void)SkRlmtEvent(pAC
, IoC
, SK_RLMT_MODE_CHANGE
, Para
);
405 /* Ensure RLMT is set to one net. */
406 if (pAC
->Rlmt
.NumNets
> 1) {
409 SkRlmtEvtSetNets(pAC
, IoC
, Para
);
412 for (i
= 0; i
< (SK_U32
)pAC
->GIni
.GIMacsFound
; i
++) {
413 Random
= SkOsGetTime(pAC
);
414 *(SK_U32
*)&pAC
->Rlmt
.Port
[i
].Random
= *(SK_U32
*)&Random
;
416 for (j
= 0; j
< 4; j
++) {
417 pAC
->Rlmt
.Port
[i
].Random
[j
] ^= pAC
->Rlmt
.Port
[i
].AddrPort
->
418 CurrentMacAddress
.a
[SK_MAC_ADDR_LEN
- 1 - j
];
421 (void)SkAddrMcClear(pAC
, IoC
, i
, SK_ADDR_PERMANENT
| SK_MC_SW_ONLY
);
423 /* Add RLMT MC address. */
424 (void)SkAddrMcAdd(pAC
, IoC
, i
, &SkRlmtMcAddr
, SK_ADDR_PERMANENT
);
426 if (pAC
->Rlmt
.Net
[0].RlmtMode
& SK_RLMT_CHECK_SEG
) {
427 /* Add BPDU MC address. */
428 (void)SkAddrMcAdd(pAC
, IoC
, i
, &BridgeMcAddr
, SK_ADDR_PERMANENT
);
431 (void)SkAddrMcUpdate(pAC
, IoC
, i
);
434 VirtualMacAddressSet
= SK_FALSE
;
435 /* Read virtual MAC address from Control Register File. */
436 for (j
= 0; j
< SK_MAC_ADDR_LEN
; j
++) {
438 SK_IN8(IoC
, B2_MAC_1
+ j
, &VirtualMacAddress
.a
[j
]);
439 VirtualMacAddressSet
|= VirtualMacAddress
.a
[j
];
442 PhysicalAMacAddressSet
= SK_FALSE
;
443 /* Read physical MAC address for MAC A from Control Register File. */
444 for (j
= 0; j
< SK_MAC_ADDR_LEN
; j
++) {
446 SK_IN8(IoC
, B2_MAC_2
+ j
, &PhysicalAMacAddress
.a
[j
]);
447 PhysicalAMacAddressSet
|= PhysicalAMacAddress
.a
[j
];
450 /* check if the two mac addresses contain reasonable values */
451 if (!VirtualMacAddressSet
|| !PhysicalAMacAddressSet
) {
453 pAC
->Rlmt
.RlmtOff
= SK_TRUE
;
456 /* if the two mac addresses are equal switch off the RLMT_PRE_LOOKAHEAD
457 and the RLMT_LOOKAHEAD macros */
458 else if (SK_ADDR_EQUAL(PhysicalAMacAddress
.a
, VirtualMacAddress
.a
)) {
460 pAC
->Rlmt
.RlmtOff
= SK_TRUE
;
463 pAC
->Rlmt
.RlmtOff
= SK_FALSE
;
474 /******************************************************************************
476 * SkRlmtBuildCheckChain - build the check chain
479 * This routine builds the local check chain:
480 * - Each port that is up checks the next port.
481 * - The last port that is up checks the first port that is up.
484 * - Currently only local ports are considered when building the chain.
485 * - Currently the SuspectState is just reset;
486 * it would be better to save it ...
494 RLMT_STATIC
void SkRlmtBuildCheckChain(
495 SK_AC
*pAC
, /* Adapter Context */
496 SK_U32 NetIdx
) /* Net Number */
500 SK_RLMT_PORT
* FirstMacUp
;
501 SK_RLMT_PORT
* PrevMacUp
;
506 if (!(pAC
->Rlmt
.Net
[NetIdx
].RlmtMode
& SK_RLMT_CHECK_LOC_LINK
)) {
507 for (i
= 0; i
< pAC
->Rlmt
.Net
[i
].NumPorts
; i
++) {
508 pAC
->Rlmt
.Net
[NetIdx
].Port
[i
]->PortsChecked
= 0;
513 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
514 ("SkRlmtBuildCheckChain.\n"))
518 for (i
= 0; i
< pAC
->Rlmt
.Net
[NetIdx
].NumPorts
; i
++) {
519 pAC
->Rlmt
.Net
[NetIdx
].Port
[i
]->PortsChecked
= 0;
520 pAC
->Rlmt
.Net
[NetIdx
].Port
[i
]->PortsSuspect
= 0;
521 pAC
->Rlmt
.Net
[NetIdx
].Port
[i
]->CheckingState
&=
522 ~(SK_RLMT_PCS_RX
| SK_RLMT_PCS_TX
);
525 * If more than two links are detected we should consider
526 * checking at least two other ports:
527 * 1. the next port that is not LinkDown and
528 * 2. the next port that is not PortDown.
530 if (!pAC
->Rlmt
.Net
[NetIdx
].Port
[i
]->LinkDown
) {
531 if (NumMacsUp
== 0) {
532 FirstMacUp
= pAC
->Rlmt
.Net
[NetIdx
].Port
[i
];
535 PrevMacUp
->PortCheck
[
536 pAC
->Rlmt
.Net
[NetIdx
].Port
[i
]->PortsChecked
].CheckAddr
=
537 pAC
->Rlmt
.Net
[NetIdx
].Port
[i
]->AddrPort
->CurrentMacAddress
;
538 PrevMacUp
->PortCheck
[
539 PrevMacUp
->PortsChecked
].SuspectTx
= SK_FALSE
;
540 PrevMacUp
->PortsChecked
++;
542 PrevMacUp
= pAC
->Rlmt
.Net
[NetIdx
].Port
[i
];
548 PrevMacUp
->PortCheck
[PrevMacUp
->PortsChecked
].CheckAddr
=
549 FirstMacUp
->AddrPort
->CurrentMacAddress
;
550 PrevMacUp
->PortCheck
[PrevMacUp
->PortsChecked
].SuspectTx
=
552 PrevMacUp
->PortsChecked
++;
556 for (i
= 0; i
< pAC
->Rlmt
.Net
[NetIdx
].NumPorts
; i
++) {
557 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
558 ("Port %d checks %d other ports: %2X.\n", i
,
559 pAC
->Rlmt
.Net
[NetIdx
].Port
[i
]->PortsChecked
,
560 pAC
->Rlmt
.Net
[NetIdx
].Port
[i
]->PortCheck
[0].CheckAddr
.a
[5]))
565 } /* SkRlmtBuildCheckChain */
568 /******************************************************************************
570 * SkRlmtBuildPacket - build an RLMT packet
573 * This routine sets up an RLMT packet.
579 * NULL or pointer to RLMT mbuf
581 RLMT_STATIC SK_MBUF
*SkRlmtBuildPacket(
582 SK_AC
*pAC
, /* Adapter Context */
583 SK_IOC IoC
, /* I/O Context */
584 SK_U32 PortNumber
, /* Sending port */
585 SK_U16 PacketType
, /* RLMT packet type */
586 SK_MAC_ADDR
*SrcAddr
, /* Source address */
587 SK_MAC_ADDR
*DestAddr
) /* Destination address */
592 SK_RLMT_PACKET
*pPacket
;
598 for (i
= 0; i
< SK_MAC_ADDR_LEN
; ++i
) {
599 CheckSrc
|= SrcAddr
->a
[i
];
600 CheckDest
|= DestAddr
->a
[i
];
603 if ((CheckSrc
== 0) || (CheckDest
== 0)) {
604 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_ERR
,
605 ("SkRlmtBuildPacket: Invalid %s%saddr.\n",
606 (CheckSrc
== 0 ? "Src" : ""), (CheckDest
== 0 ? "Dest" : "")))
610 if ((pMb
= SkDrvAllocRlmtMbuf(pAC
, IoC
, SK_RLMT_MAX_PACKET_SIZE
)) != NULL
) {
611 pPacket
= (SK_RLMT_PACKET
*)pMb
->pData
;
612 for (i
= 0; i
< SK_MAC_ADDR_LEN
; i
++) {
613 pPacket
->DstAddr
[i
] = DestAddr
->a
[i
];
614 pPacket
->SrcAddr
[i
] = SrcAddr
->a
[i
];
616 pPacket
->DSap
= SK_RLMT_DSAP
;
617 pPacket
->SSap
= SK_RLMT_SSAP
;
618 pPacket
->Ctrl
= SK_RLMT_CTRL
;
619 pPacket
->Indicator
[0] = SK_RLMT_INDICATOR0
;
620 pPacket
->Indicator
[1] = SK_RLMT_INDICATOR1
;
621 pPacket
->Indicator
[2] = SK_RLMT_INDICATOR2
;
622 pPacket
->Indicator
[3] = SK_RLMT_INDICATOR3
;
623 pPacket
->Indicator
[4] = SK_RLMT_INDICATOR4
;
624 pPacket
->Indicator
[5] = SK_RLMT_INDICATOR5
;
625 pPacket
->Indicator
[6] = SK_RLMT_INDICATOR6
;
627 SK_U16_TO_NETWORK_ORDER(PacketType
, &pPacket
->RlmtPacketType
[0]);
629 for (i
= 0; i
< 4; i
++) {
630 pPacket
->Random
[i
] = pAC
->Rlmt
.Port
[PortNumber
].Random
[i
];
633 SK_U16_TO_NETWORK_ORDER(
634 SK_RLMT_PACKET_VERSION
, &pPacket
->RlmtPacketVersion
[0]);
636 for (i
= 0; i
< SK_PACKET_DATA_LEN
; i
++) {
637 pPacket
->Data
[i
] = 0x00;
640 Length
= SK_RLMT_MAX_PACKET_SIZE
; /* Or smaller. */
641 pMb
->Length
= Length
;
642 pMb
->PortIdx
= PortNumber
;
644 SK_U16_TO_NETWORK_ORDER(Length
, &pPacket
->TypeLen
[0]);
646 if (PacketType
== SK_PACKET_ALIVE
) {
647 pAC
->Rlmt
.Port
[PortNumber
].TxHelloCts
++;
652 } /* SkRlmtBuildPacket */
655 /******************************************************************************
657 * SkRlmtBuildSpanningTreePacket - build spanning tree check packet
660 * This routine sets up a BPDU packet for spanning tree check.
666 * NULL or pointer to RLMT mbuf
668 RLMT_STATIC SK_MBUF
*SkRlmtBuildSpanningTreePacket(
669 SK_AC
*pAC
, /* Adapter Context */
670 SK_IOC IoC
, /* I/O Context */
671 SK_U32 PortNumber
) /* Sending port */
676 SK_SPTREE_PACKET
*pSPacket
;
678 if ((pMb
= SkDrvAllocRlmtMbuf(pAC
, IoC
, SK_RLMT_MAX_PACKET_SIZE
)) !=
680 pSPacket
= (SK_SPTREE_PACKET
*)pMb
->pData
;
681 for (i
= 0; i
< SK_MAC_ADDR_LEN
; i
++) {
682 pSPacket
->DstAddr
[i
] = BridgeMcAddr
.a
[i
];
683 pSPacket
->SrcAddr
[i
] =
684 pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
.a
[i
];
686 pSPacket
->DSap
= SK_RLMT_SPT_DSAP
;
687 pSPacket
->SSap
= SK_RLMT_SPT_SSAP
;
688 pSPacket
->Ctrl
= SK_RLMT_SPT_CTRL
;
690 pSPacket
->ProtocolId
[0] = SK_RLMT_SPT_PROTOCOL_ID0
;
691 pSPacket
->ProtocolId
[1] = SK_RLMT_SPT_PROTOCOL_ID1
;
692 pSPacket
->ProtocolVersionId
= SK_RLMT_SPT_PROTOCOL_VERSION_ID
;
693 pSPacket
->BpduType
= SK_RLMT_SPT_BPDU_TYPE
;
694 pSPacket
->Flags
= SK_RLMT_SPT_FLAGS
;
695 pSPacket
->RootId
[0] = SK_RLMT_SPT_ROOT_ID0
;
696 pSPacket
->RootId
[1] = SK_RLMT_SPT_ROOT_ID1
;
697 pSPacket
->RootPathCost
[0] = SK_RLMT_SPT_ROOT_PATH_COST0
;
698 pSPacket
->RootPathCost
[1] = SK_RLMT_SPT_ROOT_PATH_COST1
;
699 pSPacket
->RootPathCost
[2] = SK_RLMT_SPT_ROOT_PATH_COST2
;
700 pSPacket
->RootPathCost
[3] = SK_RLMT_SPT_ROOT_PATH_COST3
;
701 pSPacket
->BridgeId
[0] = SK_RLMT_SPT_BRIDGE_ID0
;
702 pSPacket
->BridgeId
[1] = SK_RLMT_SPT_BRIDGE_ID1
;
705 * Use logical MAC address as bridge ID and filter these packets
708 for (i
= 0; i
< SK_MAC_ADDR_LEN
; i
++) {
709 pSPacket
->BridgeId
[i
+ 2] = pSPacket
->RootId
[i
+ 2] =
710 pAC
->Addr
.Net
[pAC
->Rlmt
.Port
[PortNumber
].Net
->NetNumber
].
711 CurrentMacAddress
.a
[i
];
713 pSPacket
->PortId
[0] = SK_RLMT_SPT_PORT_ID0
;
714 pSPacket
->PortId
[1] = SK_RLMT_SPT_PORT_ID1
;
715 pSPacket
->MessageAge
[0] = SK_RLMT_SPT_MSG_AGE0
;
716 pSPacket
->MessageAge
[1] = SK_RLMT_SPT_MSG_AGE1
;
717 pSPacket
->MaxAge
[0] = SK_RLMT_SPT_MAX_AGE0
;
718 pSPacket
->MaxAge
[1] = SK_RLMT_SPT_MAX_AGE1
;
719 pSPacket
->HelloTime
[0] = SK_RLMT_SPT_HELLO_TIME0
;
720 pSPacket
->HelloTime
[1] = SK_RLMT_SPT_HELLO_TIME1
;
721 pSPacket
->ForwardDelay
[0] = SK_RLMT_SPT_FWD_DELAY0
;
722 pSPacket
->ForwardDelay
[1] = SK_RLMT_SPT_FWD_DELAY1
;
724 Length
= SK_RLMT_MAX_PACKET_SIZE
; /* Or smaller. */
725 pMb
->Length
= Length
;
726 pMb
->PortIdx
= PortNumber
;
728 SK_U16_TO_NETWORK_ORDER(Length
, &pSPacket
->TypeLen
[0]);
730 pAC
->Rlmt
.Port
[PortNumber
].TxSpHelloReqCts
++;
734 } /* SkRlmtBuildSpanningTreePacket */
737 /******************************************************************************
739 * SkRlmtSend - build and send check packets
742 * Depending on the RLMT state and the checking state, several packets
743 * are sent through the indicated port.
751 RLMT_STATIC
void SkRlmtSend(
752 SK_AC
*pAC
, /* Adapter Context */
753 SK_IOC IoC
, /* I/O Context */
754 SK_U32 PortNumber
) /* Sending port */
758 SK_RLMT_PORT
*pRPort
;
760 pRPort
= &pAC
->Rlmt
.Port
[PortNumber
];
761 if (pAC
->Rlmt
.Port
[PortNumber
].Net
->RlmtMode
& SK_RLMT_CHECK_LOC_LINK
) {
762 if (pRPort
->CheckingState
& (SK_RLMT_PCS_TX
| SK_RLMT_PCS_RX
)) {
763 /* Port is suspicious. Send the RLMT packet to the RLMT mc addr. */
764 if ((Para
.pParaPtr
= SkRlmtBuildPacket(pAC
, IoC
, PortNumber
,
765 SK_PACKET_ALIVE
, &pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
,
766 &SkRlmtMcAddr
)) != NULL
) {
767 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_RLMT_SEND
, Para
);
772 * Send a directed RLMT packet to all ports that are
773 * checked by the indicated port.
775 for (j
= 0; j
< pRPort
->PortsChecked
; j
++) {
776 if ((Para
.pParaPtr
= SkRlmtBuildPacket(pAC
, IoC
, PortNumber
,
777 SK_PACKET_ALIVE
, &pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
,
778 &pRPort
->PortCheck
[j
].CheckAddr
)) != NULL
) {
779 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_RLMT_SEND
, Para
);
785 if ((pAC
->Rlmt
.Port
[PortNumber
].Net
->RlmtMode
& SK_RLMT_CHECK_SEG
) &&
786 (pAC
->Rlmt
.Port
[PortNumber
].Net
->CheckingState
& SK_RLMT_RCS_SEND_SEG
)) {
788 * Send a BPDU packet to make a connected switch tell us
789 * the correct root bridge.
792 SkRlmtBuildSpanningTreePacket(pAC
, IoC
, PortNumber
)) != NULL
) {
793 pAC
->Rlmt
.Port
[PortNumber
].Net
->CheckingState
&= ~SK_RLMT_RCS_SEND_SEG
;
794 pRPort
->RootIdSet
= SK_FALSE
;
796 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_RLMT_SEND
, Para
);
797 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_TX
,
798 ("SkRlmtSend: BPDU Packet on Port %u.\n", PortNumber
))
805 /******************************************************************************
807 * SkRlmtPortReceives - check if port is (going) down and bring it up
810 * This routine checks if a port who received a non-BPDU packet
811 * needs to go up or needs to be stopped going down.
819 RLMT_STATIC
void SkRlmtPortReceives(
820 SK_AC
*pAC
, /* Adapter Context */
821 SK_IOC IoC
, /* I/O Context */
822 SK_U32 PortNumber
) /* Port to check */
824 SK_RLMT_PORT
*pRPort
;
827 pRPort
= &pAC
->Rlmt
.Port
[PortNumber
];
828 pRPort
->PortNoRx
= SK_FALSE
;
830 if ((pRPort
->PortState
== SK_RLMT_PS_DOWN
) &&
831 !(pRPort
->CheckingState
& SK_RLMT_PCS_TX
)) {
833 * Port is marked down (rx), but received a non-BPDU packet.
836 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
837 ("SkRlmtPacketReceive: Received on PortDown.\n"))
839 pRPort
->PortState
= SK_RLMT_PS_GOING_UP
;
840 pRPort
->GuTimeStamp
= SkOsGetTime(pAC
);
841 Para
.Para32
[0] = PortNumber
;
842 Para
.Para32
[1] = (SK_U32
)-1;
843 SkTimerStart(pAC
, IoC
, &pRPort
->UpTimer
, SK_RLMT_PORTUP_TIM_VAL
,
844 SKGE_RLMT
, SK_RLMT_PORTUP_TIM
, Para
);
845 pRPort
->CheckingState
&= ~SK_RLMT_PCS_RX
;
846 /* pAC->Rlmt.CheckSwitch = SK_TRUE; */
847 SkRlmtCheckSwitch(pAC
, IoC
, pRPort
->Net
->NetNumber
);
848 } /* PortDown && !SuspectTx */
849 else if (pRPort
->CheckingState
& SK_RLMT_PCS_RX
) {
850 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
851 ("SkRlmtPacketReceive: Stop bringing port down.\n"))
852 SkTimerStop(pAC
, IoC
, &pRPort
->DownRxTimer
);
853 pRPort
->CheckingState
&= ~SK_RLMT_PCS_RX
;
854 /* pAC->Rlmt.CheckSwitch = SK_TRUE; */
855 SkRlmtCheckSwitch(pAC
, IoC
, pRPort
->Net
->NetNumber
);
856 } /* PortGoingDown */
859 } /* SkRlmtPortReceives */
862 /******************************************************************************
864 * SkRlmtPacketReceive - receive a packet for closer examination
867 * This routine examines a packet more closely than SK_RLMT_LOOKAHEAD.
875 RLMT_STATIC
void SkRlmtPacketReceive(
876 SK_AC
*pAC
, /* Adapter Context */
877 SK_IOC IoC
, /* I/O Context */
878 SK_MBUF
*pMb
) /* Received packet */
881 extern void DumpData(char *p
, int size
);
887 SK_ADDR_PORT
*pAPort
;
888 SK_RLMT_PORT
*pRPort
;
889 SK_RLMT_PACKET
*pRPacket
;
890 SK_SPTREE_PACKET
*pSPacket
;
893 PortNumber
= pMb
->PortIdx
;
894 pAPort
= &pAC
->Addr
.Port
[PortNumber
];
895 pRPort
= &pAC
->Rlmt
.Port
[PortNumber
];
897 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
898 ("SkRlmtPacketReceive: PortNumber == %d.\n", PortNumber
))
900 pRPacket
= (SK_RLMT_PACKET
*)pMb
->pData
;
901 pSPacket
= (SK_SPTREE_PACKET
*)pRPacket
;
904 DumpData((char *)pRPacket
, 32);
907 if ((pRPort
->PacketsPerTimeSlot
- pRPort
->BpduPacketsPerTimeSlot
) != 0) {
908 SkRlmtPortReceives(pAC
, IoC
, PortNumber
);
911 /* Check destination address. */
913 if (!SK_ADDR_EQUAL(pAPort
->CurrentMacAddress
.a
, pRPacket
->DstAddr
) &&
914 !SK_ADDR_EQUAL(SkRlmtMcAddr
.a
, pRPacket
->DstAddr
) &&
915 !SK_ADDR_EQUAL(BridgeMcAddr
.a
, pRPacket
->DstAddr
)) {
917 /* Not sent to current MAC or registered MC address => Trash it. */
918 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
919 ("SkRlmtPacketReceive: Not for me.\n"))
921 SkDrvFreeRlmtMbuf(pAC
, IoC
, pMb
);
924 else if (SK_ADDR_EQUAL(pAPort
->CurrentMacAddress
.a
, pRPacket
->SrcAddr
)) {
927 * Was sent by same port (may happen during port switching
928 * or in case of duplicate MAC addresses).
932 * Check for duplicate address here:
933 * If Packet.Random != My.Random => DupAddr.
935 for (i
= 3; i
>= 0; i
--) {
936 if (pRPort
->Random
[i
] != pRPacket
->Random
[i
]) {
942 * CAUTION: Do not check for duplicate MAC address in RLMT Alive Reply
943 * packets (they have the LLC_COMMAND_RESPONSE_BIT set in
946 if (i
>= 0 && pRPacket
->DSap
== SK_RLMT_DSAP
&&
947 pRPacket
->Ctrl
== SK_RLMT_CTRL
&&
948 pRPacket
->SSap
== SK_RLMT_SSAP
&&
949 pRPacket
->Indicator
[0] == SK_RLMT_INDICATOR0
&&
950 pRPacket
->Indicator
[1] == SK_RLMT_INDICATOR1
&&
951 pRPacket
->Indicator
[2] == SK_RLMT_INDICATOR2
&&
952 pRPacket
->Indicator
[3] == SK_RLMT_INDICATOR3
&&
953 pRPacket
->Indicator
[4] == SK_RLMT_INDICATOR4
&&
954 pRPacket
->Indicator
[5] == SK_RLMT_INDICATOR5
&&
955 pRPacket
->Indicator
[6] == SK_RLMT_INDICATOR6
) {
956 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
957 ("SkRlmtPacketReceive: Duplicate MAC Address.\n"))
959 /* Error Log entry. */
960 SK_ERR_LOG(pAC
, SK_ERRCL_COMM
, SKERR_RLMT_E006
, SKERR_RLMT_E006_MSG
);
963 /* Simply trash it. */
964 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
965 ("SkRlmtPacketReceive: Sent by me.\n"))
968 SkDrvFreeRlmtMbuf(pAC
, IoC
, pMb
);
972 /* Check SuspectTx entries. */
973 if (pRPort
->PortsSuspect
> 0) {
974 for (j
= 0; j
< pRPort
->PortsChecked
; j
++) {
975 if (pRPort
->PortCheck
[j
].SuspectTx
&&
977 pRPacket
->SrcAddr
, pRPort
->PortCheck
[j
].CheckAddr
.a
)) {
978 pRPort
->PortCheck
[j
].SuspectTx
= SK_FALSE
;
979 pRPort
->PortsSuspect
--;
985 /* Determine type of packet. */
986 if (pRPacket
->DSap
== SK_RLMT_DSAP
&&
987 pRPacket
->Ctrl
== SK_RLMT_CTRL
&&
988 (pRPacket
->SSap
& ~LLC_COMMAND_RESPONSE_BIT
) == SK_RLMT_SSAP
&&
989 pRPacket
->Indicator
[0] == SK_RLMT_INDICATOR0
&&
990 pRPacket
->Indicator
[1] == SK_RLMT_INDICATOR1
&&
991 pRPacket
->Indicator
[2] == SK_RLMT_INDICATOR2
&&
992 pRPacket
->Indicator
[3] == SK_RLMT_INDICATOR3
&&
993 pRPacket
->Indicator
[4] == SK_RLMT_INDICATOR4
&&
994 pRPacket
->Indicator
[5] == SK_RLMT_INDICATOR5
&&
995 pRPacket
->Indicator
[6] == SK_RLMT_INDICATOR6
) {
997 /* It's an RLMT packet. */
998 PacketType
= (SK_U16
)((pRPacket
->RlmtPacketType
[0] << 8) |
999 pRPacket
->RlmtPacketType
[1]);
1001 switch (PacketType
) {
1002 case SK_PACKET_ANNOUNCE
: /* Not yet used. */
1004 /* Build the check chain. */
1005 SkRlmtBuildCheckChain(pAC
);
1008 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
1009 ("SkRlmtPacketReceive: Announce.\n"))
1011 SkDrvFreeRlmtMbuf(pAC
, IoC
, pMb
);
1014 case SK_PACKET_ALIVE
:
1015 if (pRPacket
->SSap
& LLC_COMMAND_RESPONSE_BIT
) {
1016 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
1017 ("SkRlmtPacketReceive: Alive Reply.\n"))
1019 if (!(pAC
->Addr
.Port
[PortNumber
].PromMode
& SK_PROM_MODE_LLC
) ||
1021 pRPacket
->DstAddr
, pAPort
->CurrentMacAddress
.a
)) {
1022 /* Obviously we could send something. */
1023 if (pRPort
->CheckingState
& SK_RLMT_PCS_TX
) {
1024 pRPort
->CheckingState
&= ~SK_RLMT_PCS_TX
;
1025 SkTimerStop(pAC
, IoC
, &pRPort
->DownTxTimer
);
1028 if ((pRPort
->PortState
== SK_RLMT_PS_DOWN
) &&
1029 !(pRPort
->CheckingState
& SK_RLMT_PCS_RX
)) {
1030 pRPort
->PortState
= SK_RLMT_PS_GOING_UP
;
1031 pRPort
->GuTimeStamp
= SkOsGetTime(pAC
);
1033 SkTimerStop(pAC
, IoC
, &pRPort
->DownTxTimer
);
1035 Para
.Para32
[0] = PortNumber
;
1036 Para
.Para32
[1] = (SK_U32
)-1;
1037 SkTimerStart(pAC
, IoC
, &pRPort
->UpTimer
,
1038 SK_RLMT_PORTUP_TIM_VAL
, SKGE_RLMT
,
1039 SK_RLMT_PORTUP_TIM
, Para
);
1043 /* Mark sending port as alive? */
1044 SkDrvFreeRlmtMbuf(pAC
, IoC
, pMb
);
1046 else { /* Alive Request Packet. */
1047 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
1048 ("SkRlmtPacketReceive: Alive Request.\n"))
1050 pRPort
->RxHelloCts
++;
1053 for (i
= 0; i
< SK_MAC_ADDR_LEN
; i
++) {
1054 pRPacket
->DstAddr
[i
] = pRPacket
->SrcAddr
[i
];
1055 pRPacket
->SrcAddr
[i
] =
1056 pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
.a
[i
];
1058 pRPacket
->SSap
|= LLC_COMMAND_RESPONSE_BIT
;
1060 Para
.pParaPtr
= pMb
;
1061 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_RLMT_SEND
, Para
);
1065 case SK_PACKET_CHECK_TX
:
1066 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
1067 ("SkRlmtPacketReceive: Check your tx line.\n"))
1069 /* A port checking us requests us to check our tx line. */
1070 pRPort
->CheckingState
|= SK_RLMT_PCS_TX
;
1072 /* Start PortDownTx timer. */
1073 Para
.Para32
[0] = PortNumber
;
1074 Para
.Para32
[1] = (SK_U32
)-1;
1075 SkTimerStart(pAC
, IoC
, &pRPort
->DownTxTimer
,
1076 SK_RLMT_PORTDOWN_TIM_VAL
, SKGE_RLMT
,
1077 SK_RLMT_PORTDOWN_TX_TIM
, Para
);
1079 SkDrvFreeRlmtMbuf(pAC
, IoC
, pMb
);
1081 if ((Para
.pParaPtr
= SkRlmtBuildPacket(pAC
, IoC
, PortNumber
,
1082 SK_PACKET_ALIVE
, &pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
,
1083 &SkRlmtMcAddr
)) != NULL
) {
1084 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_RLMT_SEND
, Para
);
1088 case SK_PACKET_ADDR_CHANGED
:
1089 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
1090 ("SkRlmtPacketReceive: Address Change.\n"))
1092 /* Build the check chain. */
1093 SkRlmtBuildCheckChain(pAC
, pRPort
->Net
->NetNumber
);
1094 SkDrvFreeRlmtMbuf(pAC
, IoC
, pMb
);
1098 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
1099 ("SkRlmtPacketReceive: Unknown RLMT packet.\n"))
1102 SkDrvFreeRlmtMbuf(pAC
, IoC
, pMb
);
1105 else if (pSPacket
->DSap
== SK_RLMT_SPT_DSAP
&&
1106 pSPacket
->Ctrl
== SK_RLMT_SPT_CTRL
&&
1107 (pSPacket
->SSap
& ~LLC_COMMAND_RESPONSE_BIT
) == SK_RLMT_SPT_SSAP
) {
1108 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
1109 ("SkRlmtPacketReceive: BPDU Packet.\n"))
1111 /* Spanning Tree packet. */
1112 pRPort
->RxSpHelloCts
++;
1114 if (!SK_ADDR_EQUAL(&pSPacket
->RootId
[2], &pAC
->Addr
.Net
[pAC
->Rlmt
.
1115 Port
[PortNumber
].Net
->NetNumber
].CurrentMacAddress
.a
[0])) {
1117 * Check segmentation if a new root bridge is set and
1118 * the segmentation check is not currently running.
1120 if (!SK_ADDR_EQUAL(&pSPacket
->RootId
[2], &pRPort
->Root
.Id
[2]) &&
1121 (pAC
->Rlmt
.Port
[PortNumber
].Net
->LinksUp
> 1) &&
1122 (pAC
->Rlmt
.Port
[PortNumber
].Net
->RlmtMode
& SK_RLMT_CHECK_SEG
)
1123 != 0 && (pAC
->Rlmt
.Port
[PortNumber
].Net
->CheckingState
&
1124 SK_RLMT_RCS_SEG
) == 0) {
1125 pAC
->Rlmt
.Port
[PortNumber
].Net
->CheckingState
|=
1126 SK_RLMT_RCS_START_SEG
| SK_RLMT_RCS_SEND_SEG
;
1129 /* Store tree view of this port. */
1130 for (i
= 0; i
< 8; i
++) {
1131 pRPort
->Root
.Id
[i
] = pSPacket
->RootId
[i
];
1133 pRPort
->RootIdSet
= SK_TRUE
;
1135 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_DUMP
,
1136 ("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n",
1138 pRPort
->Root
.Id
[0], pRPort
->Root
.Id
[1],
1139 pRPort
->Root
.Id
[2], pRPort
->Root
.Id
[3],
1140 pRPort
->Root
.Id
[4], pRPort
->Root
.Id
[5],
1141 pRPort
->Root
.Id
[6], pRPort
->Root
.Id
[7]))
1144 SkDrvFreeRlmtMbuf(pAC
, IoC
, pMb
);
1145 if ((pAC
->Rlmt
.Port
[PortNumber
].Net
->CheckingState
&
1146 SK_RLMT_RCS_REPORT_SEG
) != 0) {
1147 SkRlmtCheckSeg(pAC
, IoC
, pAC
->Rlmt
.Port
[PortNumber
].Net
->NetNumber
);
1151 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_RX
,
1152 ("SkRlmtPacketReceive: Unknown Packet Type.\n"))
1154 /* Unknown packet. */
1155 SkDrvFreeRlmtMbuf(pAC
, IoC
, pMb
);
1158 } /* SkRlmtPacketReceive */
1161 /******************************************************************************
1163 * SkRlmtCheckPort - check if a port works
1166 * This routine checks if a port whose link is up received something
1167 * and if it seems to transmit successfully.
1169 * # PortState: PsInit, PsLinkDown, PsDown, PsGoingUp, PsUp
1170 * # PortCheckingState (Bitfield): ChkTx, ChkRx, ChkSeg
1171 * # RlmtCheckingState (Bitfield): ChkSeg, StartChkSeg, ReportSeg
1173 * if (Rx - RxBpdu == 0) { # No rx.
1174 * if (state == PsUp) {
1175 * PortCheckingState |= ChkRx
1177 * if (ModeCheckSeg && (Timeout ==
1178 * TO_SHORTEN(RLMT_DEFAULT_TIMEOUT))) {
1179 * RlmtCheckingState |= ChkSeg)
1180 * PortCheckingState |= ChkSeg
1182 * NewTimeout = TO_SHORTEN(Timeout)
1183 * if (NewTimeout < RLMT_MIN_TIMEOUT) {
1184 * NewTimeout = RLMT_MIN_TIMEOUT
1185 * PortState = PsDown
1189 * else { # something was received
1190 * # Set counter to 0 at LinkDown?
1191 * # No - rx may be reported after LinkDown ???
1192 * PortCheckingState &= ~ChkRx
1193 * NewTimeout = RLMT_DEFAULT_TIMEOUT
1196 * is my tx line bad? --
1197 * send RLMT multicast and report
1198 * back internally? (only possible
1199 * between ports on same adapter)
1203 * - tx line of port set to check me
1205 * - no other port/adapter available or set
1207 * - adapter checking me has a longer
1209 * ??? anything that can be done here?
1214 * runtime, pageable?
1217 * New timeout value.
1219 RLMT_STATIC SK_U32
SkRlmtCheckPort(
1220 SK_AC
*pAC
, /* Adapter Context */
1221 SK_IOC IoC
, /* I/O Context */
1222 SK_U32 PortNumber
) /* Port to check */
1226 SK_RLMT_PORT
*pRPort
;
1229 pRPort
= &pAC
->Rlmt
.Port
[PortNumber
];
1231 if ((pRPort
->PacketsPerTimeSlot
- pRPort
->BpduPacketsPerTimeSlot
) == 0) {
1232 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1233 ("SkRlmtCheckPort %d: No (%d) receives in last time slot.\n",
1234 PortNumber
, pRPort
->PacketsPerTimeSlot
))
1237 * Check segmentation if there was no receive at least twice
1238 * in a row (PortNoRx is already set) and the segmentation
1239 * check is not currently running.
1242 if (pRPort
->PortNoRx
&& (pAC
->Rlmt
.Port
[PortNumber
].Net
->LinksUp
> 1) &&
1243 (pAC
->Rlmt
.Port
[PortNumber
].Net
->RlmtMode
& SK_RLMT_CHECK_SEG
) &&
1244 !(pAC
->Rlmt
.Port
[PortNumber
].Net
->CheckingState
& SK_RLMT_RCS_SEG
)) {
1245 pAC
->Rlmt
.Port
[PortNumber
].Net
->CheckingState
|=
1246 SK_RLMT_RCS_START_SEG
| SK_RLMT_RCS_SEND_SEG
;
1249 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1250 ("SkRlmtCheckPort: PortsSuspect %d, PcsRx %d.\n",
1251 pRPort
->PortsSuspect
, pRPort
->CheckingState
& SK_RLMT_PCS_RX
))
1253 if (pRPort
->PortState
!= SK_RLMT_PS_DOWN
) {
1254 NewTimeout
= TO_SHORTEN(pAC
->Rlmt
.Port
[PortNumber
].Net
->TimeoutValue
);
1255 if (NewTimeout
< SK_RLMT_MIN_TO_VAL
) {
1256 NewTimeout
= SK_RLMT_MIN_TO_VAL
;
1259 if (!(pRPort
->CheckingState
& SK_RLMT_PCS_RX
)) {
1260 Para
.Para32
[0] = PortNumber
;
1261 pRPort
->CheckingState
|= SK_RLMT_PCS_RX
;
1264 * What shall we do if the port checked by this one receives
1265 * our request frames? What's bad - our rx line or his tx line?
1267 Para
.Para32
[1] = (SK_U32
)-1;
1268 SkTimerStart(pAC
, IoC
, &pRPort
->DownRxTimer
,
1269 SK_RLMT_PORTDOWN_TIM_VAL
, SKGE_RLMT
,
1270 SK_RLMT_PORTDOWN_RX_TIM
, Para
);
1272 for (i
= 0; i
< pRPort
->PortsChecked
; i
++) {
1273 if (pRPort
->PortCheck
[i
].SuspectTx
) {
1276 pRPort
->PortCheck
[i
].SuspectTx
= SK_TRUE
;
1277 pRPort
->PortsSuspect
++;
1278 if ((Para
.pParaPtr
=
1279 SkRlmtBuildPacket(pAC
, IoC
, PortNumber
, SK_PACKET_CHECK_TX
,
1280 &pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
,
1281 &pRPort
->PortCheck
[i
].CheckAddr
)) != NULL
) {
1282 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_RLMT_SEND
, Para
);
1287 else { /* PortDown -- or all partners suspect. */
1288 NewTimeout
= SK_RLMT_DEF_TO_VAL
;
1290 pRPort
->PortNoRx
= SK_TRUE
;
1292 else { /* A non-BPDU packet was received. */
1293 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1294 ("SkRlmtCheckPort %d: %d (%d) receives in last time slot.\n",
1296 pRPort
->PacketsPerTimeSlot
- pRPort
->BpduPacketsPerTimeSlot
,
1297 pRPort
->PacketsPerTimeSlot
))
1299 SkRlmtPortReceives(pAC
, IoC
, PortNumber
);
1300 if (pAC
->Rlmt
.CheckSwitch
) {
1301 SkRlmtCheckSwitch(pAC
, IoC
, pRPort
->Net
->NetNumber
);
1304 NewTimeout
= SK_RLMT_DEF_TO_VAL
;
1307 return (NewTimeout
);
1308 } /* SkRlmtCheckPort */
1311 /******************************************************************************
1313 * SkRlmtSelectBcRx - select new active port, criteria 1 (CLP)
1316 * This routine selects the port that received a broadcast frame
1317 * substantially later than all other ports.
1320 * runtime, pageable?
1325 RLMT_STATIC SK_BOOL
SkRlmtSelectBcRx(
1326 SK_AC
*pAC
, /* Adapter Context */
1327 SK_IOC IoC
, /* I/O Context */
1328 SK_U32 Active
, /* Active port */
1329 SK_U32 PrefPort
, /* Preferred port */
1330 SK_U32
*pSelect
) /* New active port */
1336 BcTimeStamp
= 0; /* Not totally necessary, but feeling better. */
1337 PortFound
= SK_FALSE
;
1339 /* Select port with the latest TimeStamp. */
1340 for (i
= 0; i
< (SK_U32
)pAC
->GIni
.GIMacsFound
; i
++) {
1342 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1343 ("TimeStamp Port %d (Down: %d, NoRx: %d): %08x %08x.\n",
1345 pAC
->Rlmt
.Port
[i
].PortDown
, pAC
->Rlmt
.Port
[i
].PortNoRx
,
1346 *((SK_U32
*)(&pAC
->Rlmt
.Port
[i
].BcTimeStamp
) + OFFS_HI32
),
1347 *((SK_U32
*)(&pAC
->Rlmt
.Port
[i
].BcTimeStamp
) + OFFS_LO32
)))
1349 if (!pAC
->Rlmt
.Port
[i
].PortDown
&& !pAC
->Rlmt
.Port
[i
].PortNoRx
) {
1350 if (!PortFound
|| pAC
->Rlmt
.Port
[i
].BcTimeStamp
> BcTimeStamp
) {
1351 BcTimeStamp
= pAC
->Rlmt
.Port
[i
].BcTimeStamp
;
1353 PortFound
= SK_TRUE
;
1359 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1360 ("Port %d received the last broadcast.\n", *pSelect
))
1362 /* Look if another port's time stamp is similar. */
1363 for (i
= 0; i
< (SK_U32
)pAC
->GIni
.GIMacsFound
; i
++) {
1364 if (i
== *pSelect
) {
1367 if (!pAC
->Rlmt
.Port
[i
].PortDown
&& !pAC
->Rlmt
.Port
[i
].PortNoRx
&&
1368 (pAC
->Rlmt
.Port
[i
].BcTimeStamp
>
1369 BcTimeStamp
- SK_RLMT_BC_DELTA
||
1370 pAC
->Rlmt
.Port
[i
].BcTimeStamp
+
1371 SK_RLMT_BC_DELTA
> BcTimeStamp
)) {
1372 PortFound
= SK_FALSE
;
1374 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1375 ("Port %d received a broadcast at a similar time.\n", i
))
1383 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1384 ("SK_RLMT_SELECT_BCRX found Port %d receiving the substantially "
1385 "latest broadcast (%u).\n",
1387 BcTimeStamp
- pAC
->Rlmt
.Port
[1 - *pSelect
].BcTimeStamp
))
1392 } /* SkRlmtSelectBcRx */
1395 /******************************************************************************
1397 * SkRlmtSelectNotSuspect - select new active port, criteria 2 (CLP)
1400 * This routine selects a good port (it is PortUp && !SuspectRx).
1403 * runtime, pageable?
1408 RLMT_STATIC SK_BOOL
SkRlmtSelectNotSuspect(
1409 SK_AC
*pAC
, /* Adapter Context */
1410 SK_IOC IoC
, /* I/O Context */
1411 SK_U32 Active
, /* Active port */
1412 SK_U32 PrefPort
, /* Preferred port */
1413 SK_U32
*pSelect
) /* New active port */
1418 PortFound
= SK_FALSE
;
1420 /* Select first port that is PortUp && !SuspectRx. */
1421 for (i
= 0; i
< (SK_U32
)pAC
->GIni
.GIMacsFound
; i
++) {
1422 if (!pAC
->Rlmt
.Port
[i
].PortDown
&&
1423 !(pAC
->Rlmt
.Port
[i
].CheckingState
& SK_RLMT_PCS_RX
)) {
1425 if (!pAC
->Rlmt
.Port
[Active
].PortDown
&&
1426 !(pAC
->Rlmt
.Port
[Active
].CheckingState
& SK_RLMT_PCS_RX
)) {
1429 if (!pAC
->Rlmt
.Port
[PrefPort
].PortDown
&&
1430 !(pAC
->Rlmt
.Port
[PrefPort
].CheckingState
& SK_RLMT_PCS_RX
)) {
1431 *pSelect
= PrefPort
;
1433 PortFound
= SK_TRUE
;
1434 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1435 ("SK_RLMT_SELECT_NOTSUSPECT found Port %d up and not check RX.\n",
1441 } /* SkRlmtSelectNotSuspect */
1444 /******************************************************************************
1446 * SkRlmtSelectUp - select new active port, criteria 3, 4 (CLP)
1449 * This routine selects a port that is up.
1452 * runtime, pageable?
1457 RLMT_STATIC SK_BOOL
SkRlmtSelectUp(
1458 SK_AC
*pAC
, /* Adapter Context */
1459 SK_IOC IoC
, /* I/O Context */
1460 SK_U32 Active
, /* Active port */
1461 SK_U32 PrefPort
, /* Preferred port */
1462 SK_U32
*pSelect
, /* New active port */
1463 SK_BOOL AutoNegDone
) /* Successfully auto-negotiated? */
1468 PortFound
= SK_FALSE
;
1470 /* Select first port that is PortUp. */
1471 for (i
= 0; i
< (SK_U32
)pAC
->GIni
.GIMacsFound
; i
++) {
1472 if (pAC
->Rlmt
.Port
[i
].PortState
== SK_RLMT_PS_UP
&&
1473 pAC
->GIni
.GP
[i
].PAutoNegFail
!= AutoNegDone
) {
1475 if (pAC
->Rlmt
.Port
[Active
].PortState
== SK_RLMT_PS_UP
&&
1476 pAC
->GIni
.GP
[Active
].PAutoNegFail
!= AutoNegDone
) {
1479 if (pAC
->Rlmt
.Port
[PrefPort
].PortState
== SK_RLMT_PS_UP
&&
1480 pAC
->GIni
.GP
[PrefPort
].PAutoNegFail
!= AutoNegDone
) {
1481 *pSelect
= PrefPort
;
1483 PortFound
= SK_TRUE
;
1484 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1485 ("SK_RLMT_SELECT_UP found Port %d up.\n", *pSelect
))
1490 } /* SkRlmtSelectUp */
1493 /******************************************************************************
1495 * SkRlmtSelectGoingUp - select new active port, criteria 5, 6 (CLP)
1498 * This routine selects the port that is going up for the longest time.
1501 * runtime, pageable?
1506 RLMT_STATIC SK_BOOL
SkRlmtSelectGoingUp(
1507 SK_AC
*pAC
, /* Adapter Context */
1508 SK_IOC IoC
, /* I/O Context */
1509 SK_U32 Active
, /* Active port */
1510 SK_U32 PrefPort
, /* Preferred port */
1511 SK_U32
*pSelect
, /* New active port */
1512 SK_BOOL AutoNegDone
) /* Successfully auto-negotiated? */
1519 PortFound
= SK_FALSE
;
1521 /* Select port that is PortGoingUp for the longest time. */
1522 for (i
= 0; i
< (SK_U32
)pAC
->GIni
.GIMacsFound
; i
++) {
1523 if (pAC
->Rlmt
.Port
[i
].PortState
== SK_RLMT_PS_GOING_UP
&&
1524 pAC
->GIni
.GP
[i
].PAutoNegFail
!= AutoNegDone
) {
1525 GuTimeStamp
= pAC
->Rlmt
.Port
[i
].GuTimeStamp
;
1527 PortFound
= SK_TRUE
;
1536 for (i
= *pSelect
+ 1; i
< (SK_U32
)pAC
->GIni
.GIMacsFound
; i
++) {
1537 if (pAC
->Rlmt
.Port
[i
].PortState
== SK_RLMT_PS_GOING_UP
&&
1538 pAC
->Rlmt
.Port
[i
].GuTimeStamp
< GuTimeStamp
&&
1539 pAC
->GIni
.GP
[i
].PAutoNegFail
!= AutoNegDone
) {
1540 GuTimeStamp
= pAC
->Rlmt
.Port
[i
].GuTimeStamp
;
1545 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1546 ("SK_RLMT_SELECT_GOINGUP found Port %d going up.\n", *pSelect
))
1548 } /* SkRlmtSelectGoingUp */
1551 /******************************************************************************
1553 * SkRlmtSelectDown - select new active port, criteria 7, 8 (CLP)
1556 * This routine selects a port that is down.
1559 * runtime, pageable?
1564 RLMT_STATIC SK_BOOL
SkRlmtSelectDown(
1565 SK_AC
*pAC
, /* Adapter Context */
1566 SK_IOC IoC
, /* I/O Context */
1567 SK_U32 Active
, /* Active port */
1568 SK_U32 PrefPort
, /* Preferred port */
1569 SK_U32
*pSelect
, /* New active port */
1570 SK_BOOL AutoNegDone
) /* Successfully auto-negotiated? */
1575 PortFound
= SK_FALSE
;
1577 /* Select first port that is PortDown. */
1578 for (i
= 0; i
< (SK_U32
)pAC
->GIni
.GIMacsFound
; i
++) {
1579 if (pAC
->Rlmt
.Port
[i
].PortState
== SK_RLMT_PS_DOWN
&&
1580 pAC
->GIni
.GP
[i
].PAutoNegFail
!= AutoNegDone
) {
1582 if (pAC
->Rlmt
.Port
[Active
].PortState
== SK_RLMT_PS_DOWN
&&
1583 pAC
->GIni
.GP
[Active
].PAutoNegFail
!= AutoNegDone
) {
1586 if (pAC
->Rlmt
.Port
[PrefPort
].PortState
== SK_RLMT_PS_DOWN
&&
1587 pAC
->GIni
.GP
[PrefPort
].PAutoNegFail
!= AutoNegDone
) {
1588 *pSelect
= PrefPort
;
1590 PortFound
= SK_TRUE
;
1591 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1592 ("SK_RLMT_SELECT_DOWN found Port %d down.\n", *pSelect
))
1597 } /* SkRlmtSelectDown */
1600 /******************************************************************************
1602 * SkRlmtCheckSwitch - select new active port and switch to it
1605 * This routine decides which port should be the active one and queues
1606 * port switching if necessary.
1609 * runtime, pageable?
1614 RLMT_STATIC
void SkRlmtCheckSwitch(
1615 SK_AC
*pAC
, /* Adapter Context */
1616 SK_IOC IoC
, /* I/O Context */
1617 SK_U32 NetIdx
) /* Net index */
1625 Active
= pAC
->Rlmt
.Net
[NetIdx
].ActivePort
; /* Index of active port. */
1626 PrefPort
= pAC
->Rlmt
.Net
[NetIdx
].PrefPort
; /* Index of preferred port. */
1627 PortFound
= SK_FALSE
;
1628 pAC
->Rlmt
.CheckSwitch
= SK_FALSE
;
1630 #if 0 /* RW 2001/10/18 - active port becomes always prefered one */
1631 if (pAC
->Rlmt
.Net
[NetIdx
].Preference
== 0xFFFFFFFF) { /* Automatic */
1632 /* disable auto-fail back */
1637 if (pAC
->Rlmt
.Net
[NetIdx
].LinksUp
== 0) {
1638 /* Last link went down - shut down the net. */
1639 pAC
->Rlmt
.Net
[NetIdx
].RlmtState
= SK_RLMT_RS_NET_DOWN
;
1640 Para
.Para32
[0] = SK_RLMT_NET_DOWN_TEMP
;
1641 Para
.Para32
[1] = NetIdx
;
1642 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_NET_DOWN
, Para
);
1644 Para
.Para32
[0] = pAC
->Rlmt
.Net
[NetIdx
].
1645 Port
[pAC
->Rlmt
.Net
[NetIdx
].ActivePort
]->PortNumber
;
1646 Para
.Para32
[1] = NetIdx
;
1647 SkEventQueue(pAC
, SKGE_PNMI
, SK_PNMI_EVT_RLMT_ACTIVE_DOWN
, Para
);
1649 } /* pAC->Rlmt.LinksUp == 0 */
1650 else if (pAC
->Rlmt
.Net
[NetIdx
].LinksUp
== 1 &&
1651 pAC
->Rlmt
.Net
[NetIdx
].RlmtState
== SK_RLMT_RS_NET_DOWN
) {
1652 /* First link came up - get the net up. */
1653 pAC
->Rlmt
.Net
[NetIdx
].RlmtState
= SK_RLMT_RS_NET_UP
;
1656 * If pAC->Rlmt.ActivePort != Para.Para32[0],
1657 * the DRV switches to the port that came up.
1659 for (i
= 0; i
< pAC
->Rlmt
.Net
[NetIdx
].NumPorts
; i
++) {
1660 if (!pAC
->Rlmt
.Net
[NetIdx
].Port
[i
]->LinkDown
) {
1661 if (!pAC
->Rlmt
.Net
[NetIdx
].Port
[Active
]->LinkDown
) {
1664 if (!pAC
->Rlmt
.Net
[NetIdx
].Port
[PrefPort
]->LinkDown
) {
1667 PortFound
= SK_TRUE
;
1673 Para
.Para32
[0] = pAC
->Rlmt
.Net
[NetIdx
].Port
[i
]->PortNumber
;
1674 Para
.Para32
[1] = NetIdx
;
1675 SkEventQueue(pAC
, SKGE_PNMI
, SK_PNMI_EVT_RLMT_ACTIVE_UP
, Para
);
1677 pAC
->Rlmt
.Net
[NetIdx
].ActivePort
= i
;
1678 Para
.Para32
[0] = pAC
->Rlmt
.Net
[NetIdx
].Port
[i
]->PortNumber
;
1679 Para
.Para32
[1] = NetIdx
;
1680 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_NET_UP
, Para
);
1682 if ((pAC
->Rlmt
.Net
[NetIdx
].RlmtMode
& SK_RLMT_TRANSPARENT
) == 0 &&
1683 (Para
.pParaPtr
= SkRlmtBuildPacket(pAC
, IoC
,
1684 pAC
->Rlmt
.Net
[NetIdx
].Port
[i
]->PortNumber
,
1685 SK_PACKET_ANNOUNCE
, &pAC
->Addr
.Net
[NetIdx
].
1686 CurrentMacAddress
, &SkRlmtMcAddr
)) != NULL
) {
1688 * Send announce packet to RLMT multicast address to force
1689 * switches to learn the new location of the logical MAC address.
1691 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_RLMT_SEND
, Para
);
1695 SK_ERR_LOG(pAC
, SK_ERRCL_SW
, SKERR_RLMT_E007
, SKERR_RLMT_E007_MSG
);
1699 } /* LinksUp == 1 && RlmtState == SK_RLMT_RS_NET_DOWN */
1700 else { /* Cannot be reached in dual-net mode. */
1701 Para
.Para32
[0] = Active
;
1705 * If RLMT Mode != CheckLinkState
1706 * select port that received a broadcast frame substantially later
1707 * than all other ports
1708 * else select first port that is not SuspectRx
1709 * else select first port that is PortUp
1710 * else select port that is PortGoingUp for the longest time
1711 * else select first port that is PortDown
1714 * For the preselected port:
1715 * If ActivePort is equal in quality, select ActivePort.
1717 * If PrefPort is equal in quality, select PrefPort.
1719 * If ActivePort != SelectedPort,
1720 * If old ActivePort is LinkDown,
1725 /* check of ChgBcPrio flag added */
1726 if ((pAC
->Rlmt
.Net
[0].RlmtMode
!= SK_RLMT_MODE_CLS
) &&
1727 (!pAC
->Rlmt
.Net
[0].ChgBcPrio
)) {
1730 PortFound
= SkRlmtSelectBcRx(
1731 pAC
, IoC
, Active
, PrefPort
, &Para
.Para32
[1]);
1735 PortFound
= SkRlmtSelectNotSuspect(
1736 pAC
, IoC
, Active
, PrefPort
, &Para
.Para32
[1]);
1738 } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
1740 /* with changed priority for last broadcast received */
1741 if ((pAC
->Rlmt
.Net
[0].RlmtMode
!= SK_RLMT_MODE_CLS
) &&
1742 (pAC
->Rlmt
.Net
[0].ChgBcPrio
)) {
1744 PortFound
= SkRlmtSelectNotSuspect(
1745 pAC
, IoC
, Active
, PrefPort
, &Para
.Para32
[1]);
1749 PortFound
= SkRlmtSelectBcRx(
1750 pAC
, IoC
, Active
, PrefPort
, &Para
.Para32
[1]);
1752 } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
1755 PortFound
= SkRlmtSelectUp(
1756 pAC
, IoC
, Active
, PrefPort
, &Para
.Para32
[1], AUTONEG_SUCCESS
);
1760 PortFound
= SkRlmtSelectUp(
1761 pAC
, IoC
, Active
, PrefPort
, &Para
.Para32
[1], AUTONEG_FAILED
);
1765 PortFound
= SkRlmtSelectGoingUp(
1766 pAC
, IoC
, Active
, PrefPort
, &Para
.Para32
[1], AUTONEG_SUCCESS
);
1770 PortFound
= SkRlmtSelectGoingUp(
1771 pAC
, IoC
, Active
, PrefPort
, &Para
.Para32
[1], AUTONEG_FAILED
);
1774 if (pAC
->Rlmt
.Net
[0].RlmtMode
!= SK_RLMT_MODE_CLS
) {
1776 PortFound
= SkRlmtSelectDown(pAC
, IoC
,
1777 Active
, PrefPort
, &Para
.Para32
[1], AUTONEG_SUCCESS
);
1781 PortFound
= SkRlmtSelectDown(pAC
, IoC
,
1782 Active
, PrefPort
, &Para
.Para32
[1], AUTONEG_FAILED
);
1784 } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
1788 if (Para
.Para32
[1] != Active
) {
1789 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1790 ("Active: %d, Para1: %d.\n", Active
, Para
.Para32
[1]))
1791 pAC
->Rlmt
.Net
[NetIdx
].ActivePort
= Para
.Para32
[1];
1792 Para
.Para32
[0] = pAC
->Rlmt
.Net
[NetIdx
].
1793 Port
[Para
.Para32
[0]]->PortNumber
;
1794 Para
.Para32
[1] = pAC
->Rlmt
.Net
[NetIdx
].
1795 Port
[Para
.Para32
[1]]->PortNumber
;
1796 SK_HWAC_LINK_LED(pAC
, IoC
, Para
.Para32
[1], SK_LED_ACTIVE
);
1797 if (pAC
->Rlmt
.Port
[Active
].LinkDown
) {
1798 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_SWITCH_HARD
, Para
);
1801 SK_HWAC_LINK_LED(pAC
, IoC
, Para
.Para32
[0], SK_LED_STANDBY
);
1802 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_SWITCH_SOFT
, Para
);
1804 Para
.Para32
[1] = NetIdx
;
1806 pAC
->Rlmt
.Net
[NetIdx
].Port
[Para
.Para32
[0]]->PortNumber
;
1807 SkEventQueue(pAC
, SKGE_PNMI
, SK_PNMI_EVT_RLMT_ACTIVE_DOWN
, Para
);
1808 Para
.Para32
[0] = pAC
->Rlmt
.Net
[NetIdx
].
1809 Port
[pAC
->Rlmt
.Net
[NetIdx
].ActivePort
]->PortNumber
;
1810 SkEventQueue(pAC
, SKGE_PNMI
, SK_PNMI_EVT_RLMT_ACTIVE_UP
, Para
);
1811 if ((pAC
->Rlmt
.Net
[NetIdx
].RlmtMode
& SK_RLMT_TRANSPARENT
) == 0 &&
1812 (Para
.pParaPtr
= SkRlmtBuildPacket(pAC
, IoC
, Para
.Para32
[0],
1813 SK_PACKET_ANNOUNCE
, &pAC
->Addr
.Net
[NetIdx
].CurrentMacAddress
,
1814 &SkRlmtMcAddr
)) != NULL
) {
1816 * Send announce packet to RLMT multicast address to force
1817 * switches to learn the new location of the logical
1820 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_RLMT_SEND
, Para
);
1821 } /* (Para.pParaPtr = SkRlmtBuildPacket(...)) != NULL */
1822 } /* Para.Para32[1] != Active */
1825 SK_ERR_LOG(pAC
, SK_ERRCL_SW
, SKERR_RLMT_E004
, SKERR_RLMT_E004_MSG
);
1827 } /* LinksUp > 1 || LinksUp == 1 && RlmtState != SK_RLMT_RS_NET_DOWN */
1829 } /* SkRlmtCheckSwitch */
1832 /******************************************************************************
1834 * SkRlmtCheckSeg - Report if segmentation is detected
1837 * This routine checks if the ports see different root bridges and reports
1838 * segmentation in such a case.
1841 * runtime, pageable?
1846 RLMT_STATIC
void SkRlmtCheckSeg(
1847 SK_AC
*pAC
, /* Adapter Context */
1848 SK_IOC IoC
, /* I/O Context */
1849 SK_U32 NetIdx
) /* Net number */
1856 pNet
= &pAC
->Rlmt
.Net
[NetIdx
];
1857 pNet
->RootIdSet
= SK_FALSE
;
1860 for (i
= 0; i
< pNet
->NumPorts
; i
++) {
1861 if (pNet
->Port
[i
]->LinkDown
|| !pNet
->Port
[i
]->RootIdSet
) {
1865 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_DUMP
,
1866 ("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n", i
,
1867 pNet
->Port
[i
]->Root
.Id
[0], pNet
->Port
[i
]->Root
.Id
[1],
1868 pNet
->Port
[i
]->Root
.Id
[2], pNet
->Port
[i
]->Root
.Id
[3],
1869 pNet
->Port
[i
]->Root
.Id
[4], pNet
->Port
[i
]->Root
.Id
[5],
1870 pNet
->Port
[i
]->Root
.Id
[6], pNet
->Port
[i
]->Root
.Id
[7]))
1872 if (!pNet
->RootIdSet
) {
1873 pNet
->Root
= pNet
->Port
[i
]->Root
;
1874 pNet
->RootIdSet
= SK_TRUE
;
1878 for (j
= 0; j
< 8; j
++) {
1879 Equal
&= pNet
->Port
[i
]->Root
.Id
[j
] == pNet
->Root
.Id
[j
];
1886 SK_ERR_LOG(pAC
, SK_ERRCL_COMM
, SKERR_RLMT_E005
, SKERR_RLMT_E005_MSG
);
1887 Para
.Para32
[0] = NetIdx
;
1888 Para
.Para32
[1] = (SK_U32
)-1;
1889 SkEventQueue(pAC
, SKGE_PNMI
, SK_PNMI_EVT_RLMT_SEGMENTATION
, Para
);
1891 pNet
->CheckingState
&= ~SK_RLMT_RCS_REPORT_SEG
;
1893 /* 2000-03-06 RA: New. */
1894 Para
.Para32
[0] = NetIdx
;
1895 Para
.Para32
[1] = (SK_U32
)-1;
1896 SkTimerStart(pAC
, IoC
, &pNet
->SegTimer
, SK_RLMT_SEG_TO_VAL
,
1897 SKGE_RLMT
, SK_RLMT_SEG_TIM
, Para
);
1900 } /* for (i = 0; i < pNet->NumPorts; i++) */
1902 /* 2000-03-06 RA: Moved here. */
1903 /* Segmentation check not running anymore. */
1904 pNet
->CheckingState
&= ~SK_RLMT_RCS_SEG
;
1906 } /* SkRlmtCheckSeg */
1909 /******************************************************************************
1911 * SkRlmtPortStart - initialize port variables and start port
1914 * This routine initializes a port's variables and issues a PORT_START
1915 * to the HWAC module. This handles retries if the start fails or the
1916 * link eventually goes down.
1919 * runtime, pageable?
1924 RLMT_STATIC
void SkRlmtPortStart(
1925 SK_AC
*pAC
, /* Adapter Context */
1926 SK_IOC IoC
, /* I/O Context */
1927 SK_U32 PortNumber
) /* Port number */
1931 pAC
->Rlmt
.Port
[PortNumber
].PortState
= SK_RLMT_PS_LINK_DOWN
;
1932 pAC
->Rlmt
.Port
[PortNumber
].PortStarted
= SK_TRUE
;
1933 pAC
->Rlmt
.Port
[PortNumber
].LinkDown
= SK_TRUE
;
1934 pAC
->Rlmt
.Port
[PortNumber
].PortDown
= SK_TRUE
;
1935 pAC
->Rlmt
.Port
[PortNumber
].CheckingState
= 0;
1936 pAC
->Rlmt
.Port
[PortNumber
].RootIdSet
= SK_FALSE
;
1937 Para
.Para32
[0] = PortNumber
;
1938 Para
.Para32
[1] = (SK_U32
)-1;
1939 SkEventQueue(pAC
, SKGE_HWAC
, SK_HWEV_PORT_START
, Para
);
1940 } /* SkRlmtPortStart */
1943 /******************************************************************************
1945 * SkRlmtEvtPortStartTim - PORT_START_TIM
1948 * This routine handles PORT_START_TIM events.
1951 * runtime, pageable?
1952 * may be called after SK_INIT_IO
1957 RLMT_STATIC
void SkRlmtEvtPortStartTim(
1958 SK_AC
*pAC
, /* Adapter Context */
1959 SK_IOC IoC
, /* I/O Context */
1960 SK_EVPARA Para
) /* SK_U32 PortNumber; SK_U32 -1 */
1964 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1965 ("SK_RLMT_PORTSTART_TIMEOUT Port %d Event BEGIN.\n", Para
.Para32
[0]))
1967 if (Para
.Para32
[1] != (SK_U32
)-1) {
1968 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1969 ("Bad Parameter.\n"))
1970 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1971 ("SK_RLMT_PORTSTART_TIMEOUT Event EMPTY.\n"))
1976 * Used to start non-preferred ports if the preferred one
1978 * This timeout needs only be set when starting the first
1981 if (pAC
->Rlmt
.Port
[Para
.Para32
[0]].LinkDown
) {
1982 /* PORT_START failed. */
1983 for (i
= 0; i
< pAC
->Rlmt
.Port
[Para
.Para32
[0]].Net
->NumPorts
; i
++) {
1984 if (!pAC
->Rlmt
.Port
[Para
.Para32
[0]].Net
->Port
[i
]->PortStarted
) {
1985 SkRlmtPortStart(pAC
, IoC
,
1986 pAC
->Rlmt
.Port
[Para
.Para32
[0]].Net
->Port
[i
]->PortNumber
);
1991 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
1992 ("SK_RLMT_PORTSTART_TIMEOUT Event END.\n"))
1993 } /* SkRlmtEvtPortStartTim */
1996 /******************************************************************************
1998 * SkRlmtEvtLinkUp - LINK_UP
2001 * This routine handles LLINK_UP events.
2004 * runtime, pageable?
2005 * may be called after SK_INIT_IO
2010 RLMT_STATIC
void SkRlmtEvtLinkUp(
2011 SK_AC
*pAC
, /* Adapter Context */
2012 SK_IOC IoC
, /* I/O Context */
2013 SK_EVPARA Para
) /* SK_U32 PortNumber; SK_U32 Undefined */
2016 SK_RLMT_PORT
*pRPort
;
2019 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2020 ("SK_RLMT_LINK_UP Port %d Event BEGIN.\n", Para
.Para32
[0]))
2022 pRPort
= &pAC
->Rlmt
.Port
[Para
.Para32
[0]];
2023 if (!pRPort
->PortStarted
) {
2024 SK_ERR_LOG(pAC
, SK_ERRCL_SW
, SKERR_RLMT_E008
, SKERR_RLMT_E008_MSG
);
2026 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2027 ("SK_RLMT_LINK_UP Event EMPTY.\n"))
2031 if (!pRPort
->LinkDown
) {
2032 /* RA;:;: Any better solution? */
2033 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2034 ("SK_RLMT_LINK_UP Event EMPTY.\n"))
2038 SkTimerStop(pAC
, IoC
, &pRPort
->UpTimer
);
2039 SkTimerStop(pAC
, IoC
, &pRPort
->DownRxTimer
);
2040 SkTimerStop(pAC
, IoC
, &pRPort
->DownTxTimer
);
2042 /* Do something if timer already fired? */
2044 pRPort
->LinkDown
= SK_FALSE
;
2045 pRPort
->PortState
= SK_RLMT_PS_GOING_UP
;
2046 pRPort
->GuTimeStamp
= SkOsGetTime(pAC
);
2047 pRPort
->BcTimeStamp
= 0;
2048 pRPort
->Net
->LinksUp
++;
2049 if (pRPort
->Net
->LinksUp
== 1) {
2050 SK_HWAC_LINK_LED(pAC
, IoC
, Para
.Para32
[0], SK_LED_ACTIVE
);
2053 SK_HWAC_LINK_LED(pAC
, IoC
, Para
.Para32
[0], SK_LED_STANDBY
);
2056 for (i
= 0; i
< pRPort
->Net
->NumPorts
; i
++) {
2057 if (!pRPort
->Net
->Port
[i
]->PortStarted
) {
2058 SkRlmtPortStart(pAC
, IoC
, pRPort
->Net
->Port
[i
]->PortNumber
);
2062 SkRlmtCheckSwitch(pAC
, IoC
, pRPort
->Net
->NetNumber
);
2064 if (pRPort
->Net
->LinksUp
>= 2) {
2065 if (pRPort
->Net
->RlmtMode
& SK_RLMT_CHECK_LOC_LINK
) {
2066 /* Build the check chain. */
2067 SkRlmtBuildCheckChain(pAC
, pRPort
->Net
->NetNumber
);
2071 /* If the first link comes up, start the periodical RLMT timeout. */
2072 if (pRPort
->Net
->NumPorts
> 1 && pRPort
->Net
->LinksUp
== 1 &&
2073 (pRPort
->Net
->RlmtMode
& SK_RLMT_CHECK_OTHERS
) != 0) {
2074 Para2
.Para32
[0] = pRPort
->Net
->NetNumber
;
2075 Para2
.Para32
[1] = (SK_U32
)-1;
2076 SkTimerStart(pAC
, IoC
, &pRPort
->Net
->LocTimer
,
2077 pRPort
->Net
->TimeoutValue
, SKGE_RLMT
, SK_RLMT_TIM
, Para2
);
2081 Para2
.Para32
[1] = (SK_U32
)-1;
2082 SkTimerStart(pAC
, IoC
, &pRPort
->UpTimer
, SK_RLMT_PORTUP_TIM_VAL
,
2083 SKGE_RLMT
, SK_RLMT_PORTUP_TIM
, Para2
);
2085 /* Later: if (pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_LOC_LINK) && */
2086 if ((pRPort
->Net
->RlmtMode
& SK_RLMT_TRANSPARENT
) == 0 &&
2087 (pRPort
->Net
->RlmtMode
& SK_RLMT_CHECK_LINK
) != 0 &&
2089 SkRlmtBuildPacket(pAC
, IoC
, Para
.Para32
[0], SK_PACKET_ANNOUNCE
,
2090 &pAC
->Addr
.Port
[Para
.Para32
[0]].CurrentMacAddress
, &SkRlmtMcAddr
)
2092 /* Send "new" packet to RLMT multicast address. */
2093 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_RLMT_SEND
, Para2
);
2096 if (pRPort
->Net
->RlmtMode
& SK_RLMT_CHECK_SEG
) {
2097 if ((Para2
.pParaPtr
=
2098 SkRlmtBuildSpanningTreePacket(pAC
, IoC
, Para
.Para32
[0])) != NULL
) {
2099 pAC
->Rlmt
.Port
[Para
.Para32
[0]].RootIdSet
= SK_FALSE
;
2100 pRPort
->Net
->CheckingState
|=
2101 SK_RLMT_RCS_SEG
| SK_RLMT_RCS_REPORT_SEG
;
2103 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_RLMT_SEND
, Para2
);
2105 Para
.Para32
[1] = (SK_U32
)-1;
2106 SkTimerStart(pAC
, IoC
, &pRPort
->Net
->SegTimer
,
2107 SK_RLMT_SEG_TO_VAL
, SKGE_RLMT
, SK_RLMT_SEG_TIM
, Para
);
2111 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2112 ("SK_RLMT_LINK_UP Event END.\n"))
2113 } /* SkRlmtEvtLinkUp */
2116 /******************************************************************************
2118 * SkRlmtEvtPortUpTim - PORT_UP_TIM
2121 * This routine handles PORT_UP_TIM events.
2124 * runtime, pageable?
2125 * may be called after SK_INIT_IO
2130 RLMT_STATIC
void SkRlmtEvtPortUpTim(
2131 SK_AC
*pAC
, /* Adapter Context */
2132 SK_IOC IoC
, /* I/O Context */
2133 SK_EVPARA Para
) /* SK_U32 PortNumber; SK_U32 -1 */
2135 SK_RLMT_PORT
*pRPort
;
2137 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2138 ("SK_RLMT_PORTUP_TIM Port %d Event BEGIN.\n", Para
.Para32
[0]))
2140 if (Para
.Para32
[1] != (SK_U32
)-1) {
2141 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2142 ("Bad Parameter.\n"))
2143 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2144 ("SK_RLMT_PORTUP_TIM Event EMPTY.\n"))
2148 pRPort
= &pAC
->Rlmt
.Port
[Para
.Para32
[0]];
2149 if (pRPort
->LinkDown
|| (pRPort
->PortState
== SK_RLMT_PS_UP
)) {
2150 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2151 ("SK_RLMT_PORTUP_TIM Port %d Event EMPTY.\n", Para
.Para32
[0]))
2155 pRPort
->PortDown
= SK_FALSE
;
2156 pRPort
->PortState
= SK_RLMT_PS_UP
;
2157 pRPort
->Net
->PortsUp
++;
2158 if (pRPort
->Net
->RlmtState
!= SK_RLMT_RS_INIT
) {
2159 if (pAC
->Rlmt
.NumNets
<= 1) {
2160 SkRlmtCheckSwitch(pAC
, IoC
, pRPort
->Net
->NetNumber
);
2162 SkEventQueue(pAC
, SKGE_PNMI
, SK_PNMI_EVT_RLMT_PORT_UP
, Para
);
2165 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2166 ("SK_RLMT_PORTUP_TIM Event END.\n"))
2167 } /* SkRlmtEvtPortUpTim */
2170 /******************************************************************************
2172 * SkRlmtEvtPortDownTim - PORT_DOWN_*
2175 * This routine handles PORT_DOWN_* events.
2178 * runtime, pageable?
2179 * may be called after SK_INIT_IO
2184 RLMT_STATIC
void SkRlmtEvtPortDownX(
2185 SK_AC
*pAC
, /* Adapter Context */
2186 SK_IOC IoC
, /* I/O Context */
2187 SK_U32 Event
, /* Event code */
2188 SK_EVPARA Para
) /* SK_U32 PortNumber; SK_U32 -1 */
2190 SK_RLMT_PORT
*pRPort
;
2192 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2193 ("SK_RLMT_PORTDOWN* Port %d Event (%d) BEGIN.\n",
2194 Para
.Para32
[0], Event
))
2196 if (Para
.Para32
[1] != (SK_U32
)-1) {
2197 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2198 ("Bad Parameter.\n"))
2199 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2200 ("SK_RLMT_PORTDOWN* Event EMPTY.\n"))
2204 pRPort
= &pAC
->Rlmt
.Port
[Para
.Para32
[0]];
2205 if (!pRPort
->PortStarted
|| (Event
== SK_RLMT_PORTDOWN_TX_TIM
&&
2206 !(pRPort
->CheckingState
& SK_RLMT_PCS_TX
))) {
2207 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2208 ("SK_RLMT_PORTDOWN* Event (%d) EMPTY.\n", Event
))
2212 /* Stop port's timers. */
2213 SkTimerStop(pAC
, IoC
, &pRPort
->UpTimer
);
2214 SkTimerStop(pAC
, IoC
, &pRPort
->DownRxTimer
);
2215 SkTimerStop(pAC
, IoC
, &pRPort
->DownTxTimer
);
2217 if (pRPort
->PortState
!= SK_RLMT_PS_LINK_DOWN
) {
2218 pRPort
->PortState
= SK_RLMT_PS_DOWN
;
2221 if (!pRPort
->PortDown
) {
2222 pRPort
->Net
->PortsUp
--;
2223 pRPort
->PortDown
= SK_TRUE
;
2224 SkEventQueue(pAC
, SKGE_PNMI
, SK_PNMI_EVT_RLMT_PORT_DOWN
, Para
);
2227 pRPort
->PacketsPerTimeSlot
= 0;
2228 /* pRPort->DataPacketsPerTimeSlot = 0; */
2229 pRPort
->BpduPacketsPerTimeSlot
= 0;
2230 pRPort
->BcTimeStamp
= 0;
2233 * RA;:;: To be checked:
2234 * - actions at RLMT_STOP: We should not switch anymore.
2236 if (pRPort
->Net
->RlmtState
!= SK_RLMT_RS_INIT
) {
2237 if (Para
.Para32
[0] ==
2238 pRPort
->Net
->Port
[pRPort
->Net
->ActivePort
]->PortNumber
) {
2239 /* Active Port went down. */
2240 SkRlmtCheckSwitch(pAC
, IoC
, pRPort
->Net
->NetNumber
);
2244 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2245 ("SK_RLMT_PORTDOWN* Event (%d) END.\n", Event
))
2246 } /* SkRlmtEvtPortDownX */
2249 /******************************************************************************
2251 * SkRlmtEvtLinkDown - LINK_DOWN
2254 * This routine handles LINK_DOWN events.
2257 * runtime, pageable?
2258 * may be called after SK_INIT_IO
2263 RLMT_STATIC
void SkRlmtEvtLinkDown(
2264 SK_AC
*pAC
, /* Adapter Context */
2265 SK_IOC IoC
, /* I/O Context */
2266 SK_EVPARA Para
) /* SK_U32 PortNumber; SK_U32 Undefined */
2268 SK_RLMT_PORT
*pRPort
;
2270 pRPort
= &pAC
->Rlmt
.Port
[Para
.Para32
[0]];
2271 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2272 ("SK_RLMT_LINK_DOWN Port %d Event BEGIN.\n", Para
.Para32
[0]))
2274 if (!pAC
->Rlmt
.Port
[Para
.Para32
[0]].LinkDown
) {
2275 pRPort
->Net
->LinksUp
--;
2276 pRPort
->LinkDown
= SK_TRUE
;
2277 pRPort
->PortState
= SK_RLMT_PS_LINK_DOWN
;
2278 SK_HWAC_LINK_LED(pAC
, IoC
, Para
.Para32
[0], SK_LED_OFF
);
2280 if ((pRPort
->Net
->RlmtMode
& SK_RLMT_CHECK_LOC_LINK
) != 0) {
2281 /* Build the check chain. */
2282 SkRlmtBuildCheckChain(pAC
, pRPort
->Net
->NetNumber
);
2285 /* Ensure that port is marked down. */
2286 Para
.Para32
[1] = -1;
2287 (void)SkRlmtEvent(pAC
, IoC
, SK_RLMT_PORTDOWN
, Para
);
2290 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2291 ("SK_RLMT_LINK_DOWN Event END.\n"))
2292 } /* SkRlmtEvtLinkDown */
2295 /******************************************************************************
2297 * SkRlmtEvtPortAddr - PORT_ADDR
2300 * This routine handles PORT_ADDR events.
2303 * runtime, pageable?
2304 * may be called after SK_INIT_IO
2309 RLMT_STATIC
void SkRlmtEvtPortAddr(
2310 SK_AC
*pAC
, /* Adapter Context */
2311 SK_IOC IoC
, /* I/O Context */
2312 SK_EVPARA Para
) /* SK_U32 PortNumber; SK_U32 -1 */
2315 SK_RLMT_PORT
*pRPort
;
2316 SK_MAC_ADDR
*pOldMacAddr
;
2317 SK_MAC_ADDR
*pNewMacAddr
;
2319 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2320 ("SK_RLMT_PORT_ADDR Port %d Event BEGIN.\n", Para
.Para32
[0]))
2322 if (Para
.Para32
[1] != (SK_U32
)-1) {
2323 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2324 ("Bad Parameter.\n"))
2325 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2326 ("SK_RLMT_PORT_ADDR Event EMPTY.\n"))
2330 /* Port's physical MAC address changed. */
2331 pOldMacAddr
= &pAC
->Addr
.Port
[Para
.Para32
[0]].PreviousMacAddress
;
2332 pNewMacAddr
= &pAC
->Addr
.Port
[Para
.Para32
[0]].CurrentMacAddress
;
2335 * NOTE: This is not scalable for solutions where ports are
2336 * checked remotely. There, we need to send an RLMT
2337 * address change packet - and how do we ensure delivery?
2339 for (i
= 0; i
< (SK_U32
)pAC
->GIni
.GIMacsFound
; i
++) {
2340 pRPort
= &pAC
->Rlmt
.Port
[i
];
2341 for (j
= 0; j
< pRPort
->PortsChecked
; j
++) {
2343 pRPort
->PortCheck
[j
].CheckAddr
.a
, pOldMacAddr
->a
)) {
2344 pRPort
->PortCheck
[j
].CheckAddr
= *pNewMacAddr
;
2349 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2350 ("SK_RLMT_PORT_ADDR Event END.\n"))
2351 } /* SkRlmtEvtPortAddr */
2354 /******************************************************************************
2356 * SkRlmtEvtStart - START
2359 * This routine handles START events.
2362 * runtime, pageable?
2363 * may be called after SK_INIT_IO
2368 RLMT_STATIC
void SkRlmtEvtStart(
2369 SK_AC
*pAC
, /* Adapter Context */
2370 SK_IOC IoC
, /* I/O Context */
2371 SK_EVPARA Para
) /* SK_U32 NetNumber; SK_U32 -1 */
2377 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2378 ("SK_RLMT_START Net %d Event BEGIN.\n", Para
.Para32
[0]))
2380 if (Para
.Para32
[1] != (SK_U32
)-1) {
2381 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2382 ("Bad Parameter.\n"))
2383 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2384 ("SK_RLMT_START Event EMPTY.\n"))
2388 if (Para
.Para32
[0] >= pAC
->Rlmt
.NumNets
) {
2389 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2390 ("Bad NetNumber %d.\n", Para
.Para32
[0]))
2391 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2392 ("SK_RLMT_START Event EMPTY.\n"))
2396 if (pAC
->Rlmt
.Net
[Para
.Para32
[0]].RlmtState
!= SK_RLMT_RS_INIT
) {
2397 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2398 ("SK_RLMT_START Event EMPTY.\n"))
2402 if (pAC
->Rlmt
.NetsStarted
>= pAC
->Rlmt
.NumNets
) {
2403 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2404 ("All nets should have been started.\n"))
2405 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2406 ("SK_RLMT_START Event EMPTY.\n"))
2410 if (pAC
->Rlmt
.Net
[Para
.Para32
[0]].PrefPort
>=
2411 pAC
->Rlmt
.Net
[Para
.Para32
[0]].NumPorts
) {
2412 SK_ERR_LOG(pAC
, SK_ERRCL_SW
, SKERR_RLMT_E009
, SKERR_RLMT_E009_MSG
);
2414 /* Change PrefPort to internal default. */
2415 Para2
.Para32
[0] = 0xFFFFFFFF;
2416 Para2
.Para32
[1] = Para
.Para32
[0];
2417 (void)SkRlmtEvent(pAC
, IoC
, SK_RLMT_PREFPORT_CHANGE
, Para2
);
2420 PortIdx
= pAC
->Rlmt
.Net
[Para
.Para32
[0]].PrefPort
;
2421 PortNumber
= pAC
->Rlmt
.Net
[Para
.Para32
[0]].Port
[PortIdx
]->PortNumber
;
2423 pAC
->Rlmt
.Net
[Para
.Para32
[0]].LinksUp
= 0;
2424 pAC
->Rlmt
.Net
[Para
.Para32
[0]].PortsUp
= 0;
2425 pAC
->Rlmt
.Net
[Para
.Para32
[0]].CheckingState
= 0;
2426 pAC
->Rlmt
.Net
[Para
.Para32
[0]].RlmtState
= SK_RLMT_RS_NET_DOWN
;
2428 /* Start preferred port. */
2429 SkRlmtPortStart(pAC
, IoC
, PortNumber
);
2431 /* Start Timer (for first port only). */
2432 Para2
.Para32
[0] = PortNumber
;
2433 Para2
.Para32
[1] = (SK_U32
)-1;
2434 SkTimerStart(pAC
, IoC
, &pAC
->Rlmt
.Port
[PortNumber
].UpTimer
,
2435 SK_RLMT_PORTSTART_TIM_VAL
, SKGE_RLMT
, SK_RLMT_PORTSTART_TIM
, Para2
);
2437 pAC
->Rlmt
.NetsStarted
++;
2439 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2440 ("SK_RLMT_START Event END.\n"))
2441 } /* SkRlmtEvtStart */
2444 /******************************************************************************
2446 * SkRlmtEvtStop - STOP
2449 * This routine handles STOP events.
2452 * runtime, pageable?
2453 * may be called after SK_INIT_IO
2458 RLMT_STATIC
void SkRlmtEvtStop(
2459 SK_AC
*pAC
, /* Adapter Context */
2460 SK_IOC IoC
, /* I/O Context */
2461 SK_EVPARA Para
) /* SK_U32 NetNumber; SK_U32 -1 */
2467 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2468 ("SK_RLMT_STOP Net %d Event BEGIN.\n", Para
.Para32
[0]))
2470 if (Para
.Para32
[1] != (SK_U32
)-1) {
2471 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2472 ("Bad Parameter.\n"))
2473 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2474 ("SK_RLMT_STOP Event EMPTY.\n"))
2478 if (Para
.Para32
[0] >= pAC
->Rlmt
.NumNets
) {
2479 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2480 ("Bad NetNumber %d.\n", Para
.Para32
[0]))
2481 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2482 ("SK_RLMT_STOP Event EMPTY.\n"))
2486 if (pAC
->Rlmt
.Net
[Para
.Para32
[0]].RlmtState
== SK_RLMT_RS_INIT
) {
2487 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2488 ("SK_RLMT_STOP Event EMPTY.\n"))
2492 if (pAC
->Rlmt
.NetsStarted
== 0) {
2493 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2494 ("All nets are stopped.\n"))
2495 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2496 ("SK_RLMT_STOP Event EMPTY.\n"))
2500 /* Stop RLMT timers. */
2501 SkTimerStop(pAC
, IoC
, &pAC
->Rlmt
.Net
[Para
.Para32
[0]].LocTimer
);
2502 SkTimerStop(pAC
, IoC
, &pAC
->Rlmt
.Net
[Para
.Para32
[0]].SegTimer
);
2505 pAC
->Rlmt
.Net
[Para
.Para32
[0]].RlmtState
= SK_RLMT_RS_INIT
;
2506 pAC
->Rlmt
.Net
[Para
.Para32
[0]].RootIdSet
= SK_FALSE
;
2507 Para2
.Para32
[0] = SK_RLMT_NET_DOWN_FINAL
;
2508 Para2
.Para32
[1] = Para
.Para32
[0]; /* Net# */
2509 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_NET_DOWN
, Para2
);
2512 for (i
= 0; i
< pAC
->Rlmt
.Net
[Para
.Para32
[0]].NumPorts
; i
++) {
2513 PortNumber
= pAC
->Rlmt
.Net
[Para
.Para32
[0]].Port
[i
]->PortNumber
;
2514 if (pAC
->Rlmt
.Port
[PortNumber
].PortState
!= SK_RLMT_PS_INIT
) {
2515 SkTimerStop(pAC
, IoC
, &pAC
->Rlmt
.Port
[PortNumber
].UpTimer
);
2516 SkTimerStop(pAC
, IoC
, &pAC
->Rlmt
.Port
[PortNumber
].DownRxTimer
);
2517 SkTimerStop(pAC
, IoC
, &pAC
->Rlmt
.Port
[PortNumber
].DownTxTimer
);
2519 pAC
->Rlmt
.Port
[PortNumber
].PortState
= SK_RLMT_PS_INIT
;
2520 pAC
->Rlmt
.Port
[PortNumber
].RootIdSet
= SK_FALSE
;
2521 pAC
->Rlmt
.Port
[PortNumber
].PortStarted
= SK_FALSE
;
2522 Para2
.Para32
[0] = PortNumber
;
2523 Para2
.Para32
[1] = (SK_U32
)-1;
2524 SkEventQueue(pAC
, SKGE_HWAC
, SK_HWEV_PORT_STOP
, Para2
);
2528 pAC
->Rlmt
.NetsStarted
--;
2530 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2531 ("SK_RLMT_STOP Event END.\n"))
2532 } /* SkRlmtEvtStop */
2535 /******************************************************************************
2537 * SkRlmtEvtTim - TIM
2540 * This routine handles TIM events.
2543 * runtime, pageable?
2544 * may be called after SK_INIT_IO
2549 RLMT_STATIC
void SkRlmtEvtTim(
2550 SK_AC
*pAC
, /* Adapter Context */
2551 SK_IOC IoC
, /* I/O Context */
2552 SK_EVPARA Para
) /* SK_U32 NetNumber; SK_U32 -1 */
2554 SK_RLMT_PORT
*pRPort
;
2560 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2561 ("SK_RLMT_TIM Event BEGIN.\n"))
2563 if (Para
.Para32
[1] != (SK_U32
)-1) {
2564 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2565 ("Bad Parameter.\n"))
2566 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2567 ("SK_RLMT_TIM Event EMPTY.\n"))
2571 if ((pAC
->Rlmt
.Net
[Para
.Para32
[0]].RlmtMode
& SK_RLMT_CHECK_OTHERS
) == 0 ||
2572 pAC
->Rlmt
.Net
[Para
.Para32
[0]].LinksUp
== 0) {
2573 /* Mode changed or all links down: No more link checking. */
2578 pAC
->Rlmt
.SwitchCheckCounter
--;
2579 if (pAC
->Rlmt
.SwitchCheckCounter
== 0) {
2580 pAC
->Rlmt
.SwitchCheckCounter
;
2584 NewTimeout
= SK_RLMT_DEF_TO_VAL
;
2585 for (i
= 0; i
< pAC
->Rlmt
.Net
[Para
.Para32
[0]].NumPorts
; i
++) {
2586 PortNumber
= pAC
->Rlmt
.Net
[Para
.Para32
[0]].Port
[i
]->PortNumber
;
2587 pRPort
= &pAC
->Rlmt
.Port
[PortNumber
];
2588 if (!pRPort
->LinkDown
) {
2589 Timeout
= SkRlmtCheckPort(pAC
, IoC
, PortNumber
);
2590 if (Timeout
< NewTimeout
) {
2591 NewTimeout
= Timeout
;
2595 * These counters should be set to 0 for all ports before the
2596 * first frame is sent in the next loop.
2598 pRPort
->PacketsPerTimeSlot
= 0;
2599 /* pRPort->DataPacketsPerTimeSlot = 0; */
2600 pRPort
->BpduPacketsPerTimeSlot
= 0;
2603 pAC
->Rlmt
.Net
[Para
.Para32
[0]].TimeoutValue
= NewTimeout
;
2605 if (pAC
->Rlmt
.Net
[Para
.Para32
[0]].LinksUp
> 1) {
2607 * If checking remote ports, also send packets if
2609 * this port checks at least one (remote) port.
2613 * Must be new loop, as SkRlmtCheckPort can request to
2614 * check segmentation when e.g. checking the last port.
2616 for (i
= 0; i
< pAC
->Rlmt
.Net
[Para
.Para32
[0]].NumPorts
; i
++) {
2617 if (!pAC
->Rlmt
.Net
[Para
.Para32
[0]].Port
[i
]->LinkDown
) {
2618 SkRlmtSend(pAC
, IoC
,
2619 pAC
->Rlmt
.Net
[Para
.Para32
[0]].Port
[i
]->PortNumber
);
2624 SkTimerStart(pAC
, IoC
, &pAC
->Rlmt
.Net
[Para
.Para32
[0]].LocTimer
,
2625 pAC
->Rlmt
.Net
[Para
.Para32
[0]].TimeoutValue
, SKGE_RLMT
, SK_RLMT_TIM
,
2628 if (pAC
->Rlmt
.Net
[Para
.Para32
[0]].LinksUp
> 1 &&
2629 (pAC
->Rlmt
.Net
[Para
.Para32
[0]].RlmtMode
& SK_RLMT_CHECK_SEG
) &&
2630 (pAC
->Rlmt
.Net
[Para
.Para32
[0]].CheckingState
& SK_RLMT_RCS_START_SEG
)) {
2631 SkTimerStart(pAC
, IoC
, &pAC
->Rlmt
.Net
[Para
.Para32
[0]].SegTimer
,
2632 SK_RLMT_SEG_TO_VAL
, SKGE_RLMT
, SK_RLMT_SEG_TIM
, Para
);
2633 pAC
->Rlmt
.Net
[Para
.Para32
[0]].CheckingState
&= ~SK_RLMT_RCS_START_SEG
;
2634 pAC
->Rlmt
.Net
[Para
.Para32
[0]].CheckingState
|=
2635 SK_RLMT_RCS_SEG
| SK_RLMT_RCS_REPORT_SEG
;
2638 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2639 ("SK_RLMT_TIM Event END.\n"))
2640 } /* SkRlmtEvtTim */
2643 /******************************************************************************
2645 * SkRlmtEvtSegTim - SEG_TIM
2648 * This routine handles SEG_TIM events.
2651 * runtime, pageable?
2652 * may be called after SK_INIT_IO
2657 RLMT_STATIC
void SkRlmtEvtSegTim(
2658 SK_AC
*pAC
, /* Adapter Context */
2659 SK_IOC IoC
, /* I/O Context */
2660 SK_EVPARA Para
) /* SK_U32 NetNumber; SK_U32 -1 */
2666 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2667 ("SK_RLMT_SEG_TIM Event BEGIN.\n"))
2669 if (Para
.Para32
[1] != (SK_U32
)-1) {
2670 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2671 ("Bad Parameter.\n"))
2672 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2673 ("SK_RLMT_SEG_TIM Event EMPTY.\n"))
2678 for (j
= 0; j
< pAC
->Rlmt
.Net
[Para
.Para32
[0]].NumPorts
; j
++) {
2679 SK_ADDR_PORT
*pAPort
;
2684 InAddr
= (SK_U16
*)&InAddr8
[0];
2685 pAPort
= pAC
->Rlmt
.Net
[Para
.Para32
[0]].Port
[j
]->AddrPort
;
2686 for (k
= 0; k
< pAPort
->NextExactMatchRlmt
; k
++) {
2687 /* Get exact match address k from port j. */
2688 XM_INADDR(IoC
, pAC
->Rlmt
.Net
[Para
.Para32
[0]].Port
[j
]->PortNumber
,
2690 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2691 ("MC address %d on Port %u: %02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x.\n",
2692 k
, pAC
->Rlmt
.Net
[Para
.Para32
[0]].Port
[j
]->PortNumber
,
2693 InAddr8
[0], InAddr8
[1], InAddr8
[2],
2694 InAddr8
[3], InAddr8
[4], InAddr8
[5],
2695 pAPort
->Exact
[k
].a
[0], pAPort
->Exact
[k
].a
[1],
2696 pAPort
->Exact
[k
].a
[2], pAPort
->Exact
[k
].a
[3],
2697 pAPort
->Exact
[k
].a
[4], pAPort
->Exact
[k
].a
[5]))
2702 SkRlmtCheckSeg(pAC
, IoC
, Para
.Para32
[0]);
2704 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2705 ("SK_RLMT_SEG_TIM Event END.\n"))
2706 } /* SkRlmtEvtSegTim */
2709 /******************************************************************************
2711 * SkRlmtEvtPacketRx - PACKET_RECEIVED
2714 * This routine handles PACKET_RECEIVED events.
2717 * runtime, pageable?
2718 * may be called after SK_INIT_IO
2723 RLMT_STATIC
void SkRlmtEvtPacketRx(
2724 SK_AC
*pAC
, /* Adapter Context */
2725 SK_IOC IoC
, /* I/O Context */
2726 SK_EVPARA Para
) /* SK_MBUF *pMb */
2733 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2734 ("SK_RLMT_PACKET_RECEIVED Event BEGIN.\n"))
2736 /* Should we ignore frames during port switching? */
2739 pMb
= Para
.pParaPtr
;
2741 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
, ("No mbuf.\n"))
2743 else if (pMb
->pNext
!= NULL
) {
2744 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2745 ("More than one mbuf or pMb->pNext not set.\n"))
2749 for (pMb
= Para
.pParaPtr
; pMb
!= NULL
; pMb
= pNextMb
) {
2750 pNextMb
= pMb
->pNext
;
2753 NetNumber
= pAC
->Rlmt
.Port
[pMb
->PortIdx
].Net
->NetNumber
;
2754 if (pAC
->Rlmt
.Net
[NetNumber
].RlmtState
== SK_RLMT_RS_INIT
) {
2755 SkDrvFreeRlmtMbuf(pAC
, IoC
, pMb
);
2758 SkRlmtPacketReceive(pAC
, IoC
, pMb
);
2762 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2763 ("SK_RLMT_PACKET_RECEIVED Event END.\n"))
2764 } /* SkRlmtEvtPacketRx */
2767 /******************************************************************************
2769 * SkRlmtEvtStatsClear - STATS_CLEAR
2772 * This routine handles STATS_CLEAR events.
2775 * runtime, pageable?
2776 * may be called after SK_INIT_IO
2781 RLMT_STATIC
void SkRlmtEvtStatsClear(
2782 SK_AC
*pAC
, /* Adapter Context */
2783 SK_IOC IoC
, /* I/O Context */
2784 SK_EVPARA Para
) /* SK_U32 NetNumber; SK_U32 -1 */
2787 SK_RLMT_PORT
*pRPort
;
2789 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2790 ("SK_RLMT_STATS_CLEAR Event BEGIN.\n"))
2792 if (Para
.Para32
[1] != (SK_U32
)-1) {
2793 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2794 ("Bad Parameter.\n"))
2795 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2796 ("SK_RLMT_STATS_CLEAR Event EMPTY.\n"))
2800 if (Para
.Para32
[0] >= pAC
->Rlmt
.NumNets
) {
2801 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2802 ("Bad NetNumber %d.\n", Para
.Para32
[0]))
2803 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2804 ("SK_RLMT_STATS_CLEAR Event EMPTY.\n"))
2808 /* Clear statistics for logical and physical ports. */
2809 for (i
= 0; i
< pAC
->Rlmt
.Net
[Para
.Para32
[0]].NumPorts
; i
++) {
2811 &pAC
->Rlmt
.Port
[pAC
->Rlmt
.Net
[Para
.Para32
[0]].Port
[i
]->PortNumber
];
2812 pRPort
->TxHelloCts
= 0;
2813 pRPort
->RxHelloCts
= 0;
2814 pRPort
->TxSpHelloReqCts
= 0;
2815 pRPort
->RxSpHelloCts
= 0;
2818 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2819 ("SK_RLMT_STATS_CLEAR Event END.\n"))
2820 } /* SkRlmtEvtStatsClear */
2823 /******************************************************************************
2825 * SkRlmtEvtStatsUpdate - STATS_UPDATE
2828 * This routine handles STATS_UPDATE events.
2831 * runtime, pageable?
2832 * may be called after SK_INIT_IO
2837 RLMT_STATIC
void SkRlmtEvtStatsUpdate(
2838 SK_AC
*pAC
, /* Adapter Context */
2839 SK_IOC IoC
, /* I/O Context */
2840 SK_EVPARA Para
) /* SK_U32 NetNumber; SK_U32 -1 */
2842 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2843 ("SK_RLMT_STATS_UPDATE Event BEGIN.\n"))
2845 if (Para
.Para32
[1] != (SK_U32
)-1) {
2846 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2847 ("Bad Parameter.\n"))
2848 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2849 ("SK_RLMT_STATS_UPDATE Event EMPTY.\n"))
2853 if (Para
.Para32
[0] >= pAC
->Rlmt
.NumNets
) {
2854 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2855 ("Bad NetNumber %d.\n", Para
.Para32
[0]))
2856 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2857 ("SK_RLMT_STATS_UPDATE Event EMPTY.\n"))
2861 /* Update statistics - currently always up-to-date. */
2863 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2864 ("SK_RLMT_STATS_UPDATE Event END.\n"))
2865 } /* SkRlmtEvtStatsUpdate */
2868 /******************************************************************************
2870 * SkRlmtEvtPrefportChange - PREFPORT_CHANGE
2873 * This routine handles PREFPORT_CHANGE events.
2876 * runtime, pageable?
2877 * may be called after SK_INIT_IO
2882 RLMT_STATIC
void SkRlmtEvtPrefportChange(
2883 SK_AC
*pAC
, /* Adapter Context */
2884 SK_IOC IoC
, /* I/O Context */
2885 SK_EVPARA Para
) /* SK_U32 PortIndex; SK_U32 NetNumber */
2887 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2888 ("SK_RLMT_PREFPORT_CHANGE to Port %d Event BEGIN.\n", Para
.Para32
[0]))
2890 if (Para
.Para32
[1] >= pAC
->Rlmt
.NumNets
) {
2891 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2892 ("Bad NetNumber %d.\n", Para
.Para32
[1]))
2893 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2894 ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n"))
2898 /* 0xFFFFFFFF == auto-mode. */
2899 if (Para
.Para32
[0] == 0xFFFFFFFF) {
2900 pAC
->Rlmt
.Net
[Para
.Para32
[1]].PrefPort
= SK_RLMT_DEF_PREF_PORT
;
2903 if (Para
.Para32
[0] >= pAC
->Rlmt
.Net
[Para
.Para32
[1]].NumPorts
) {
2904 SK_ERR_LOG(pAC
, SK_ERRCL_SW
, SKERR_RLMT_E010
, SKERR_RLMT_E010_MSG
);
2906 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2907 ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n"))
2911 pAC
->Rlmt
.Net
[Para
.Para32
[1]].PrefPort
= Para
.Para32
[0];
2914 pAC
->Rlmt
.Net
[Para
.Para32
[1]].Preference
= Para
.Para32
[0];
2916 if (pAC
->Rlmt
.Net
[Para
.Para32
[1]].RlmtState
!= SK_RLMT_RS_INIT
) {
2917 SkRlmtCheckSwitch(pAC
, IoC
, Para
.Para32
[1]);
2920 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2921 ("SK_RLMT_PREFPORT_CHANGE Event END.\n"))
2922 } /* SkRlmtEvtPrefportChange */
2925 /******************************************************************************
2927 * SkRlmtEvtSetNets - SET_NETS
2930 * This routine handles SET_NETS events.
2933 * runtime, pageable?
2934 * may be called after SK_INIT_IO
2939 RLMT_STATIC
void SkRlmtEvtSetNets(
2940 SK_AC
*pAC
, /* Adapter Context */
2941 SK_IOC IoC
, /* I/O Context */
2942 SK_EVPARA Para
) /* SK_U32 NumNets; SK_U32 -1 */
2946 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2947 ("SK_RLMT_SET_NETS Event BEGIN.\n"))
2949 if (Para
.Para32
[1] != (SK_U32
)-1) {
2950 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2951 ("Bad Parameter.\n"))
2952 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2953 ("SK_RLMT_SET_NETS Event EMPTY.\n"))
2957 if (Para
.Para32
[0] == 0 || Para
.Para32
[0] > SK_MAX_NETS
||
2958 Para
.Para32
[0] > (SK_U32
)pAC
->GIni
.GIMacsFound
) {
2959 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2960 ("Bad number of nets: %d.\n", Para
.Para32
[0]))
2961 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2962 ("SK_RLMT_SET_NETS Event EMPTY.\n"))
2966 if (Para
.Para32
[0] == pAC
->Rlmt
.NumNets
) { /* No change. */
2967 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2968 ("SK_RLMT_SET_NETS Event EMPTY.\n"))
2972 /* Entering and leaving dual mode only allowed while nets are stopped. */
2973 if (pAC
->Rlmt
.NetsStarted
> 0) {
2974 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2975 ("Changing dual mode only allowed while all nets are stopped.\n"))
2976 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
2977 ("SK_RLMT_SET_NETS Event EMPTY.\n"))
2981 if (Para
.Para32
[0] == 1) {
2982 if (pAC
->Rlmt
.NumNets
> 1) {
2983 /* Clear logical MAC addr from second net's active port. */
2984 (void)SkAddrOverride(pAC
, IoC
, pAC
->Rlmt
.Net
[1].Port
[pAC
->Addr
.
2985 Net
[1].ActivePort
]->PortNumber
, NULL
, SK_ADDR_CLEAR_LOGICAL
);
2986 pAC
->Rlmt
.Net
[1].NumPorts
= 0;
2989 pAC
->Rlmt
.NumNets
= Para
.Para32
[0];
2990 for (i
= 0; (SK_U32
)i
< pAC
->Rlmt
.NumNets
; i
++) {
2991 pAC
->Rlmt
.Net
[i
].RlmtState
= SK_RLMT_RS_INIT
;
2992 pAC
->Rlmt
.Net
[i
].RootIdSet
= SK_FALSE
;
2993 pAC
->Rlmt
.Net
[i
].Preference
= 0xFFFFFFFF; /* "Automatic" */
2994 pAC
->Rlmt
.Net
[i
].PrefPort
= SK_RLMT_DEF_PREF_PORT
;
2995 /* Just assuming. */
2996 pAC
->Rlmt
.Net
[i
].ActivePort
= pAC
->Rlmt
.Net
[i
].PrefPort
;
2997 pAC
->Rlmt
.Net
[i
].RlmtMode
= SK_RLMT_DEF_MODE
;
2998 pAC
->Rlmt
.Net
[i
].TimeoutValue
= SK_RLMT_DEF_TO_VAL
;
2999 pAC
->Rlmt
.Net
[i
].NetNumber
= i
;
3002 pAC
->Rlmt
.Port
[1].Net
= &pAC
->Rlmt
.Net
[0];
3003 pAC
->Rlmt
.Net
[0].NumPorts
= pAC
->GIni
.GIMacsFound
;
3005 SkEventQueue(pAC
, SKGE_PNMI
, SK_PNMI_EVT_RLMT_SET_NETS
, Para
);
3007 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
3008 ("RLMT: Changed to one net with two ports.\n"))
3010 else if (Para
.Para32
[0] == 2) {
3011 pAC
->Rlmt
.Port
[1].Net
= &pAC
->Rlmt
.Net
[1];
3012 pAC
->Rlmt
.Net
[1].NumPorts
= pAC
->GIni
.GIMacsFound
- 1;
3013 pAC
->Rlmt
.Net
[0].NumPorts
=
3014 pAC
->GIni
.GIMacsFound
- pAC
->Rlmt
.Net
[1].NumPorts
;
3016 pAC
->Rlmt
.NumNets
= Para
.Para32
[0];
3017 for (i
= 0; (SK_U32
)i
< pAC
->Rlmt
.NumNets
; i
++) {
3018 pAC
->Rlmt
.Net
[i
].RlmtState
= SK_RLMT_RS_INIT
;
3019 pAC
->Rlmt
.Net
[i
].RootIdSet
= SK_FALSE
;
3020 pAC
->Rlmt
.Net
[i
].Preference
= 0xFFFFFFFF; /* "Automatic" */
3021 pAC
->Rlmt
.Net
[i
].PrefPort
= SK_RLMT_DEF_PREF_PORT
;
3022 /* Just assuming. */
3023 pAC
->Rlmt
.Net
[i
].ActivePort
= pAC
->Rlmt
.Net
[i
].PrefPort
;
3024 pAC
->Rlmt
.Net
[i
].RlmtMode
= SK_RLMT_DEF_MODE
;
3025 pAC
->Rlmt
.Net
[i
].TimeoutValue
= SK_RLMT_DEF_TO_VAL
;
3027 pAC
->Rlmt
.Net
[i
].NetNumber
= i
;
3030 /* Set logical MAC addr on second net's active port. */
3031 (void)SkAddrOverride(pAC
, IoC
, pAC
->Rlmt
.Net
[1].Port
[pAC
->Addr
.
3032 Net
[1].ActivePort
]->PortNumber
, NULL
, SK_ADDR_SET_LOGICAL
);
3034 SkEventQueue(pAC
, SKGE_PNMI
, SK_PNMI_EVT_RLMT_SET_NETS
, Para
);
3036 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
3037 ("RLMT: Changed to two nets with one port each.\n"))
3040 /* Not implemented for more than two nets. */
3041 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
3042 ("SetNets not implemented for more than two nets.\n"))
3043 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
3044 ("SK_RLMT_SET_NETS Event EMPTY.\n"))
3048 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
3049 ("SK_RLMT_SET_NETS Event END.\n"))
3050 } /* SkRlmtSetNets */
3053 /******************************************************************************
3055 * SkRlmtEvtModeChange - MODE_CHANGE
3058 * This routine handles MODE_CHANGE events.
3061 * runtime, pageable?
3062 * may be called after SK_INIT_IO
3067 RLMT_STATIC
void SkRlmtEvtModeChange(
3068 SK_AC
*pAC
, /* Adapter Context */
3069 SK_IOC IoC
, /* I/O Context */
3070 SK_EVPARA Para
) /* SK_U32 NewMode; SK_U32 NetNumber */
3074 SK_U32 PrevRlmtMode
;
3076 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
3077 ("SK_RLMT_MODE_CHANGE Event BEGIN.\n"))
3079 if (Para
.Para32
[1] >= pAC
->Rlmt
.NumNets
) {
3080 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
3081 ("Bad NetNumber %d.\n", Para
.Para32
[1]))
3082 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
3083 ("SK_RLMT_MODE_CHANGE Event EMPTY.\n"))
3087 Para
.Para32
[0] |= SK_RLMT_CHECK_LINK
;
3089 if ((pAC
->Rlmt
.Net
[Para
.Para32
[1]].NumPorts
== 1) &&
3090 Para
.Para32
[0] != SK_RLMT_MODE_CLS
) {
3091 pAC
->Rlmt
.Net
[Para
.Para32
[1]].RlmtMode
= SK_RLMT_MODE_CLS
;
3092 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
3093 ("Forced RLMT mode to CLS on single port net.\n"))
3094 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
3095 ("SK_RLMT_MODE_CHANGE Event EMPTY.\n"))
3099 /* Update RLMT mode. */
3100 PrevRlmtMode
= pAC
->Rlmt
.Net
[Para
.Para32
[1]].RlmtMode
;
3101 pAC
->Rlmt
.Net
[Para
.Para32
[1]].RlmtMode
= Para
.Para32
[0];
3103 if ((PrevRlmtMode
& SK_RLMT_CHECK_LOC_LINK
) !=
3104 (pAC
->Rlmt
.Net
[Para
.Para32
[1]].RlmtMode
& SK_RLMT_CHECK_LOC_LINK
)) {
3105 /* SK_RLMT_CHECK_LOC_LINK bit changed. */
3106 if ((PrevRlmtMode
& SK_RLMT_CHECK_OTHERS
) == 0 &&
3107 pAC
->Rlmt
.Net
[Para
.Para32
[1]].NumPorts
> 1 &&
3108 pAC
->Rlmt
.Net
[Para
.Para32
[1]].PortsUp
>= 1) {
3109 /* 20001207 RA: Was "PortsUp == 1". */
3110 Para2
.Para32
[0] = Para
.Para32
[1];
3111 Para2
.Para32
[1] = (SK_U32
)-1;
3112 SkTimerStart(pAC
, IoC
, &pAC
->Rlmt
.Net
[Para
.Para32
[1]].LocTimer
,
3113 pAC
->Rlmt
.Net
[Para
.Para32
[1]].TimeoutValue
,
3114 SKGE_RLMT
, SK_RLMT_TIM
, Para2
);
3118 if ((PrevRlmtMode
& SK_RLMT_CHECK_SEG
) !=
3119 (pAC
->Rlmt
.Net
[Para
.Para32
[1]].RlmtMode
& SK_RLMT_CHECK_SEG
)) {
3120 /* SK_RLMT_CHECK_SEG bit changed. */
3121 for (i
= 0; i
< pAC
->Rlmt
.Net
[Para
.Para32
[1]].NumPorts
; i
++) {
3122 (void)SkAddrMcClear(pAC
, IoC
,
3123 pAC
->Rlmt
.Net
[Para
.Para32
[1]].Port
[i
]->PortNumber
,
3124 SK_ADDR_PERMANENT
| SK_MC_SW_ONLY
);
3126 /* Add RLMT MC address. */
3127 (void)SkAddrMcAdd(pAC
, IoC
,
3128 pAC
->Rlmt
.Net
[Para
.Para32
[1]].Port
[i
]->PortNumber
,
3129 &SkRlmtMcAddr
, SK_ADDR_PERMANENT
);
3131 if ((pAC
->Rlmt
.Net
[Para
.Para32
[1]].RlmtMode
&
3132 SK_RLMT_CHECK_SEG
) != 0) {
3133 /* Add BPDU MC address. */
3134 (void)SkAddrMcAdd(pAC
, IoC
,
3135 pAC
->Rlmt
.Net
[Para
.Para32
[1]].Port
[i
]->PortNumber
,
3136 &BridgeMcAddr
, SK_ADDR_PERMANENT
);
3138 if (pAC
->Rlmt
.Net
[Para
.Para32
[1]].RlmtState
!= SK_RLMT_RS_INIT
) {
3139 if (!pAC
->Rlmt
.Net
[Para
.Para32
[1]].Port
[i
]->LinkDown
&&
3140 (Para2
.pParaPtr
= SkRlmtBuildSpanningTreePacket(
3141 pAC
, IoC
, i
)) != NULL
) {
3142 pAC
->Rlmt
.Net
[Para
.Para32
[1]].Port
[i
]->RootIdSet
=
3144 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_RLMT_SEND
, Para2
);
3148 (void)SkAddrMcUpdate(pAC
, IoC
,
3149 pAC
->Rlmt
.Net
[Para
.Para32
[1]].Port
[i
]->PortNumber
);
3152 if ((pAC
->Rlmt
.Net
[Para
.Para32
[1]].RlmtMode
& SK_RLMT_CHECK_SEG
) != 0) {
3153 Para2
.Para32
[0] = Para
.Para32
[1];
3154 Para2
.Para32
[1] = (SK_U32
)-1;
3155 SkTimerStart(pAC
, IoC
, &pAC
->Rlmt
.Net
[Para
.Para32
[1]].SegTimer
,
3156 SK_RLMT_SEG_TO_VAL
, SKGE_RLMT
, SK_RLMT_SEG_TIM
, Para2
);
3158 } /* SK_RLMT_CHECK_SEG bit changed. */
3160 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
3161 ("SK_RLMT_MODE_CHANGE Event END.\n"))
3162 } /* SkRlmtEvtModeChange */
3165 /******************************************************************************
3167 * SkRlmtEvent - a PORT- or an RLMT-specific event happened
3170 * This routine calls subroutines to handle PORT- and RLMT-specific events.
3173 * runtime, pageable?
3174 * may be called after SK_INIT_IO
3180 SK_AC
*pAC
, /* Adapter Context */
3181 SK_IOC IoC
, /* I/O Context */
3182 SK_U32 Event
, /* Event code */
3183 SK_EVPARA Para
) /* Event-specific parameter */
3187 /* ----- PORT events ----- */
3189 case SK_RLMT_PORTSTART_TIM
: /* From RLMT via TIME. */
3190 SkRlmtEvtPortStartTim(pAC
, IoC
, Para
);
3192 case SK_RLMT_LINK_UP
: /* From SIRQ. */
3193 SkRlmtEvtLinkUp(pAC
, IoC
, Para
);
3195 case SK_RLMT_PORTUP_TIM
: /* From RLMT via TIME. */
3196 SkRlmtEvtPortUpTim(pAC
, IoC
, Para
);
3198 case SK_RLMT_PORTDOWN
: /* From RLMT. */
3199 case SK_RLMT_PORTDOWN_RX_TIM
: /* From RLMT via TIME. */
3200 case SK_RLMT_PORTDOWN_TX_TIM
: /* From RLMT via TIME. */
3201 SkRlmtEvtPortDownX(pAC
, IoC
, Event
, Para
);
3203 case SK_RLMT_LINK_DOWN
: /* From SIRQ. */
3204 SkRlmtEvtLinkDown(pAC
, IoC
, Para
);
3206 case SK_RLMT_PORT_ADDR
: /* From ADDR. */
3207 SkRlmtEvtPortAddr(pAC
, IoC
, Para
);
3210 /* ----- RLMT events ----- */
3212 case SK_RLMT_START
: /* From DRV. */
3213 SkRlmtEvtStart(pAC
, IoC
, Para
);
3215 case SK_RLMT_STOP
: /* From DRV. */
3216 SkRlmtEvtStop(pAC
, IoC
, Para
);
3218 case SK_RLMT_TIM
: /* From RLMT via TIME. */
3219 SkRlmtEvtTim(pAC
, IoC
, Para
);
3221 case SK_RLMT_SEG_TIM
:
3222 SkRlmtEvtSegTim(pAC
, IoC
, Para
);
3224 case SK_RLMT_PACKET_RECEIVED
: /* From DRV. */
3225 SkRlmtEvtPacketRx(pAC
, IoC
, Para
);
3227 case SK_RLMT_STATS_CLEAR
: /* From PNMI. */
3228 SkRlmtEvtStatsClear(pAC
, IoC
, Para
);
3230 case SK_RLMT_STATS_UPDATE
: /* From PNMI. */
3231 SkRlmtEvtStatsUpdate(pAC
, IoC
, Para
);
3233 case SK_RLMT_PREFPORT_CHANGE
: /* From PNMI. */
3234 SkRlmtEvtPrefportChange(pAC
, IoC
, Para
);
3236 case SK_RLMT_MODE_CHANGE
: /* From PNMI. */
3237 SkRlmtEvtModeChange(pAC
, IoC
, Para
);
3239 case SK_RLMT_SET_NETS
: /* From DRV. */
3240 SkRlmtEvtSetNets(pAC
, IoC
, Para
);
3243 /* ----- Unknown events ----- */
3245 default: /* Create error log entry. */
3246 SK_DBG_MSG(pAC
, SK_DBGMOD_RLMT
, SK_DBGCAT_CTRL
,
3247 ("Unknown RLMT Event %d.\n", Event
))
3248 SK_ERR_LOG(pAC
, SK_ERRCL_SW
, SKERR_RLMT_E003
, SKERR_RLMT_E003_MSG
);
3257 #endif /* __cplusplus */