skrlmt.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:98k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

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