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