skaddr.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:34k
源码类别:

Linux/Unix编程

开发平台:

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 HASH_BITS 6 /* #bits in hash */
  193. #define SK_MC_BIT 0x01
  194. /* Error numbers and messages. */
  195. #define SKERR_ADDR_E001 (SK_ERRBASE_ADDR + 0)
  196. #define SKERR_ADDR_E001MSG "Bad Flags."
  197. #define SKERR_ADDR_E002 (SKERR_ADDR_E001 + 1)
  198. #define SKERR_ADDR_E002MSG "New Error."
  199. /* typedefs *******************************************************************/
  200. /* None. */
  201. /* global variables ***********************************************************/
  202. /* 64-bit hash values with all bits set. */
  203. SK_U16 OnesHash[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
  204. /* local variables ************************************************************/
  205. #ifdef DEBUG
  206. static int Next0[SK_MAX_MACS] = {0, 0};
  207. #endif /* DEBUG */
  208. /* functions ******************************************************************/
  209. /******************************************************************************
  210.  *
  211.  * SkAddrInit - initialize data, set state to init
  212.  *
  213.  * Description:
  214.  *
  215.  * SK_INIT_DATA
  216.  * ============
  217.  *
  218.  * This routine clears the multicast tables and resets promiscuous mode.
  219.  * Some entries are reserved for the "logical MAC address", the
  220.  * SK-RLMT multicast address, and the BPDU multicast address.
  221.  *
  222.  *
  223.  * SK_INIT_IO
  224.  * ==========
  225.  *
  226.  * All permanent MAC addresses are read from EPROM.
  227.  * If the current MAC addresses are not already set in software,
  228.  * they are set to the values of the permanent addresses.
  229.  * The current addresses are written to the corresponding XMAC.
  230.  *
  231.  *
  232.  * SK_INIT_RUN
  233.  * ===========
  234.  *
  235.  * Nothing.
  236.  *
  237.  * Context:
  238.  * init, pageable
  239.  *
  240.  * Returns:
  241.  * SK_ADDR_SUCCESS
  242.  */
  243. int SkAddrInit(
  244. SK_AC *pAC, /* the adapter context */
  245. SK_IOC IoC, /* I/O context */
  246. int Level) /* initialization level */
  247. {
  248. int j;
  249. SK_U32 i;
  250. SK_U8 *InAddr;
  251. SK_U16 *OutAddr;
  252. SK_ADDR_PORT *pAPort;
  253. switch (Level) {
  254. case SK_INIT_DATA:
  255. SK_MEMSET((char *)&pAC->Addr, 0, sizeof(SK_ADDR));
  256. for (i = 0; i < SK_MAX_MACS; i++) {
  257. pAPort = &pAC->Addr.Port[i];
  258. pAPort->PromMode = SK_PROM_MODE_NONE;
  259. pAPort->FirstExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
  260. pAPort->FirstExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
  261. pAPort->NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
  262. pAPort->NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
  263. #if 0
  264. /* Don't do this here ... */
  265. /* Reset Promiscuous mode. */
  266. (void)SkAddrPromiscuousChange(
  267. pAC,
  268. IoC,
  269. i,
  270. SK_PROM_MODE_NONE);
  271. #endif /* 0 */
  272. }
  273. #ifdef DEBUG
  274. for (i = 0; i < SK_MAX_MACS; i++) {
  275. if (pAC->Addr.Port[i].NextExactMatchRlmt <
  276. SK_ADDR_FIRST_MATCH_RLMT) {
  277. Next0[i] |= 4;
  278. }
  279. }
  280. #endif /* DEBUG */
  281. /* pAC->Addr.InitDone = SK_INIT_DATA; */
  282. break;
  283. case SK_INIT_IO:
  284. for (i = 0; i < SK_MAX_NETS; i++) {
  285. pAC->Addr.Net[i].ActivePort = pAC->Rlmt.Net[i].ActivePort;
  286. }
  287. #ifdef DEBUG
  288. for (i = 0; i < SK_MAX_MACS; i++) {
  289. if (pAC->Addr.Port[i].NextExactMatchRlmt <
  290. SK_ADDR_FIRST_MATCH_RLMT) {
  291. Next0[i] |= 8;
  292. }
  293. }
  294. #endif /* DEBUG */
  295. /* Read permanent logical MAC address from Control Register File. */
  296. for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
  297. InAddr = (SK_U8 *)&pAC->Addr.Net[0].PermanentMacAddress.a[j];
  298. SK_IN8(IoC, B2_MAC_1 + j, InAddr);
  299. }
  300. if (!pAC->Addr.Net[0].CurrentMacAddressSet) {
  301. /* Set the current logical MAC address to the permanent one. */
  302. pAC->Addr.Net[0].CurrentMacAddress =
  303. pAC->Addr.Net[0].PermanentMacAddress;
  304. pAC->Addr.Net[0].CurrentMacAddressSet = SK_TRUE;
  305. }
  306. /* Set the current logical MAC address. */
  307. pAC->Addr.Port[pAC->Addr.Net[0].ActivePort].Exact[0] =
  308. pAC->Addr.Net[0].CurrentMacAddress;
  309. #if SK_MAX_NETS > 1
  310. /* Set logical MAC address for net 2 to (log | 3). */
  311. if (!pAC->Addr.Net[1].CurrentMacAddressSet) {
  312. pAC->Addr.Net[1].PermanentMacAddress =
  313. pAC->Addr.Net[0].PermanentMacAddress;
  314. pAC->Addr.Net[1].PermanentMacAddress.a[5] |= 3;
  315. /* Set the current logical MAC address to the permanent one. */
  316. pAC->Addr.Net[1].CurrentMacAddress =
  317. pAC->Addr.Net[1].PermanentMacAddress;
  318. pAC->Addr.Net[1].CurrentMacAddressSet = SK_TRUE;
  319. }
  320. #endif /* SK_MAX_NETS > 1 */
  321. #ifdef xDEBUG
  322. SK_DBG_MSG(
  323. pAC,
  324. SK_DBGMOD_ADDR,
  325. SK_DBGCAT_INIT,
  326. ("Permanent MAC Address: %02X %02X %02X %02X %02X %02Xn",
  327. pAC->Addr.PermanentMacAddress.a[0],
  328. pAC->Addr.PermanentMacAddress.a[1],
  329. pAC->Addr.PermanentMacAddress.a[2],
  330. pAC->Addr.PermanentMacAddress.a[3],
  331. pAC->Addr.PermanentMacAddress.a[4],
  332. pAC->Addr.PermanentMacAddress.a[5]))
  333. SK_DBG_MSG(
  334. pAC,
  335. SK_DBGMOD_ADDR,
  336. SK_DBGCAT_INIT,
  337. ("Logical MAC Address: %02X %02X %02X %02X %02X %02Xn",
  338. pAC->Addr.CurrentMacAddress.a[0],
  339. pAC->Addr.CurrentMacAddress.a[1],
  340. pAC->Addr.CurrentMacAddress.a[2],
  341. pAC->Addr.CurrentMacAddress.a[3],
  342. pAC->Addr.CurrentMacAddress.a[4],
  343. pAC->Addr.CurrentMacAddress.a[5]))
  344. #endif /* DEBUG */
  345. #if 0
  346. /* Don't do this here ... */
  347. (void)SkAddrMcUpdate(pAC, IoC, pAC->Addr.ActivePort);
  348. #endif /* 0 */
  349. for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
  350. pAPort = &pAC->Addr.Port[i];
  351. /* Read permanent port addresses from Control Register File. */
  352. for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
  353. InAddr = (SK_U8 *)&pAPort->PermanentMacAddress.a[j];
  354. SK_IN8(IoC, B2_MAC_2 + 8 * i + j, InAddr);
  355. }
  356. if (!pAPort->CurrentMacAddressSet) {
  357. /*
  358.  * Set the current and previous physical MAC address
  359.  * of this port to its permanent MAC address.
  360.  */
  361. pAPort->CurrentMacAddress = pAPort->PermanentMacAddress;
  362. pAPort->PreviousMacAddress = pAPort->PermanentMacAddress;
  363. pAPort->CurrentMacAddressSet = SK_TRUE;
  364. }
  365. /* Set port's current MAC addresses. */
  366. OutAddr = (SK_U16 *)&pAPort->CurrentMacAddress.a[0];
  367. XM_OUTADDR(IoC, i, XM_SA, OutAddr);
  368. #ifdef xDEBUG
  369. SK_DBG_MSG(
  370. pAC,
  371. SK_DBGMOD_ADDR,
  372. SK_DBGCAT_INIT,
  373. ("Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02Xn",
  374. pAPort->PermanentMacAddress.a[0],
  375. pAPort->PermanentMacAddress.a[1],
  376. pAPort->PermanentMacAddress.a[2],
  377. pAPort->PermanentMacAddress.a[3],
  378. pAPort->PermanentMacAddress.a[4],
  379. pAPort->PermanentMacAddress.a[5]))
  380. SK_DBG_MSG(
  381. pAC,
  382. SK_DBGMOD_ADDR,
  383. SK_DBGCAT_INIT,
  384. ("Phsical MAC Address: %02X %02X %02X %02X %02X %02Xn",
  385. pAPort->CurrentMacAddress.a[0],
  386. pAPort->CurrentMacAddress.a[1],
  387. pAPort->CurrentMacAddress.a[2],
  388. pAPort->CurrentMacAddress.a[3],
  389. pAPort->CurrentMacAddress.a[4],
  390. pAPort->CurrentMacAddress.a[5]))
  391. #endif /* DEBUG */
  392. }
  393. /* pAC->Addr.InitDone = SK_INIT_IO; */
  394. break;
  395. case SK_INIT_RUN:
  396. #ifdef DEBUG
  397. for (i = 0; i < SK_MAX_MACS; i++) {
  398. if (pAC->Addr.Port[i].NextExactMatchRlmt <
  399. SK_ADDR_FIRST_MATCH_RLMT) {
  400. Next0[i] |= 16;
  401. }
  402. }
  403. #endif /* DEBUG */
  404. /* pAC->Addr.InitDone = SK_INIT_RUN; */
  405. break;
  406. default: /* error */
  407. break;
  408. }
  409. return (SK_ADDR_SUCCESS);
  410. } /* SkAddrInit */
  411. /******************************************************************************
  412.  *
  413.  * SkAddrMcClear - clear the multicast table
  414.  *
  415.  * Description:
  416.  * This routine clears the multicast table
  417.  * (either entry 2 or entries 3-16 and InexactFilter) of the given port.
  418.  * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
  419.  * immediately.
  420.  *
  421.  * Context:
  422.  * runtime, pageable
  423.  * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
  424.  * may be called after SK_INIT_IO without limitation
  425.  *
  426.  * Returns:
  427.  * SK_ADDR_SUCCESS
  428.  * SK_ADDR_ILLEGAL_PORT
  429.  */
  430. int SkAddrMcClear(
  431. SK_AC *pAC, /* adapter context */
  432. SK_IOC IoC, /* I/O context */
  433. SK_U32 PortNumber, /* Index of affected port */
  434. int Flags) /* permanent/non-perm, sw-only */
  435. {
  436. int i;
  437. if (PortNumber >= (SK_U32)pAC->GIni.GIMacsFound) {
  438. return (SK_ADDR_ILLEGAL_PORT);
  439. }
  440. if (Flags & SK_ADDR_PERMANENT) {
  441. /* Clear RLMT multicast addresses. */
  442. pAC->Addr.Port[PortNumber].NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
  443. }
  444. else { /* not permanent => DRV */
  445. /* Clear InexactFilter. */
  446. for (i = 0; i < 8; i++) {
  447. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
  448. }
  449. /* Clear DRV multicast addresses. */
  450. pAC->Addr.Port[PortNumber].NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
  451. }
  452. if (!(Flags & SK_MC_SW_ONLY)) {
  453. (void)SkAddrMcUpdate(pAC, IoC, PortNumber);
  454. }
  455. return (SK_ADDR_SUCCESS);
  456. } /* SkAddrMcClear */
  457. #ifndef SK_ADDR_CHEAT
  458. /******************************************************************************
  459.  *
  460.  * SkCrc32McHash - hash multicast address
  461.  *
  462.  * Description:
  463.  * This routine computes the hash value for a multicast address.
  464.  *
  465.  * Notes:
  466.  * The code was adapted from the XaQti data sheet.
  467.  *
  468.  * Context:
  469.  * runtime, pageable
  470.  *
  471.  * Returns:
  472.  * Hash value of multicast address.
  473.  */
  474. unsigned SkCrc32McHash(
  475. unsigned char *pMc) /* Multicast address */
  476. {
  477. u32 Crc;
  478. Crc = ether_crc_le(SK_MAC_ADDR_LEN, pMc);
  479. return (Crc & ((1 << HASH_BITS) - 1));
  480. } /* SkCrc32McHash */
  481. #endif /* not SK_ADDR_CHEAT */
  482. /******************************************************************************
  483.  *
  484.  * SkAddrMcAdd - add a multicast address to a port
  485.  *
  486.  * Description:
  487.  * This routine enables reception for a given address on the given port.
  488.  *
  489.  * Notes:
  490.  * The return code is only valid for SK_PROM_MODE_NONE.
  491.  *
  492.  * In the current version, only RLMT may add addresses to the non-active
  493.  * port.
  494.  *
  495.  * The multicast bit is only checked if there are no free exact match
  496.  * entries.
  497.  *
  498.  * Context:
  499.  * runtime, pageable
  500.  * may be called after SK_INIT_DATA
  501.  *
  502.  * Returns:
  503.  * SK_MC_FILTERING_EXACT
  504.  * SK_MC_FILTERING_INEXACT
  505.  * SK_MC_ILLEGAL_ADDRESS
  506.  * SK_MC_ILLEGAL_PORT
  507.  * SK_MC_RLMT_OVERFLOW
  508.  */
  509. int SkAddrMcAdd(
  510. SK_AC *pAC, /* adapter context */
  511. SK_IOC IoC, /* I/O context */
  512. SK_U32 PortNumber, /* Port Number */
  513. SK_MAC_ADDR *pMc, /* multicast address to be added */
  514. int Flags) /* permanent/non-permanent */
  515. {
  516. int i;
  517. SK_U8 Inexact;
  518. #ifndef SK_ADDR_CHEAT
  519. unsigned HashBit;
  520. #endif /* !defined(SK_ADDR_CHEAT) */
  521. if (PortNumber >= (SK_U32)pAC->GIni.GIMacsFound) {
  522. return (SK_ADDR_ILLEGAL_PORT);
  523. }
  524. if (Flags & SK_ADDR_PERMANENT) {
  525. #ifdef DEBUG
  526. if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt <
  527. SK_ADDR_FIRST_MATCH_RLMT) {
  528. Next0[PortNumber] |= 1;
  529. return (SK_MC_RLMT_OVERFLOW);
  530. }
  531. #endif /* DEBUG */
  532. if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt >
  533. SK_ADDR_LAST_MATCH_RLMT) {
  534. return (SK_MC_RLMT_OVERFLOW);
  535. }
  536. /* Set an RLMT multicast address. */
  537. pAC->Addr.Port[PortNumber].Exact[
  538. pAC->Addr.Port[PortNumber].NextExactMatchRlmt++] = *pMc;
  539. return (SK_MC_FILTERING_EXACT);
  540. }
  541. #if 0
  542. /* Not PERMANENT => DRV */
  543. if (PortNumber != pAC->Addr.ActivePort) {
  544. /* Only RLMT is allowed to do this. */
  545. return (SK_MC_ILLEGAL_PORT);
  546. }
  547. #endif /* 0 */
  548. #ifdef DEBUG
  549. if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <
  550. SK_ADDR_FIRST_MATCH_DRV) {
  551. Next0[PortNumber] |= 2;
  552. return (SK_MC_RLMT_OVERFLOW);
  553. }
  554. #endif /* DEBUG */
  555. if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
  556. /* Set exact match entry. */
  557. pAC->Addr.Port[PortNumber].Exact[
  558. pAC->Addr.Port[PortNumber].NextExactMatchDrv++] = *pMc;
  559. /* Clear InexactFilter. */
  560. for (i = 0; i < 8; i++) {
  561. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
  562. }
  563. }
  564. else {
  565. if (!(pMc->a[0] & SK_MC_BIT)) {
  566. /*
  567.  * Hashing only possible with
  568.  * multicast addresses.
  569.  */
  570. return (SK_MC_ILLEGAL_ADDRESS);
  571. }
  572. #ifndef SK_ADDR_CHEAT
  573. /* Compute hash value of address. */
  574. HashBit = 63 - SkCrc32McHash(&pMc->a[0]);
  575. /* Add bit to InexactFilter. */
  576. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[HashBit / 8] |=
  577. 1 << (HashBit % 8);
  578. #else /* SK_ADDR_CHEAT */
  579. /* Set all bits in InexactFilter. */
  580. for (i = 0; i < 8; i++) {
  581. pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
  582. }
  583. #endif /* SK_ADDR_CHEAT */
  584. }
  585. for (Inexact = 0, i = 0; i < 8; i++) {
  586. Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
  587. }
  588. if (Inexact == 0 && pAC->Addr.Port[PortNumber].PromMode == 0) {
  589. return (SK_MC_FILTERING_EXACT);
  590. }
  591. else {
  592. return (SK_MC_FILTERING_INEXACT);
  593. }
  594. } /* SkAddrMcAdd */
  595. /******************************************************************************
  596.  *
  597.  * SkAddrMcUpdate - update the HW MC address table and set the MAC address
  598.  *
  599.  * Description:
  600.  * This routine enables reception of the addresses contained in a local
  601.  * table for a given port.
  602.  * It also programs the port's current physical MAC address.
  603.  *
  604.  * Notes:
  605.  * The return code is only valid for SK_PROM_MODE_NONE.
  606.  *
  607.  * Context:
  608.  * runtime, pageable
  609.  * may be called after SK_INIT_IO
  610.  *
  611.  * Returns:
  612.  * SK_MC_FILTERING_EXACT
  613.  * SK_MC_FILTERING_INEXACT
  614.  * SK_ADDR_ILLEGAL_PORT
  615.  */
  616. int SkAddrMcUpdate(
  617. SK_AC *pAC, /* adapter context */
  618. SK_IOC IoC, /* I/O context */
  619. SK_U32 PortNumber) /* Port Number */
  620. {
  621. SK_U32 i;
  622. SK_U8 Inexact;
  623. SK_U16 *OutAddr;
  624. SK_U16 LoMode; /* Lower 16 bits of XMAC Mode Reg. */
  625. SK_ADDR_PORT *pAPort;
  626. if (PortNumber >= (SK_U32)pAC->GIni.GIMacsFound) {
  627. return (SK_ADDR_ILLEGAL_PORT);
  628. }
  629. SK_DBG_MSG(
  630. pAC,
  631. SK_DBGMOD_ADDR,
  632. SK_DBGCAT_CTRL,
  633. ("SkAddrMcUpdate on Port %u.n", PortNumber))
  634. pAPort = &pAC->Addr.Port[PortNumber];
  635. #ifdef DEBUG
  636. SK_DBG_MSG(
  637. pAC,
  638. SK_DBGMOD_ADDR,
  639. SK_DBGCAT_CTRL,
  640. ("Next0 on Port %d: %dn", PortNumber, Next0[PortNumber]))
  641. #endif /* DEBUG */
  642. /* Start with 0 to also program the logical MAC address. */
  643. for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
  644. /* Set exact match address i on HW. */
  645. OutAddr = (SK_U16 *)&pAPort->Exact[i].a[0];
  646. XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
  647. }
  648. /* Clear other permanent exact match addresses on HW. */
  649. if (pAPort->NextExactMatchRlmt <= SK_ADDR_LAST_MATCH_RLMT) {
  650. SkXmClrExactAddr(
  651. pAC,
  652. IoC,
  653. PortNumber,
  654. pAPort->NextExactMatchRlmt,
  655. SK_ADDR_LAST_MATCH_RLMT);
  656. }
  657. for (i = pAPort->FirstExactMatchDrv; i < pAPort->NextExactMatchDrv; i++) {
  658. OutAddr = (SK_U16 *)&pAPort->Exact[i].a[0];
  659. XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
  660. }
  661. /* Clear other non-permanent exact match addresses on HW. */
  662. if (pAPort->NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
  663. SkXmClrExactAddr(
  664. pAC,
  665. IoC,
  666. PortNumber,
  667. pAPort->NextExactMatchDrv,
  668. SK_ADDR_LAST_MATCH_DRV);
  669. }
  670. for (Inexact = 0, i = 0; i < 8; i++) {
  671. Inexact |= pAPort->InexactFilter.Bytes[i];
  672. }
  673. if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
  674. /* Set all bits in 64-bit hash register. */
  675. XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
  676. /* Set bit 15 in mode register. */
  677. XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
  678. LoMode |= XM_MD_ENA_HSH;
  679. XM_OUT16(IoC, PortNumber, XM_MODE, LoMode);
  680. }
  681. else if (Inexact != 0) {
  682. /* Set 64-bit hash register to InexactFilter. */
  683. XM_OUTHASH(IoC, PortNumber, XM_HSM, &pAPort->InexactFilter.Bytes[0]);
  684. /* Set bit 15 in mode register. */
  685. XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
  686. LoMode |= XM_MD_ENA_HSH;
  687. XM_OUT16(IoC, PortNumber, XM_MODE, LoMode);
  688. }
  689. else {
  690. /* Clear bit 15 in mode register. */
  691. XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
  692. LoMode &= ~XM_MD_ENA_HSH;
  693. XM_OUT16(IoC, PortNumber, XM_MODE, LoMode);
  694. }
  695. if (pAPort->PromMode != SK_PROM_MODE_NONE) {
  696. (void)SkAddrPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
  697. }
  698. /* Set port's current MAC address. */
  699. OutAddr = (SK_U16 *)&pAPort->CurrentMacAddress.a[0];
  700. XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
  701. #ifdef xDEBUG
  702. for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
  703. SK_U8 InAddr8[6];
  704. SK_U16 *InAddr;
  705. /* Get exact match address i from port PortNumber. */
  706. InAddr = (SK_U16 *)&InAddr8[0];
  707. XM_INADDR(IoC, PortNumber, XM_EXM(i), InAddr);
  708. SK_DBG_MSG(
  709. pAC,
  710. SK_DBGMOD_ADDR,
  711. SK_DBGCAT_CTRL,
  712. ("MC address %d on Port %u: %02x %02x %02x %02x %02x %02x --  %02x %02x %02x %02x %02x %02x.n",
  713. i,
  714. PortNumber,
  715. InAddr8[0],
  716. InAddr8[1],
  717. InAddr8[2],
  718. InAddr8[3],
  719. InAddr8[4],
  720. InAddr8[5],
  721. pAPort->Exact[i].a[0],
  722. pAPort->Exact[i].a[1],
  723. pAPort->Exact[i].a[2],
  724. pAPort->Exact[i].a[3],
  725. pAPort->Exact[i].a[4],
  726. pAPort->Exact[i].a[5]))
  727. }
  728. #endif /* DEBUG */
  729. /* Determine return value. */
  730. if (Inexact == 0 && pAPort->PromMode == 0) {
  731. return (SK_MC_FILTERING_EXACT);
  732. }
  733. else {
  734. return (SK_MC_FILTERING_INEXACT);
  735. }
  736. } /* SkAddrMcUpdate */
  737. /******************************************************************************
  738.  *
  739.  * SkAddrOverride - override a port's MAC address
  740.  *
  741.  * Description:
  742.  * This routine overrides the MAC address of one port.
  743.  *
  744.  * Context:
  745.  * runtime, pageable
  746.  * may be called after SK_INIT_IO
  747.  *
  748.  * Returns:
  749.  * SK_ADDR_SUCCESS if successful.
  750.  * SK_ADDR_DUPLICATE_ADDRESS if duplicate MAC address.
  751.  * SK_ADDR_MULTICAST_ADDRESS if multicast or broadcast address.
  752.  * SK_ADDR_TOO_EARLY if SK_INIT_IO was not executed before.
  753.  */
  754. int SkAddrOverride(
  755. SK_AC *pAC, /* adapter context */
  756. SK_IOC IoC, /* I/O context */
  757. SK_U32 PortNumber, /* Port Number */
  758. SK_MAC_ADDR *pNewAddr, /* new MAC address */
  759. int Flags) /* logical/physical MAC address */
  760. {
  761. SK_EVPARA Para;
  762. SK_U32 NetNumber;
  763. SK_U32 i;
  764. SK_U16 *OutAddr;
  765. NetNumber = pAC->Rlmt.Port[PortNumber].Net->NetNumber;
  766. if (PortNumber >= (SK_U32)pAC->GIni.GIMacsFound) {
  767. return (SK_ADDR_ILLEGAL_PORT);
  768. }
  769. if (pNewAddr != NULL && (pNewAddr->a[0] & SK_MC_BIT) != 0) {
  770. return (SK_ADDR_MULTICAST_ADDRESS);
  771. }
  772. if (!pAC->Addr.Net[NetNumber].CurrentMacAddressSet) {
  773. return (SK_ADDR_TOO_EARLY);
  774. }
  775. if (Flags & SK_ADDR_SET_LOGICAL) { /* Activate logical MAC address. */
  776. /* Parameter *pNewAddr is ignored. */
  777. for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
  778. if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
  779. return (SK_ADDR_TOO_EARLY);
  780. }
  781. }
  782. /* Set PortNumber to number of net's active port. */
  783. PortNumber = pAC->Rlmt.Net[NetNumber].
  784. Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
  785. pAC->Addr.Port[PortNumber].Exact[0] =
  786. pAC->Addr.Net[NetNumber].CurrentMacAddress;
  787. /* Write address to first exact match entry of active port. */
  788. (void)SkAddrMcUpdate(pAC, IoC, PortNumber);
  789. }
  790. else if (Flags & SK_ADDR_CLEAR_LOGICAL) {
  791. /* Deactivate logical MAC address. */
  792. /* Parameter *pNewAddr is ignored. */
  793. for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
  794. if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
  795. return (SK_ADDR_TOO_EARLY);
  796. }
  797. }
  798. /* Set PortNumber to number of net's active port. */
  799. PortNumber = pAC->Rlmt.Net[NetNumber].
  800. Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
  801. for (i = 0; i < SK_MAC_ADDR_LEN; i++ ) {
  802. pAC->Addr.Port[PortNumber].Exact[0].a[i] = 0;
  803. }
  804. /* Write address to first exact match entry of active port. */
  805. (void)SkAddrMcUpdate(pAC, IoC, PortNumber);
  806. }
  807. else if (Flags & SK_ADDR_PHYSICAL_ADDRESS) { /* Physical MAC address. */
  808. if (SK_ADDR_EQUAL(pNewAddr->a,
  809. pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
  810. return (SK_ADDR_DUPLICATE_ADDRESS);
  811. }
  812. for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
  813. if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
  814. return (SK_ADDR_TOO_EARLY);
  815. }
  816. if (SK_ADDR_EQUAL(pNewAddr->a,
  817. pAC->Addr.Port[i].CurrentMacAddress.a)) {
  818. if (i == PortNumber) {
  819. return (SK_ADDR_SUCCESS);
  820. }
  821. else {
  822. return (SK_ADDR_DUPLICATE_ADDRESS);
  823. }
  824. }
  825. }
  826. pAC->Addr.Port[PortNumber].PreviousMacAddress =
  827. pAC->Addr.Port[PortNumber].CurrentMacAddress;
  828. pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
  829. /* Change port's address. */
  830. OutAddr = (SK_U16 *)pNewAddr;
  831. XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
  832. /* Report address change to RLMT. */
  833. Para.Para32[0] = PortNumber;
  834. Para.Para32[0] = -1;
  835. SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
  836. }
  837. else { /* Logical MAC address. */
  838. if (SK_ADDR_EQUAL(pNewAddr->a,
  839. pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
  840. return (SK_ADDR_SUCCESS);
  841. }
  842. for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
  843. if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
  844. return (SK_ADDR_TOO_EARLY);
  845. }
  846. if (SK_ADDR_EQUAL(pNewAddr->a,
  847. pAC->Addr.Port[i].CurrentMacAddress.a)) {
  848. return (SK_ADDR_DUPLICATE_ADDRESS);
  849. }
  850. }
  851. /* Set PortNumber to number of net's active port. */
  852. PortNumber = pAC->Rlmt.Net[NetNumber].
  853. Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
  854. pAC->Addr.Net[NetNumber].CurrentMacAddress = *pNewAddr;
  855. pAC->Addr.Port[PortNumber].Exact[0] = *pNewAddr;
  856. #ifdef DEBUG
  857. SK_DBG_MSG(
  858. pAC,
  859. SK_DBGMOD_ADDR,
  860. SK_DBGCAT_CTRL,
  861. ("Permanent MAC Address: %02X %02X %02X %02X %02X %02Xn",
  862. pAC->Addr.Net[NetNumber].PermanentMacAddress.a[0],
  863. pAC->Addr.Net[NetNumber].PermanentMacAddress.a[1],
  864. pAC->Addr.Net[NetNumber].PermanentMacAddress.a[2],
  865. pAC->Addr.Net[NetNumber].PermanentMacAddress.a[3],
  866. pAC->Addr.Net[NetNumber].PermanentMacAddress.a[4],
  867. pAC->Addr.Net[NetNumber].PermanentMacAddress.a[5]))
  868. SK_DBG_MSG(
  869. pAC,
  870. SK_DBGMOD_ADDR,
  871. SK_DBGCAT_CTRL,
  872. ("New logical MAC Address: %02X %02X %02X %02X %02X %02Xn",
  873. pAC->Addr.Net[NetNumber].CurrentMacAddress.a[0],
  874. pAC->Addr.Net[NetNumber].CurrentMacAddress.a[1],
  875. pAC->Addr.Net[NetNumber].CurrentMacAddress.a[2],
  876. pAC->Addr.Net[NetNumber].CurrentMacAddress.a[3],
  877. pAC->Addr.Net[NetNumber].CurrentMacAddress.a[4],
  878. pAC->Addr.Net[NetNumber].CurrentMacAddress.a[5]))
  879. #endif /* DEBUG */
  880. /* Write address to first exact match entry of active port. */
  881. (void)SkAddrMcUpdate(pAC, IoC, PortNumber);
  882. }
  883. return (SK_ADDR_SUCCESS);
  884. } /* SkAddrOverride */
  885. /******************************************************************************
  886.  *
  887.  * SkAddrPromiscuousChange - set promiscuous mode for given port
  888.  *
  889.  * Description:
  890.  * This routine manages promiscuous mode:
  891.  * - none
  892.  * - all LLC frames
  893.  * - all MC frames
  894.  *
  895.  * Context:
  896.  * runtime, pageable
  897.  * may be called after SK_INIT_IO
  898.  *
  899.  * Returns:
  900.  * SK_ADDR_SUCCESS
  901.  * SK_ADDR_ILLEGAL_PORT
  902.  */
  903. int SkAddrPromiscuousChange(
  904. SK_AC *pAC, /* adapter context */
  905. SK_IOC IoC, /* I/O context */
  906. SK_U32 PortNumber, /* port whose promiscuous mode changes */
  907. int NewPromMode) /* new promiscuous mode */
  908. {
  909. int i;
  910. SK_BOOL InexactModeBit;
  911. SK_U8 Inexact;
  912. SK_U8 HwInexact;
  913. SK_FILTER64 HwInexactFilter;
  914. SK_U16 LoMode; /* Lower 16 bits of XMAC Mode Register. */
  915. int CurPromMode = SK_PROM_MODE_NONE;
  916. if (PortNumber >= (SK_U32)pAC->GIni.GIMacsFound) {
  917. return (SK_ADDR_ILLEGAL_PORT);
  918. }
  919. /* Read CurPromMode from Hardware. */
  920. XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
  921. if (LoMode & XM_MD_ENA_PROM) {
  922. CurPromMode |= SK_PROM_MODE_LLC;
  923. }
  924. for (Inexact = 0xFF, i = 0; i < 8; i++) {
  925. Inexact &= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
  926. }
  927. if (Inexact == 0xFF) {
  928. CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
  929. }
  930. else {
  931. /* Read InexactModeBit (bit 15 in mode register). */
  932. XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
  933. InexactModeBit = (LoMode & XM_MD_ENA_HSH) != 0;
  934. /* Read 64-bit hash register from HW. */
  935. XM_INHASH(IoC, PortNumber, XM_HSM, &HwInexactFilter.Bytes[0]);
  936. for (HwInexact = 0xFF, i = 0; i < 8; i++) {
  937. HwInexact &= HwInexactFilter.Bytes[i];
  938. }
  939. if (InexactModeBit && (HwInexact == 0xFF)) {
  940. CurPromMode |= SK_PROM_MODE_ALL_MC;
  941. }
  942. }
  943. pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
  944. if (NewPromMode == CurPromMode) {
  945. return (SK_ADDR_SUCCESS);
  946. }
  947. if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
  948. !(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC. */
  949. /* Set all bits in 64-bit hash register. */
  950. XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
  951. /* Set bit 15 in mode register. */
  952. XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
  953. LoMode |= XM_MD_ENA_HSH;
  954. XM_OUT16(IoC, PortNumber, XM_MODE, LoMode);
  955. }
  956. else if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
  957. !(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm MC. */
  958. for (Inexact = 0, i = 0; i < 8; i++) {
  959. Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
  960. }
  961. if (Inexact == 0) {
  962. /* Clear bit 15 in mode register. */
  963. XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
  964. LoMode &= ~XM_MD_ENA_HSH;
  965. XM_OUT16(IoC, PortNumber, XM_MODE, LoMode);
  966. }
  967. else {
  968. /* Set 64-bit hash register to InexactFilter. */
  969. XM_OUTHASH(
  970. IoC,
  971. PortNumber,
  972. XM_HSM,
  973. &pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
  974. /* Set bit 15 in mode register. */
  975. XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
  976. LoMode |= XM_MD_ENA_HSH;
  977. XM_OUT16(IoC, PortNumber, XM_MODE, LoMode);
  978. }
  979. }
  980. if ((NewPromMode & SK_PROM_MODE_LLC) &&
  981. !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */
  982. /* Set promiscuous bit in mode register. */
  983. XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
  984. #if 0
  985. /* Receive MAC frames. */
  986. LoMode |= XM_MD_RX_MCTRL;
  987. #endif /* 0 */
  988. LoMode |= XM_MD_ENA_PROM;
  989. XM_OUT16(IoC, PortNumber, XM_MODE, LoMode);
  990. }
  991. else if ((CurPromMode & SK_PROM_MODE_LLC) &&
  992. !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC. */
  993. /* Clear promiscuous bit in mode register. */
  994. XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
  995. #if 0
  996. /* Don't receive MAC frames. */
  997. LoMode &= ~XM_MD_RX_MCTRL;
  998. #endif /* 0 */
  999. LoMode &= ~XM_MD_ENA_PROM;
  1000. XM_OUT16(IoC, PortNumber, XM_MODE, LoMode);
  1001. }
  1002. return (SK_ADDR_SUCCESS);
  1003. } /* SkAddrPromiscuousChange */
  1004. /******************************************************************************
  1005.  *
  1006.  * SkAddrSwap - swap address info
  1007.  *
  1008.  * Description:
  1009.  * This routine swaps address info of two ports.
  1010.  *
  1011.  * Context:
  1012.  * runtime, pageable
  1013.  * may be called after SK_INIT_IO
  1014.  *
  1015.  * Returns:
  1016.  * SK_ADDR_SUCCESS
  1017.  * SK_ADDR_ILLEGAL_PORT
  1018.  */
  1019. int SkAddrSwap(
  1020. SK_AC *pAC, /* adapter context */
  1021. SK_IOC IoC, /* I/O context */
  1022. SK_U32 FromPortNumber, /* Port1 Index */
  1023. SK_U32 ToPortNumber) /* Port2 Index */
  1024. {
  1025. int i;
  1026. SK_U8 Byte;
  1027. SK_MAC_ADDR MacAddr;
  1028. SK_U32 DWord;
  1029. if (FromPortNumber >= (SK_U32)pAC->GIni.GIMacsFound) {
  1030. return (SK_ADDR_ILLEGAL_PORT);
  1031. }
  1032. if (ToPortNumber >= (SK_U32)pAC->GIni.GIMacsFound) {
  1033. return (SK_ADDR_ILLEGAL_PORT);
  1034. }
  1035. if (pAC->Rlmt.Port[FromPortNumber].Net != pAC->Rlmt.Port[ToPortNumber].Net) {
  1036. return (SK_ADDR_ILLEGAL_PORT);
  1037. }
  1038. /*
  1039.  * Swap
  1040.  * - Exact Match Entries
  1041.  * - FirstExactMatchRlmt;
  1042.  * - NextExactMatchRlmt;
  1043.  * - FirstExactMatchDrv;
  1044.  * - NextExactMatchDrv;
  1045.  * - 64-bit filter
  1046.  * - Promiscuous Mode
  1047.  * of ports.
  1048.  */
  1049. for (i = 0; i < SK_ADDR_EXACT_MATCHES; i++) {
  1050. MacAddr = pAC->Addr.Port[FromPortNumber].Exact[i];
  1051. pAC->Addr.Port[FromPortNumber].Exact[i] =
  1052. pAC->Addr.Port[ToPortNumber].Exact[i];
  1053. pAC->Addr.Port[ToPortNumber].Exact[i] = MacAddr;
  1054. }
  1055. for (i = 0; i < 8; i++) {
  1056. Byte = pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i];
  1057. pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i] =
  1058. pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i];
  1059. pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i] = Byte;
  1060. }
  1061. i = pAC->Addr.Port[FromPortNumber].PromMode;
  1062. pAC->Addr.Port[FromPortNumber].PromMode = pAC->Addr.Port[ToPortNumber].PromMode;
  1063. pAC->Addr.Port[ToPortNumber].PromMode = i;
  1064. DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt;
  1065. pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt =
  1066. pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt;
  1067. pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt = DWord;
  1068. DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt;
  1069. pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt =
  1070. pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt;
  1071. pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt = DWord;
  1072. DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv;
  1073. pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv =
  1074. pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv;
  1075. pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv = DWord;
  1076. DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchDrv;
  1077. pAC->Addr.Port[FromPortNumber].NextExactMatchDrv =
  1078. pAC->Addr.Port[ToPortNumber].NextExactMatchDrv;
  1079. pAC->Addr.Port[ToPortNumber].NextExactMatchDrv = DWord;
  1080. /* CAUTION: Solution works if only ports of one adapter are in use. */
  1081. for (i = 0; (SK_U32)i < pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].
  1082. Net->NetNumber].NumPorts; i++) {
  1083. if (pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
  1084. Port[i]->PortNumber == ToPortNumber) {
  1085. pAC->Addr.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
  1086. ActivePort = i;
  1087. /* 20001207 RA: Was "ToPortNumber;". */
  1088. }
  1089. }
  1090. (void)SkAddrMcUpdate(pAC, IoC, FromPortNumber);
  1091. (void)SkAddrMcUpdate(pAC, IoC, ToPortNumber);
  1092. return (SK_ADDR_SUCCESS);
  1093. } /* SkAddrSwap */
  1094. #ifdef __cplusplus
  1095. }
  1096. #endif /* __cplusplus */