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