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

嵌入式Linux

开发平台:

Unix_Linux

  1. /******************************************************************************
  2.  *
  3.  * Name: skaddr.c
  4.  * Project: GEnesis, PCI Gigabit Ethernet Adapter
  5.  * Version: $Revision: 1.40 $
  6.  * Date: $Date: 2001/02/14 14:04:59 $
  7.  * Purpose: Manage Addresses (Multicast and Unicast) and Promiscuous Mode.
  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: skaddr.c,v $
  27.  * Revision 1.40  2001/02/14 14:04:59  rassmann
  28.  * Editorial changes.
  29.  *
  30.  * Revision 1.39  2001/01/30 10:30:04  rassmann
  31.  * Editorial changes.
  32.  *
  33.  * Revision 1.38  2001/01/25 16:26:52  rassmann
  34.  * Ensured that logical address overrides are done on net's active port.
  35.  *
  36.  * Revision 1.37  2001/01/22 13:41:34  rassmann
  37.  * Supporting two nets on dual-port adapters.
  38.  *
  39.  * Revision 1.36  2000/08/07 11:10:39  rassmann
  40.  * Editorial changes.
  41.  *
  42.  * Revision 1.35  2000/05/04 09:38:41  rassmann
  43.  * Editorial changes.
  44.  * Corrected multicast address hashing.
  45.  *
  46.  * Revision 1.34  1999/11/22 13:23:44  cgoos
  47.  * Changed license header to GPL.
  48.  *
  49.  * Revision 1.33  1999/05/28 10:56:06  rassmann
  50.  * Editorial changes.
  51.  *
  52.  * Revision 1.32  1999/03/31 10:59:20  rassmann
  53.  * Returning Success instead of DupAddr if address shall be overridden
  54.  * with same value.
  55.  *
  56.  * Revision 1.31  1999/01/14 16:18:17  rassmann
  57.  * Corrected multicast initialization.
  58.  *
  59.  * Revision 1.30  1999/01/04 10:30:35  rassmann
  60.  * SkAddrOverride only possible after SK_INIT_IO phase.
  61.  *
  62.  * Revision 1.29  1998/12/29 13:13:10  rassmann
  63.  * An address override is now preserved in the SK_INIT_IO phase.
  64.  * All functions return an int now.
  65.  * Extended parameter checking.
  66.  *
  67.  * Revision 1.28  1998/12/01 11:45:53  rassmann
  68.  * Code cleanup.
  69.  *
  70.  * Revision 1.27  1998/12/01 09:22:49  rassmann
  71.  * SkAddrMcAdd and SkAddrMcUpdate returned SK_MC_FILTERING_INEXACT
  72.  * too often.
  73.  *
  74.  * Revision 1.26  1998/11/24 12:39:44  rassmann
  75.  * Reserved multicast entry for BPDU address.
  76.  * 13 multicast entries left for protocol.
  77.  *
  78.  * Revision 1.25  1998/11/17 16:54:23  rassmann
  79.  * Using exact match for up to 14 multicast addresses.
  80.  * Still receiving all multicasts if more addresses are added.
  81.  *
  82.  * Revision 1.24  1998/11/13 17:24:31  rassmann
  83.  * Changed return value of SkAddrOverride to int.
  84.  *
  85.  * Revision 1.23  1998/11/13 16:56:18  rassmann
  86.  * Added macro SK_ADDR_COMPARE.
  87.  * Changed return type of SkAddrOverride to SK_BOOL.
  88.  *
  89.  * Revision 1.22  1998/11/04 17:06:17  rassmann
  90.  * Corrected McUpdate and PromiscuousChange functions.
  91.  *
  92.  * Revision 1.21  1998/10/29 14:34:04  rassmann
  93.  * Clearing SK_ADDR struct at startup.
  94.  *
  95.  * Revision 1.20  1998/10/28 18:16:34  rassmann
  96.  * Avoiding I/Os before SK_INIT_RUN level.
  97.  * Aligning InexactFilter.
  98.  *
  99.  * Revision 1.19  1998/10/28 11:29:28  rassmann
  100.  * Programming physical address in SkAddrMcUpdate.
  101.  * Corrected programming of exact match entries.
  102.  *
  103.  * Revision 1.18  1998/10/28 10:34:48  rassmann
  104.  * Corrected reading of physical addresses.
  105.  *
  106.  * Revision 1.17  1998/10/28 10:26:13  rassmann
  107.  * Getting ports' current MAC addresses from EPROM now.
  108.  * Added debug output.
  109.  *
  110.  * Revision 1.16  1998/10/27 16:20:12  rassmann
  111.  * Reading MAC address byte by byte.
  112.  *
  113.  * Revision 1.15  1998/10/22 11:39:09  rassmann
  114.  * Corrected signed/unsigned mismatches.
  115.  *
  116.  * Revision 1.14  1998/10/19 17:12:35  rassmann
  117.  * Syntax corrections.
  118.  *
  119.  * Revision 1.13  1998/10/19 17:02:19  rassmann
  120.  * Now reading permanent MAC addresses from CRF.
  121.  *
  122.  * Revision 1.12  1998/10/15 15:15:48  rassmann
  123.  * Changed Flags Parameters from SK_U8 to int.
  124.  * Checked with lint.
  125.  *
  126.  * Revision 1.11  1998/09/24 19:15:12  rassmann
  127.  * Code cleanup.
  128.  *
  129.  * Revision 1.10  1998/09/18 20:18:54  rassmann
  130.  * Added HW access.
  131.  * Implemented swapping.
  132.  *
  133.  * Revision 1.9  1998/09/16 11:32:00  rassmann
  134.  * Including skdrv1st.h again. :(
  135.  *
  136.  * Revision 1.8  1998/09/16 11:09:34  rassmann
  137.  * Syntax corrections.
  138.  *
  139.  * Revision 1.7  1998/09/14 17:06:34  rassmann
  140.  * Minor changes.
  141.  *
  142.  * Revision 1.6  1998/09/07 08:45:41  rassmann
  143.  * Syntax corrections.
  144.  *
  145.  * Revision 1.5  1998/09/04 19:40:19  rassmann
  146.  * Interface enhancements.
  147.  *
  148.  * Revision 1.4  1998/09/04 12:14:12  rassmann
  149.  * Interface cleanup.
  150.  *
  151.  * Revision 1.3  1998/09/02 16:56:40  rassmann
  152.  * Updated interface.
  153.  *
  154.  * Revision 1.2  1998/08/27 14:26:09  rassmann
  155.  * Updated interface.
  156.  *
  157.  * Revision 1.1  1998/08/21 08:30:22  rassmann
  158.  * First public version.
  159.  *
  160.  ******************************************************************************/
  161. /******************************************************************************
  162.  *
  163.  * Description:
  164.  *
  165.  * This module is intended to manage multicast addresses, address override,
  166.  * and promiscuous mode on GEnesis adapters.
  167.  *
  168.  * Address Layout:
  169.  * port address: physical MAC address
  170.  * 1st exact match: logical MAC address
  171.  * 2nd exact match: RLMT multicast
  172.  * exact match 3-13: OS-specific multicasts
  173.  *
  174.  * Include File Hierarchy:
  175.  *
  176.  * "skdrv1st.h"
  177.  * "skdrv2nd.h"
  178.  *
  179.  ******************************************************************************/
  180. #ifndef lint
  181. static const char SysKonnectFileId[] =
  182. "@(#) $Id: skaddr.c,v 1.40 2001/02/14 14:04:59 rassmann Exp $ (C) SysKonnect.";
  183. #endif /* !defined(lint) */
  184. #define __SKADDR_C
  185. #ifdef __cplusplus
  186. #error C++ is not yet supported.
  187. extern "C" {
  188. #endif /* cplusplus */
  189. #include "h/skdrv1st.h"
  190. #include "h/skdrv2nd.h"
  191. /* defines ********************************************************************/
  192. #define CRC32_POLY 0xEDB88320UL /* CRC32-Poly - XMAC: Little Endian */
  193. #define HASH_BITS 6 /* #bits in hash */
  194. #define SK_MC_BIT 0x01
  195. /* Error numbers and messages. */
  196. #define SKERR_ADDR_E001 (SK_ERRBASE_ADDR + 0)
  197. #define SKERR_ADDR_E001MSG "Bad Flags."
  198. #define SKERR_ADDR_E002 (SKERR_ADDR_E001 + 1)
  199. #define SKERR_ADDR_E002MSG "New Error."
  200. /* typedefs *******************************************************************/
  201. /* None. */
  202. /* global variables ***********************************************************/
  203. /* 64-bit hash values with all bits set. */
  204. SK_U16 OnesHash[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
  205. /* local variables ************************************************************/
  206. #ifdef DEBUG
  207. static int Next0[SK_MAX_MACS] = {0, 0};
  208. #endif /* DEBUG */
  209. /* functions ******************************************************************/
  210. /******************************************************************************
  211.  *
  212.  * SkAddrInit - initialize data, set state to init
  213.  *
  214.  * Description:
  215.  *
  216.  * SK_INIT_DATA
  217.  * ============
  218.  *
  219.  * This routine clears the multicast tables and resets promiscuous mode.
  220.  * Some entries are reserved for the "logical MAC address", the
  221.  * SK-RLMT multicast address, and the BPDU multicast address.
  222.  *
  223.  *
  224.  * SK_INIT_IO
  225.  * ==========
  226.  *
  227.  * All permanent MAC addresses are read from EPROM.
  228.  * If the current MAC addresses are not already set in software,
  229.  * they are set to the values of the permanent addresses.
  230.  * The current addresses are written to the corresponding XMAC.
  231.  *
  232.  *
  233.  * SK_INIT_RUN
  234.  * ===========
  235.  *
  236.  * Nothing.
  237.  *
  238.  * Context:
  239.  * init, pageable
  240.  *
  241.  * Returns:
  242.  * SK_ADDR_SUCCESS
  243.  */
  244. int SkAddrInit(
  245. SK_AC *pAC, /* the adapter context */
  246. SK_IOC IoC, /* I/O context */
  247. int Level) /* initialization level */
  248. {
  249. int j;
  250. SK_U32 i;
  251. SK_U8 *InAddr;
  252. SK_U16 *OutAddr;
  253. SK_ADDR_PORT *pAPort;
  254. switch (Level) {
  255. case SK_INIT_DATA:
  256. SK_MEMSET((char *)&pAC->Addr, 0, sizeof(SK_ADDR));
  257. for (i = 0; i < SK_MAX_MACS; i++) {
  258. pAPort = &pAC->Addr.Port[i];
  259. pAPort->PromMode = SK_PROM_MODE_NONE;
  260. pAPort->FirstExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
  261. pAPort->FirstExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
  262. pAPort->NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
  263. pAPort->NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
  264. #if 0
  265. /* Don't do this here ... */
  266. /* Reset Promiscuous mode. */
  267. (void)SkAddrPromiscuousChange(
  268. pAC,
  269. IoC,
  270. i,
  271. SK_PROM_MODE_NONE);
  272. #endif /* 0 */
  273. }
  274. #ifdef DEBUG
  275. for (i = 0; i < SK_MAX_MACS; i++) {
  276. if (pAC->Addr.Port[i].NextExactMatchRlmt <
  277. SK_ADDR_FIRST_MATCH_RLMT) {
  278. Next0[i] |= 4;
  279. }
  280. }
  281. #endif /* DEBUG */
  282. /* pAC->Addr.InitDone = SK_INIT_DATA; */
  283. break;
  284. case SK_INIT_IO:
  285. for (i = 0; i < SK_MAX_NETS; i++) {
  286. pAC->Addr.Net[i].ActivePort = pAC->Rlmt.Net[i].ActivePort;
  287. }
  288. #ifdef DEBUG
  289. for (i = 0; i < SK_MAX_MACS; i++) {
  290. if (pAC->Addr.Port[i].NextExactMatchRlmt <
  291. SK_ADDR_FIRST_MATCH_RLMT) {
  292. Next0[i] |= 8;
  293. }
  294. }
  295. #endif /* DEBUG */
  296. /* Read permanent logical MAC address from Control Register File. */
  297. for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
  298. InAddr = (SK_U8 *)&pAC->Addr.Net[0].PermanentMacAddress.a[j];
  299. SK_IN8(IoC, B2_MAC_1 + j, InAddr);
  300. }
  301. if (!pAC->Addr.Net[0].CurrentMacAddressSet) {
  302. /* Set the current logical MAC address to the permanent one. */
  303. pAC->Addr.Net[0].CurrentMacAddress =
  304. pAC->Addr.Net[0].PermanentMacAddress;
  305. pAC->Addr.Net[0].CurrentMacAddressSet = SK_TRUE;
  306. }
  307. /* Set the current logical MAC address. */
  308. pAC->Addr.Port[pAC->Addr.Net[0].ActivePort].Exact[0] =
  309. pAC->Addr.Net[0].CurrentMacAddress;
  310. #if SK_MAX_NETS > 1
  311. /* Set logical MAC address for net 2 to (log | 3). */
  312. if (!pAC->Addr.Net[1].CurrentMacAddressSet) {
  313. pAC->Addr.Net[1].PermanentMacAddress =
  314. pAC->Addr.Net[0].PermanentMacAddress;
  315. pAC->Addr.Net[1].PermanentMacAddress.a[5] |= 3;
  316. /* Set the current logical MAC address to the permanent one. */
  317. pAC->Addr.Net[1].CurrentMacAddress =
  318. pAC->Addr.Net[1].PermanentMacAddress;
  319. pAC->Addr.Net[1].CurrentMacAddressSet = SK_TRUE;
  320. }
  321. #endif /* SK_MAX_NETS > 1 */
  322. #ifdef xDEBUG
  323. SK_DBG_MSG(
  324. pAC,
  325. SK_DBGMOD_ADDR,
  326. SK_DBGCAT_INIT,
  327. ("Permanent MAC Address: %02X %02X %02X %02X %02X %02Xn",
  328. pAC->Addr.PermanentMacAddress.a[0],
  329. pAC->Addr.PermanentMacAddress.a[1],
  330. pAC->Addr.PermanentMacAddress.a[2],
  331. pAC->Addr.PermanentMacAddress.a[3],
  332. pAC->Addr.PermanentMacAddress.a[4],
  333. pAC->Addr.PermanentMacAddress.a[5]))
  334. SK_DBG_MSG(
  335. pAC,
  336. SK_DBGMOD_ADDR,
  337. SK_DBGCAT_INIT,
  338. ("Logical MAC Address: %02X %02X %02X %02X %02X %02Xn",
  339. pAC->Addr.CurrentMacAddress.a[0],
  340. pAC->Addr.CurrentMacAddress.a[1],
  341. pAC->Addr.CurrentMacAddress.a[2],
  342. pAC->Addr.CurrentMacAddress.a[3],
  343. pAC->Addr.CurrentMacAddress.a[4],
  344. pAC->Addr.CurrentMacAddress.a[5]))
  345. #endif /* DEBUG */
  346. #if 0
  347. /* Don't do this here ... */
  348. (void)SkAddrMcUpdate(pAC, IoC, pAC->Addr.ActivePort);
  349. #endif /* 0 */
  350. for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
  351. pAPort = &pAC->Addr.Port[i];
  352. /* Read permanent port addresses from Control Register File. */
  353. for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
  354. InAddr = (SK_U8 *)&pAPort->PermanentMacAddress.a[j];
  355. SK_IN8(IoC, B2_MAC_2 + 8 * i + j, InAddr);
  356. }
  357. if (!pAPort->CurrentMacAddressSet) {
  358. /*
  359.  * Set the current and previous physical MAC address
  360.  * of this port to its permanent MAC address.
  361.  */
  362. pAPort->CurrentMacAddress = pAPort->PermanentMacAddress;
  363. pAPort->PreviousMacAddress = pAPort->PermanentMacAddress;
  364. pAPort->CurrentMacAddressSet = SK_TRUE;
  365. }
  366. /* Set port's current MAC addresses. */
  367. OutAddr = (SK_U16 *)&pAPort->CurrentMacAddress.a[0];
  368. XM_OUTADDR(IoC, i, XM_SA, OutAddr);
  369. #ifdef xDEBUG
  370. SK_DBG_MSG(
  371. pAC,
  372. SK_DBGMOD_ADDR,
  373. SK_DBGCAT_INIT,
  374. ("Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02Xn",
  375. pAPort->PermanentMacAddress.a[0],
  376. pAPort->PermanentMacAddress.a[1],
  377. pAPort->PermanentMacAddress.a[2],
  378. pAPort->PermanentMacAddress.a[3],
  379. pAPort->PermanentMacAddress.a[4],
  380. pAPort->PermanentMacAddress.a[5]))
  381. SK_DBG_MSG(
  382. pAC,
  383. SK_DBGMOD_ADDR,
  384. SK_DBGCAT_INIT,
  385. ("Phsical MAC Address: %02X %02X %02X %02X %02X %02Xn",
  386. pAPort->CurrentMacAddress.a[0],
  387. pAPort->CurrentMacAddress.a[1],
  388. pAPort->CurrentMacAddress.a[2],
  389. pAPort->CurrentMacAddress.a[3],
  390. pAPort->CurrentMacAddress.a[4],
  391. pAPort->CurrentMacAddress.a[5]))
  392. #endif /* DEBUG */
  393. }
  394. /* pAC->Addr.InitDone = SK_INIT_IO; */
  395. break;
  396. case SK_INIT_RUN:
  397. #ifdef DEBUG
  398. for (i = 0; i < SK_MAX_MACS; i++) {
  399. if (pAC->Addr.Port[i].NextExactMatchRlmt <
  400. SK_ADDR_FIRST_MATCH_RLMT) {
  401. Next0[i] |= 16;
  402. }
  403. }
  404. #endif /* DEBUG */
  405. /* pAC->Addr.InitDone = SK_INIT_RUN; */
  406. break;
  407. default: /* error */
  408. break;
  409. }
  410. return (SK_ADDR_SUCCESS);
  411. } /* SkAddrInit */
  412. /******************************************************************************
  413.  *
  414.  * SkAddrMcClear - clear the multicast table
  415.  *
  416.  * Description:
  417.  * This routine clears the multicast table
  418.  * (either entry 2 or entries 3-16 and InexactFilter) of the given port.
  419.  * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
  420.  * immediately.
  421.  *
  422.  * Context:
  423.  * runtime, pageable
  424.  * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
  425.  * may be called after SK_INIT_IO without limitation
  426.  *
  427.  * Returns:
  428.  * SK_ADDR_SUCCESS
  429.  * SK_ADDR_ILLEGAL_PORT
  430.  */
  431. int SkAddrMcClear(
  432. SK_AC *pAC, /* adapter context */
  433. SK_IOC IoC, /* I/O context */
  434. SK_U32 PortNumber, /* Index of affected port */
  435. int Flags) /* permanent/non-perm, sw-only */
  436. {
  437. int i;
  438. if (PortNumber >= (SK_U32)pAC->GIni.GIMacsFound) {
  439. return (SK_ADDR_ILLEGAL_PORT);
  440. }
  441. if (Flags & SK_ADDR_PERMANENT) {
  442. /* Clear RLMT multicast addresses. */
  443. pAC->Addr.Port[PortNumber].NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
  444. }
  445. else { /* not permanent => DRV */
  446. /* Clear InexactFilter. */
  447. for (i = 0; i < 8; i++) {
  448. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
  449. }
  450. /* Clear DRV multicast addresses. */
  451. pAC->Addr.Port[PortNumber].NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
  452. }
  453. if (!(Flags & SK_MC_SW_ONLY)) {
  454. (void)SkAddrMcUpdate(pAC, IoC, PortNumber);
  455. }
  456. return (SK_ADDR_SUCCESS);
  457. } /* SkAddrMcClear */
  458. #ifndef SK_ADDR_CHEAT
  459. /******************************************************************************
  460.  *
  461.  * SkCrc32McHash - hash multicast address
  462.  *
  463.  * Description:
  464.  * This routine computes the hash value for a multicast address.
  465.  *
  466.  * Notes:
  467.  * The code was adapted from the XaQti data sheet.
  468.  *
  469.  * Context:
  470.  * runtime, pageable
  471.  *
  472.  * Returns:
  473.  * Hash value of multicast address.
  474.  */
  475. unsigned SkCrc32McHash(
  476. unsigned char *pMc) /* Multicast address */
  477. {
  478. unsigned Idx;
  479. unsigned Bit;
  480. unsigned Data;
  481. unsigned Crc;
  482. Crc = 0xFFFFFFFFUL;
  483. for (Idx = 0; Idx < SK_MAC_ADDR_LEN; Idx++) {
  484. Data = *pMc++;
  485. for (Bit = 0; Bit < 8; Bit++, Data >>= 1) {
  486. Crc = (Crc >> 1) ^ (((Crc ^ Data) & 1) ? CRC32_POLY : 0);
  487. }
  488. }
  489. return (Crc & ((1 << HASH_BITS) - 1));
  490. } /* SkCrc32McHash */
  491. #endif /* not SK_ADDR_CHEAT */
  492. /******************************************************************************
  493.  *
  494.  * SkAddrMcAdd - add a multicast address to a port
  495.  *
  496.  * Description:
  497.  * This routine enables reception for a given address on the given port.
  498.  *
  499.  * Notes:
  500.  * The return code is only valid for SK_PROM_MODE_NONE.
  501.  *
  502.  * In the current version, only RLMT may add addresses to the non-active
  503.  * port.
  504.  *
  505.  * The multicast bit is only checked if there are no free exact match
  506.  * entries.
  507.  *
  508.  * Context:
  509.  * runtime, pageable
  510.  * may be called after SK_INIT_DATA
  511.  *
  512.  * Returns:
  513.  * SK_MC_FILTERING_EXACT
  514.  * SK_MC_FILTERING_INEXACT
  515.  * SK_MC_ILLEGAL_ADDRESS
  516.  * SK_MC_ILLEGAL_PORT
  517.  * SK_MC_RLMT_OVERFLOW
  518.  */
  519. int SkAddrMcAdd(
  520. SK_AC *pAC, /* adapter context */
  521. SK_IOC IoC, /* I/O context */
  522. SK_U32 PortNumber, /* Port Number */
  523. SK_MAC_ADDR *pMc, /* multicast address to be added */
  524. int Flags) /* permanent/non-permanent */
  525. {
  526. int i;
  527. SK_U8 Inexact;
  528. #ifndef SK_ADDR_CHEAT
  529. unsigned HashBit;
  530. #endif /* !defined(SK_ADDR_CHEAT) */
  531. if (PortNumber >= (SK_U32)pAC->GIni.GIMacsFound) {
  532. return (SK_ADDR_ILLEGAL_PORT);
  533. }
  534. if (Flags & SK_ADDR_PERMANENT) {
  535. #ifdef DEBUG
  536. if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt <
  537. SK_ADDR_FIRST_MATCH_RLMT) {
  538. Next0[PortNumber] |= 1;
  539. return (SK_MC_RLMT_OVERFLOW);
  540. }
  541. #endif /* DEBUG */
  542. if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt >
  543. SK_ADDR_LAST_MATCH_RLMT) {
  544. return (SK_MC_RLMT_OVERFLOW);
  545. }
  546. /* Set an RLMT multicast address. */
  547. pAC->Addr.Port[PortNumber].Exact[
  548. pAC->Addr.Port[PortNumber].NextExactMatchRlmt++] = *pMc;
  549. return (SK_MC_FILTERING_EXACT);
  550. }
  551. #if 0
  552. /* Not PERMANENT => DRV */
  553. if (PortNumber != pAC->Addr.ActivePort) {
  554. /* Only RLMT is allowed to do this. */
  555. return (SK_MC_ILLEGAL_PORT);
  556. }
  557. #endif /* 0 */
  558. #ifdef DEBUG
  559. if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <
  560. SK_ADDR_FIRST_MATCH_DRV) {
  561. Next0[PortNumber] |= 2;
  562. return (SK_MC_RLMT_OVERFLOW);
  563. }
  564. #endif /* DEBUG */
  565. if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
  566. /* Set exact match entry. */
  567. pAC->Addr.Port[PortNumber].Exact[
  568. pAC->Addr.Port[PortNumber].NextExactMatchDrv++] = *pMc;
  569. /* Clear InexactFilter. */
  570. for (i = 0; i < 8; i++) {
  571. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
  572. }
  573. }
  574. else {
  575. if (!(pMc->a[0] & SK_MC_BIT)) {
  576. /*
  577.  * Hashing only possible with
  578.  * multicast addresses.
  579.  */
  580. return (SK_MC_ILLEGAL_ADDRESS);
  581. }
  582. #ifndef SK_ADDR_CHEAT
  583. /* Compute hash value of address. */
  584. HashBit = 63 - SkCrc32McHash(&pMc->a[0]);
  585. /* Add bit to InexactFilter. */
  586. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[HashBit / 8] |=
  587. 1 << (HashBit % 8);
  588. #else /* SK_ADDR_CHEAT */
  589. /* Set all bits in InexactFilter. */
  590. for (i = 0; i < 8; i++) {
  591. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
  592. }
  593. #endif /* SK_ADDR_CHEAT */
  594. }
  595. for (Inexact = 0, i = 0; i < 8; i++) {
  596. Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
  597. }
  598. if (Inexact == 0 && pAC->Addr.Port[PortNumber].PromMode == 0) {
  599. return (SK_MC_FILTERING_EXACT);
  600. }
  601. else {
  602. return (SK_MC_FILTERING_INEXACT);
  603. }
  604. } /* SkAddrMcAdd */
  605. /******************************************************************************
  606.  *
  607.  * SkAddrMcUpdate - update the HW MC address table and set the MAC address
  608.  *
  609.  * Description:
  610.  * This routine enables reception of the addresses contained in a local
  611.  * table for a given port.
  612.  * It also programs the port's current physical MAC address.
  613.  *
  614.  * Notes:
  615.  * The return code is only valid for SK_PROM_MODE_NONE.
  616.  *
  617.  * Context:
  618.  * runtime, pageable
  619.  * may be called after SK_INIT_IO
  620.  *
  621.  * Returns:
  622.  * SK_MC_FILTERING_EXACT
  623.  * SK_MC_FILTERING_INEXACT
  624.  * SK_ADDR_ILLEGAL_PORT
  625.  */
  626. int SkAddrMcUpdate(
  627. SK_AC *pAC, /* adapter context */
  628. SK_IOC IoC, /* I/O context */
  629. SK_U32 PortNumber) /* Port Number */
  630. {
  631. SK_U32 i;
  632. SK_U8 Inexact;
  633. SK_U16 *OutAddr;
  634. SK_U16 LoMode; /* Lower 16 bits of XMAC Mode Reg. */
  635. SK_ADDR_PORT *pAPort;
  636. if (PortNumber >= (SK_U32)pAC->GIni.GIMacsFound) {
  637. return (SK_ADDR_ILLEGAL_PORT);
  638. }
  639. SK_DBG_MSG(
  640. pAC,
  641. SK_DBGMOD_ADDR,
  642. SK_DBGCAT_CTRL,
  643. ("SkAddrMcUpdate on Port %u.n", PortNumber))
  644. pAPort = &pAC->Addr.Port[PortNumber];
  645. #ifdef DEBUG
  646. SK_DBG_MSG(
  647. pAC,
  648. SK_DBGMOD_ADDR,
  649. SK_DBGCAT_CTRL,
  650. ("Next0 on Port %d: %dn", PortNumber, Next0[PortNumber]))
  651. #endif /* DEBUG */
  652. /* Start with 0 to also program the logical MAC address. */
  653. for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
  654. /* Set exact match address i on HW. */
  655. OutAddr = (SK_U16 *)&pAPort->Exact[i].a[0];
  656. XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
  657. }
  658. /* Clear other permanent exact match addresses on HW. */
  659. if (pAPort->NextExactMatchRlmt <= SK_ADDR_LAST_MATCH_RLMT) {
  660. SkXmClrExactAddr(
  661. pAC,
  662. IoC,
  663. PortNumber,
  664. pAPort->NextExactMatchRlmt,
  665. SK_ADDR_LAST_MATCH_RLMT);
  666. }
  667. for (i = pAPort->FirstExactMatchDrv; i < pAPort->NextExactMatchDrv; i++) {
  668. OutAddr = (SK_U16 *)&pAPort->Exact[i].a[0];
  669. XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
  670. }
  671. /* Clear other non-permanent exact match addresses on HW. */
  672. if (pAPort->NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
  673. SkXmClrExactAddr(
  674. pAC,
  675. IoC,
  676. PortNumber,
  677. pAPort->NextExactMatchDrv,
  678. SK_ADDR_LAST_MATCH_DRV);
  679. }
  680. for (Inexact = 0, i = 0; i < 8; i++) {
  681. Inexact |= pAPort->InexactFilter.Bytes[i];
  682. }
  683. if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
  684. /* Set all bits in 64-bit hash register. */
  685. XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
  686. /* Set bit 15 in mode register. */
  687. XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
  688. LoMode |= XM_MD_ENA_HSH;
  689. XM_OUT16(IoC, PortNumber, XM_MODE, LoMode);
  690. }
  691. else if (Inexact != 0) {
  692. /* Set 64-bit hash register to InexactFilter. */
  693. XM_OUTHASH(IoC, PortNumber, XM_HSM, &pAPort->InexactFilter.Bytes[0]);
  694. /* Set bit 15 in mode register. */
  695. XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
  696. LoMode |= XM_MD_ENA_HSH;
  697. XM_OUT16(IoC, PortNumber, XM_MODE, LoMode);
  698. }
  699. else {
  700. /* Clear bit 15 in mode register. */
  701. XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
  702. LoMode &= ~XM_MD_ENA_HSH;
  703. XM_OUT16(IoC, PortNumber, XM_MODE, LoMode);
  704. }
  705. if (pAPort->PromMode != SK_PROM_MODE_NONE) {
  706. (void)SkAddrPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
  707. }
  708. /* Set port's current MAC address. */
  709. OutAddr = (SK_U16 *)&pAPort->CurrentMacAddress.a[0];
  710. XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
  711. #ifdef xDEBUG
  712. for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
  713. SK_U8 InAddr8[6];
  714. SK_U16 *InAddr;
  715. /* Get exact match address i from port PortNumber. */
  716. InAddr = (SK_U16 *)&InAddr8[0];
  717. XM_INADDR(IoC, PortNumber, XM_EXM(i), InAddr);
  718. SK_DBG_MSG(
  719. pAC,
  720. SK_DBGMOD_ADDR,
  721. SK_DBGCAT_CTRL,
  722. ("MC address %d on Port %u: %02x %02x %02x %02x %02x %02x --  %02x %02x %02x %02x %02x %02x.n",
  723. i,
  724. PortNumber,
  725. InAddr8[0],
  726. InAddr8[1],
  727. InAddr8[2],
  728. InAddr8[3],
  729. InAddr8[4],
  730. InAddr8[5],
  731. pAPort->Exact[i].a[0],
  732. pAPort->Exact[i].a[1],
  733. pAPort->Exact[i].a[2],
  734. pAPort->Exact[i].a[3],
  735. pAPort->Exact[i].a[4],
  736. pAPort->Exact[i].a[5]))
  737. }
  738. #endif /* DEBUG */
  739. /* Determine return value. */
  740. if (Inexact == 0 && pAPort->PromMode == 0) {
  741. return (SK_MC_FILTERING_EXACT);
  742. }
  743. else {
  744. return (SK_MC_FILTERING_INEXACT);
  745. }
  746. } /* SkAddrMcUpdate */
  747. /******************************************************************************
  748.  *
  749.  * SkAddrOverride - override a port's MAC address
  750.  *
  751.  * Description:
  752.  * This routine overrides the MAC address of one port.
  753.  *
  754.  * Context:
  755.  * runtime, pageable
  756.  * may be called after SK_INIT_IO
  757.  *
  758.  * Returns:
  759.  * SK_ADDR_SUCCESS if successful.
  760.  * SK_ADDR_DUPLICATE_ADDRESS if duplicate MAC address.
  761.  * SK_ADDR_MULTICAST_ADDRESS if multicast or broadcast address.
  762.  * SK_ADDR_TOO_EARLY if SK_INIT_IO was not executed before.
  763.  */
  764. int SkAddrOverride(
  765. SK_AC *pAC, /* adapter context */
  766. SK_IOC IoC, /* I/O context */
  767. SK_U32 PortNumber, /* Port Number */
  768. SK_MAC_ADDR *pNewAddr, /* new MAC address */
  769. int Flags) /* logical/physical MAC address */
  770. {
  771. SK_EVPARA Para;
  772. SK_U32 NetNumber;
  773. SK_U32 i;
  774. SK_U16 *OutAddr;
  775. NetNumber = pAC->Rlmt.Port[PortNumber].Net->NetNumber;
  776. if (PortNumber >= (SK_U32)pAC->GIni.GIMacsFound) {
  777. return (SK_ADDR_ILLEGAL_PORT);
  778. }
  779. if (pNewAddr != NULL && (pNewAddr->a[0] & SK_MC_BIT) != 0) {
  780. return (SK_ADDR_MULTICAST_ADDRESS);
  781. }
  782. if (!pAC->Addr.Net[NetNumber].CurrentMacAddressSet) {
  783. return (SK_ADDR_TOO_EARLY);
  784. }
  785. if (Flags & SK_ADDR_SET_LOGICAL) { /* Activate logical MAC address. */
  786. /* Parameter *pNewAddr is ignored. */
  787. for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
  788. if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
  789. return (SK_ADDR_TOO_EARLY);
  790. }
  791. }
  792. /* Set PortNumber to number of net's active port. */
  793. PortNumber = pAC->Rlmt.Net[NetNumber].
  794. Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
  795. pAC->Addr.Port[PortNumber].Exact[0] =
  796. pAC->Addr.Net[NetNumber].CurrentMacAddress;
  797. /* Write address to first exact match entry of active port. */
  798. (void)SkAddrMcUpdate(pAC, IoC, PortNumber);
  799. }
  800. else if (Flags & SK_ADDR_CLEAR_LOGICAL) {
  801. /* Deactivate logical MAC address. */
  802. /* Parameter *pNewAddr is ignored. */
  803. for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
  804. if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
  805. return (SK_ADDR_TOO_EARLY);
  806. }
  807. }
  808. /* Set PortNumber to number of net's active port. */
  809. PortNumber = pAC->Rlmt.Net[NetNumber].
  810. Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
  811. for (i = 0; i < SK_MAC_ADDR_LEN; i++ ) {
  812. pAC->Addr.Port[PortNumber].Exact[0].a[i] = 0;
  813. }
  814. /* Write address to first exact match entry of active port. */
  815. (void)SkAddrMcUpdate(pAC, IoC, PortNumber);
  816. }
  817. else if (Flags & SK_ADDR_PHYSICAL_ADDRESS) { /* Physical MAC address. */
  818. if (SK_ADDR_EQUAL(pNewAddr->a,
  819. pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
  820. return (SK_ADDR_DUPLICATE_ADDRESS);
  821. }
  822. for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
  823. if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
  824. return (SK_ADDR_TOO_EARLY);
  825. }
  826. if (SK_ADDR_EQUAL(pNewAddr->a,
  827. pAC->Addr.Port[i].CurrentMacAddress.a)) {
  828. if (i == PortNumber) {
  829. return (SK_ADDR_SUCCESS);
  830. }
  831. else {
  832. return (SK_ADDR_DUPLICATE_ADDRESS);
  833. }
  834. }
  835. }
  836. pAC->Addr.Port[PortNumber].PreviousMacAddress =
  837. pAC->Addr.Port[PortNumber].CurrentMacAddress;
  838. pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
  839. /* Change port's address. */
  840. OutAddr = (SK_U16 *)pNewAddr;
  841. XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
  842. /* Report address change to RLMT. */
  843. Para.Para32[0] = PortNumber;
  844. Para.Para32[0] = -1;
  845. SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
  846. }
  847. else { /* Logical MAC address. */
  848. if (SK_ADDR_EQUAL(pNewAddr->a,
  849. pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
  850. return (SK_ADDR_SUCCESS);
  851. }
  852. for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
  853. if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
  854. return (SK_ADDR_TOO_EARLY);
  855. }
  856. if (SK_ADDR_EQUAL(pNewAddr->a,
  857. pAC->Addr.Port[i].CurrentMacAddress.a)) {
  858. return (SK_ADDR_DUPLICATE_ADDRESS);
  859. }
  860. }
  861. /* Set PortNumber to number of net's active port. */
  862. PortNumber = pAC->Rlmt.Net[NetNumber].
  863. Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
  864. pAC->Addr.Net[NetNumber].CurrentMacAddress = *pNewAddr;
  865. pAC->Addr.Port[PortNumber].Exact[0] = *pNewAddr;
  866. #ifdef DEBUG
  867. SK_DBG_MSG(
  868. pAC,
  869. SK_DBGMOD_ADDR,
  870. SK_DBGCAT_CTRL,
  871. ("Permanent MAC Address: %02X %02X %02X %02X %02X %02Xn",
  872. pAC->Addr.Net[NetNumber].PermanentMacAddress.a[0],
  873. pAC->Addr.Net[NetNumber].PermanentMacAddress.a[1],
  874. pAC->Addr.Net[NetNumber].PermanentMacAddress.a[2],
  875. pAC->Addr.Net[NetNumber].PermanentMacAddress.a[3],
  876. pAC->Addr.Net[NetNumber].PermanentMacAddress.a[4],
  877. pAC->Addr.Net[NetNumber].PermanentMacAddress.a[5]))
  878. SK_DBG_MSG(
  879. pAC,
  880. SK_DBGMOD_ADDR,
  881. SK_DBGCAT_CTRL,
  882. ("New logical MAC Address: %02X %02X %02X %02X %02X %02Xn",
  883. pAC->Addr.Net[NetNumber].CurrentMacAddress.a[0],
  884. pAC->Addr.Net[NetNumber].CurrentMacAddress.a[1],
  885. pAC->Addr.Net[NetNumber].CurrentMacAddress.a[2],
  886. pAC->Addr.Net[NetNumber].CurrentMacAddress.a[3],
  887. pAC->Addr.Net[NetNumber].CurrentMacAddress.a[4],
  888. pAC->Addr.Net[NetNumber].CurrentMacAddress.a[5]))
  889. #endif /* DEBUG */
  890. /* Write address to first exact match entry of active port. */
  891. (void)SkAddrMcUpdate(pAC, IoC, PortNumber);
  892. }
  893. return (SK_ADDR_SUCCESS);
  894. } /* SkAddrOverride */
  895. /******************************************************************************
  896.  *
  897.  * SkAddrPromiscuousChange - set promiscuous mode for given port
  898.  *
  899.  * Description:
  900.  * This routine manages promiscuous mode:
  901.  * - none
  902.  * - all LLC frames
  903.  * - all MC frames
  904.  *
  905.  * Context:
  906.  * runtime, pageable
  907.  * may be called after SK_INIT_IO
  908.  *
  909.  * Returns:
  910.  * SK_ADDR_SUCCESS
  911.  * SK_ADDR_ILLEGAL_PORT
  912.  */
  913. int SkAddrPromiscuousChange(
  914. SK_AC *pAC, /* adapter context */
  915. SK_IOC IoC, /* I/O context */
  916. SK_U32 PortNumber, /* port whose promiscuous mode changes */
  917. int NewPromMode) /* new promiscuous mode */
  918. {
  919. int i;
  920. SK_BOOL InexactModeBit;
  921. SK_U8 Inexact;
  922. SK_U8 HwInexact;
  923. SK_FILTER64 HwInexactFilter;
  924. SK_U16 LoMode; /* Lower 16 bits of XMAC Mode Register. */
  925. int CurPromMode = SK_PROM_MODE_NONE;
  926. if (PortNumber >= (SK_U32)pAC->GIni.GIMacsFound) {
  927. return (SK_ADDR_ILLEGAL_PORT);
  928. }
  929. /* Read CurPromMode from Hardware. */
  930. XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
  931. if (LoMode & XM_MD_ENA_PROM) {
  932. CurPromMode |= SK_PROM_MODE_LLC;
  933. }
  934. for (Inexact = 0xFF, i = 0; i < 8; i++) {
  935. Inexact &= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
  936. }
  937. if (Inexact == 0xFF) {
  938. CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
  939. }
  940. else {
  941. /* Read InexactModeBit (bit 15 in mode register). */
  942. XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
  943. InexactModeBit = (LoMode & XM_MD_ENA_HSH) != 0;
  944. /* Read 64-bit hash register from HW. */
  945. XM_INHASH(IoC, PortNumber, XM_HSM, &HwInexactFilter.Bytes[0]);
  946. for (HwInexact = 0xFF, i = 0; i < 8; i++) {
  947. HwInexact &= HwInexactFilter.Bytes[i];
  948. }
  949. if (InexactModeBit && (HwInexact == 0xFF)) {
  950. CurPromMode |= SK_PROM_MODE_ALL_MC;
  951. }
  952. }
  953. pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
  954. if (NewPromMode == CurPromMode) {
  955. return (SK_ADDR_SUCCESS);
  956. }
  957. if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
  958. !(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC. */
  959. /* Set all bits in 64-bit hash register. */
  960. XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
  961. /* Set bit 15 in mode register. */
  962. XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
  963. LoMode |= XM_MD_ENA_HSH;
  964. XM_OUT16(IoC, PortNumber, XM_MODE, LoMode);
  965. }
  966. else if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
  967. !(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm MC. */
  968. for (Inexact = 0, i = 0; i < 8; i++) {
  969. Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
  970. }
  971. if (Inexact == 0) {
  972. /* Clear bit 15 in mode register. */
  973. XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
  974. LoMode &= ~XM_MD_ENA_HSH;
  975. XM_OUT16(IoC, PortNumber, XM_MODE, LoMode);
  976. }
  977. else {
  978. /* Set 64-bit hash register to InexactFilter. */
  979. XM_OUTHASH(
  980. IoC,
  981. PortNumber,
  982. XM_HSM,
  983. &pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
  984. /* Set bit 15 in mode register. */
  985. XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
  986. LoMode |= XM_MD_ENA_HSH;
  987. XM_OUT16(IoC, PortNumber, XM_MODE, LoMode);
  988. }
  989. }
  990. if ((NewPromMode & SK_PROM_MODE_LLC) &&
  991. !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */
  992. /* Set promiscuous bit in mode register. */
  993. XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
  994. #if 0
  995. /* Receive MAC frames. */
  996. LoMode |= XM_MD_RX_MCTRL;
  997. #endif /* 0 */
  998. LoMode |= XM_MD_ENA_PROM;
  999. XM_OUT16(IoC, PortNumber, XM_MODE, LoMode);
  1000. }
  1001. else if ((CurPromMode & SK_PROM_MODE_LLC) &&
  1002. !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC. */
  1003. /* Clear promiscuous bit in mode register. */
  1004. XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
  1005. #if 0
  1006. /* Don't receive MAC frames. */
  1007. LoMode &= ~XM_MD_RX_MCTRL;
  1008. #endif /* 0 */
  1009. LoMode &= ~XM_MD_ENA_PROM;
  1010. XM_OUT16(IoC, PortNumber, XM_MODE, LoMode);
  1011. }
  1012. return (SK_ADDR_SUCCESS);
  1013. } /* SkAddrPromiscuousChange */
  1014. /******************************************************************************
  1015.  *
  1016.  * SkAddrSwap - swap address info
  1017.  *
  1018.  * Description:
  1019.  * This routine swaps address info of two ports.
  1020.  *
  1021.  * Context:
  1022.  * runtime, pageable
  1023.  * may be called after SK_INIT_IO
  1024.  *
  1025.  * Returns:
  1026.  * SK_ADDR_SUCCESS
  1027.  * SK_ADDR_ILLEGAL_PORT
  1028.  */
  1029. int SkAddrSwap(
  1030. SK_AC *pAC, /* adapter context */
  1031. SK_IOC IoC, /* I/O context */
  1032. SK_U32 FromPortNumber, /* Port1 Index */
  1033. SK_U32 ToPortNumber) /* Port2 Index */
  1034. {
  1035. int i;
  1036. SK_U8 Byte;
  1037. SK_MAC_ADDR MacAddr;
  1038. SK_U32 DWord;
  1039. if (FromPortNumber >= (SK_U32)pAC->GIni.GIMacsFound) {
  1040. return (SK_ADDR_ILLEGAL_PORT);
  1041. }
  1042. if (ToPortNumber >= (SK_U32)pAC->GIni.GIMacsFound) {
  1043. return (SK_ADDR_ILLEGAL_PORT);
  1044. }
  1045. if (pAC->Rlmt.Port[FromPortNumber].Net != pAC->Rlmt.Port[ToPortNumber].Net) {
  1046. return (SK_ADDR_ILLEGAL_PORT);
  1047. }
  1048. /*
  1049.  * Swap
  1050.  * - Exact Match Entries
  1051.  * - FirstExactMatchRlmt;
  1052.  * - NextExactMatchRlmt;
  1053.  * - FirstExactMatchDrv;
  1054.  * - NextExactMatchDrv;
  1055.  * - 64-bit filter
  1056.  * - Promiscuous Mode
  1057.  * of ports.
  1058.  */
  1059. for (i = 0; i < SK_ADDR_EXACT_MATCHES; i++) {
  1060. MacAddr = pAC->Addr.Port[FromPortNumber].Exact[i];
  1061. pAC->Addr.Port[FromPortNumber].Exact[i] =
  1062. pAC->Addr.Port[ToPortNumber].Exact[i];
  1063. pAC->Addr.Port[ToPortNumber].Exact[i] = MacAddr;
  1064. }
  1065. for (i = 0; i < 8; i++) {
  1066. Byte = pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i];
  1067. pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i] =
  1068. pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i];
  1069. pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i] = Byte;
  1070. }
  1071. i = pAC->Addr.Port[FromPortNumber].PromMode;
  1072. pAC->Addr.Port[FromPortNumber].PromMode = pAC->Addr.Port[ToPortNumber].PromMode;
  1073. pAC->Addr.Port[ToPortNumber].PromMode = i;
  1074. DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt;
  1075. pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt =
  1076. pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt;
  1077. pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt = DWord;
  1078. DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt;
  1079. pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt =
  1080. pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt;
  1081. pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt = DWord;
  1082. DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv;
  1083. pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv =
  1084. pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv;
  1085. pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv = DWord;
  1086. DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchDrv;
  1087. pAC->Addr.Port[FromPortNumber].NextExactMatchDrv =
  1088. pAC->Addr.Port[ToPortNumber].NextExactMatchDrv;
  1089. pAC->Addr.Port[ToPortNumber].NextExactMatchDrv = DWord;
  1090. /* CAUTION: Solution works if only ports of one adapter are in use. */
  1091. for (i = 0; (SK_U32)i < pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].
  1092. Net->NetNumber].NumPorts; i++) {
  1093. if (pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
  1094. Port[i]->PortNumber == ToPortNumber) {
  1095. pAC->Addr.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
  1096. ActivePort = i;
  1097. /* 20001207 RA: Was "ToPortNumber;". */
  1098. }
  1099. }
  1100. (void)SkAddrMcUpdate(pAC, IoC, FromPortNumber);
  1101. (void)SkAddrMcUpdate(pAC, IoC, ToPortNumber);
  1102. return (SK_ADDR_SUCCESS);
  1103. } /* SkAddrSwap */
  1104. #ifdef __cplusplus
  1105. }
  1106. #endif /* __cplusplus */