1 /******************************************************************************
4 * Project: GEnesis, PCI Gigabit Ethernet Adapter
5 * Version: $Revision: 1.48 $
6 * Date: $Date: 2003/02/12 17:09:37 $
7 * Purpose: Manage Addresses (Multicast and Unicast) and Promiscuous Mode.
9 ******************************************************************************/
11 /******************************************************************************
13 * (C)Copyright 1998-2002 SysKonnect GmbH.
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * The information in this file is provided "AS IS" without warranty.
22 ******************************************************************************/
24 /******************************************************************************
29 * Revision 1.48 2003/02/12 17:09:37 tschilli
30 * Fix in SkAddrOverride() to set both (physical and logical) MAC addresses
31 * in case that both addresses are identical.
33 * Revision 1.47 2002/09/17 06:31:10 tschilli
34 * Handling of SK_PROM_MODE_ALL_MC flag in SkAddrGmacMcUpdate()
35 * and SkAddrGmacPromiscuousChange() fixed.
38 * Revision 1.46 2002/08/22 07:55:41 tschilli
39 * New function SkGmacMcHash() for GMAC multicast hashing algorithm added.
42 * Revision 1.45 2002/08/15 12:29:35 tschilli
43 * SkAddrGmacMcUpdate() and SkAddrGmacPromiscuousChange() changed.
45 * Revision 1.44 2002/08/14 12:18:03 rschmidt
46 * Replaced direct handling of MAC Hashing (XMAC and GMAC)
47 * with routine SkMacHashing().
48 * Replaced wrong 3rd para 'i' with 'PortNumber' in SkMacPromiscMode().
50 * Revision 1.43 2002/08/13 09:37:43 rschmidt
51 * Corrected some SK_DBG_MSG outputs.
52 * Replaced wrong 2nd para pAC with IoC in SkMacPromiscMode().
55 * Revision 1.42 2002/08/12 11:24:36 rschmidt
56 * Remove setting of logical MAC address GM_SRC_ADDR_2 in SkAddrInit().
57 * Replaced direct handling of MAC Promiscuous Mode (XMAC and GMAC)
58 * with routine SkMacPromiscMode().
61 * Revision 1.41 2002/06/10 13:52:18 tschilli
62 * Changes for handling YUKON.
63 * All changes are internally and not visible to the programmer
66 * Revision 1.40 2001/02/14 14:04:59 rassmann
69 * Revision 1.39 2001/01/30 10:30:04 rassmann
72 * Revision 1.38 2001/01/25 16:26:52 rassmann
73 * Ensured that logical address overrides are done on net's active port.
75 * Revision 1.37 2001/01/22 13:41:34 rassmann
76 * Supporting two nets on dual-port adapters.
78 * Revision 1.36 2000/08/07 11:10:39 rassmann
81 * Revision 1.35 2000/05/04 09:38:41 rassmann
83 * Corrected multicast address hashing.
85 * Revision 1.34 1999/11/22 13:23:44 cgoos
86 * Changed license header to GPL.
88 * Revision 1.33 1999/05/28 10:56:06 rassmann
91 * Revision 1.32 1999/03/31 10:59:20 rassmann
92 * Returning Success instead of DupAddr if address shall be overridden
95 * Revision 1.31 1999/01/14 16:18:17 rassmann
96 * Corrected multicast initialization.
98 * Revision 1.30 1999/01/04 10:30:35 rassmann
99 * SkAddrOverride only possible after SK_INIT_IO phase.
101 * Revision 1.29 1998/12/29 13:13:10 rassmann
102 * An address override is now preserved in the SK_INIT_IO phase.
103 * All functions return an int now.
104 * Extended parameter checking.
106 * Revision 1.28 1998/12/01 11:45:53 rassmann
109 * Revision 1.27 1998/12/01 09:22:49 rassmann
110 * SkAddrMcAdd and SkAddrMcUpdate returned SK_MC_FILTERING_INEXACT
113 * Revision 1.26 1998/11/24 12:39:44 rassmann
114 * Reserved multicast entry for BPDU address.
115 * 13 multicast entries left for protocol.
117 * Revision 1.25 1998/11/17 16:54:23 rassmann
118 * Using exact match for up to 14 multicast addresses.
119 * Still receiving all multicasts if more addresses are added.
121 * Revision 1.24 1998/11/13 17:24:31 rassmann
122 * Changed return value of SkAddrOverride to int.
124 * Revision 1.23 1998/11/13 16:56:18 rassmann
125 * Added macro SK_ADDR_COMPARE.
126 * Changed return type of SkAddrOverride to SK_BOOL.
128 * Revision 1.22 1998/11/04 17:06:17 rassmann
129 * Corrected McUpdate and PromiscuousChange functions.
131 * Revision 1.21 1998/10/29 14:34:04 rassmann
132 * Clearing SK_ADDR struct at startup.
134 * Revision 1.20 1998/10/28 18:16:34 rassmann
135 * Avoiding I/Os before SK_INIT_RUN level.
136 * Aligning InexactFilter.
138 * Revision 1.19 1998/10/28 11:29:28 rassmann
139 * Programming physical address in SkAddrMcUpdate.
140 * Corrected programming of exact match entries.
142 * Revision 1.18 1998/10/28 10:34:48 rassmann
143 * Corrected reading of physical addresses.
145 * Revision 1.17 1998/10/28 10:26:13 rassmann
146 * Getting ports' current MAC addresses from EPROM now.
147 * Added debug output.
149 * Revision 1.16 1998/10/27 16:20:12 rassmann
150 * Reading MAC address byte by byte.
152 * Revision 1.15 1998/10/22 11:39:09 rassmann
153 * Corrected signed/unsigned mismatches.
155 * Revision 1.14 1998/10/19 17:12:35 rassmann
156 * Syntax corrections.
158 * Revision 1.13 1998/10/19 17:02:19 rassmann
159 * Now reading permanent MAC addresses from CRF.
161 * Revision 1.12 1998/10/15 15:15:48 rassmann
162 * Changed Flags Parameters from SK_U8 to int.
165 * Revision 1.11 1998/09/24 19:15:12 rassmann
168 * Revision 1.10 1998/09/18 20:18:54 rassmann
170 * Implemented swapping.
172 * Revision 1.9 1998/09/16 11:32:00 rassmann
173 * Including skdrv1st.h again. :(
175 * Revision 1.8 1998/09/16 11:09:34 rassmann
176 * Syntax corrections.
178 * Revision 1.7 1998/09/14 17:06:34 rassmann
181 * Revision 1.6 1998/09/07 08:45:41 rassmann
182 * Syntax corrections.
184 * Revision 1.5 1998/09/04 19:40:19 rassmann
185 * Interface enhancements.
187 * Revision 1.4 1998/09/04 12:14:12 rassmann
190 * Revision 1.3 1998/09/02 16:56:40 rassmann
193 * Revision 1.2 1998/08/27 14:26:09 rassmann
196 * Revision 1.1 1998/08/21 08:30:22 rassmann
197 * First public version.
199 ******************************************************************************/
201 /******************************************************************************
205 * This module is intended to manage multicast addresses, address override,
206 * and promiscuous mode on GEnesis and Yukon adapters.
209 * port address: physical MAC address
210 * 1st exact match: logical MAC address (GEnesis only)
211 * 2nd exact match: RLMT multicast (GEnesis only)
212 * exact match 3-13: OS-specific multicasts (GEnesis only)
214 * Include File Hierarchy:
219 ******************************************************************************/
224 static const char SysKonnectFileId[] =
225 "@(#) $Id: skaddr.c,v 1.48 2003/02/12 17:09:37 tschilli Exp $ (C) SysKonnect.";
226 #endif /* !defined(lint) */
231 #error C++ is not yet supported.
233 #endif /* cplusplus */
235 #include "h/skdrv1st.h"
236 #include "h/skdrv2nd.h"
238 /* defines ********************************************************************/
241 #define XMAC_POLY 0xEDB88320UL /* CRC32-Poly - XMAC: Little Endian */
242 #define GMAC_POLY 0x04C11DB7L /* CRC16-Poly - GMAC: Little Endian */
243 #define HASH_BITS 6 /* #bits in hash */
244 #define SK_MC_BIT 0x01
246 /* Error numbers and messages. */
248 #define SKERR_ADDR_E001 (SK_ERRBASE_ADDR + 0)
249 #define SKERR_ADDR_E001MSG "Bad Flags."
250 #define SKERR_ADDR_E002 (SKERR_ADDR_E001 + 1)
251 #define SKERR_ADDR_E002MSG "New Error."
253 /* typedefs *******************************************************************/
257 /* global variables ***********************************************************/
259 /* 64-bit hash values with all bits set. */
261 SK_U16 OnesHash[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
263 /* local variables ************************************************************/
266 static int Next0[SK_MAX_MACS] = {0, 0};
269 /* functions ******************************************************************/
271 /******************************************************************************
273 * SkAddrInit - initialize data, set state to init
280 * This routine clears the multicast tables and resets promiscuous mode.
281 * Some entries are reserved for the "logical MAC address", the
282 * SK-RLMT multicast address, and the BPDU multicast address.
288 * All permanent MAC addresses are read from EPROM.
289 * If the current MAC addresses are not already set in software,
290 * they are set to the values of the permanent addresses.
291 * The current addresses are written to the corresponding MAC.
306 SK_AC *pAC, /* the adapter context */
307 SK_IOC IoC, /* I/O context */
308 int Level) /* initialization level */
314 SK_ADDR_PORT *pAPort;
318 SK_MEMSET((char *) &pAC->Addr, 0, sizeof(SK_ADDR));
320 for (i = 0; i < SK_MAX_MACS; i++) {
321 pAPort = &pAC->Addr.Port[i];
322 pAPort->PromMode = SK_PROM_MODE_NONE;
324 pAPort->FirstExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
325 pAPort->FirstExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
326 pAPort->NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
327 pAPort->NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
330 for (i = 0; i < SK_MAX_MACS; i++) {
331 if (pAC->Addr.Port[i].NextExactMatchRlmt <
332 SK_ADDR_FIRST_MATCH_RLMT) {
337 /* pAC->Addr.InitDone = SK_INIT_DATA; */
341 for (i = 0; i < SK_MAX_NETS; i++) {
342 pAC->Addr.Net[i].ActivePort = pAC->Rlmt.Net[i].ActivePort;
345 for (i = 0; i < SK_MAX_MACS; i++) {
346 if (pAC->Addr.Port[i].NextExactMatchRlmt <
347 SK_ADDR_FIRST_MATCH_RLMT) {
353 /* Read permanent logical MAC address from Control Register File. */
354 for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
355 InAddr = (SK_U8 *) &pAC->Addr.Net[0].PermanentMacAddress.a[j];
356 SK_IN8(IoC, B2_MAC_1 + j, InAddr);
359 if (!pAC->Addr.Net[0].CurrentMacAddressSet) {
360 /* Set the current logical MAC address to the permanent one. */
361 pAC->Addr.Net[0].CurrentMacAddress =
362 pAC->Addr.Net[0].PermanentMacAddress;
363 pAC->Addr.Net[0].CurrentMacAddressSet = SK_TRUE;
366 /* Set the current logical MAC address. */
367 pAC->Addr.Port[pAC->Addr.Net[0].ActivePort].Exact[0] =
368 pAC->Addr.Net[0].CurrentMacAddress;
370 /* Set logical MAC address for net 2 to (log | 3). */
371 if (!pAC->Addr.Net[1].CurrentMacAddressSet) {
372 pAC->Addr.Net[1].PermanentMacAddress =
373 pAC->Addr.Net[0].PermanentMacAddress;
374 pAC->Addr.Net[1].PermanentMacAddress.a[5] |= 3;
375 /* Set the current logical MAC address to the permanent one. */
376 pAC->Addr.Net[1].CurrentMacAddress =
377 pAC->Addr.Net[1].PermanentMacAddress;
378 pAC->Addr.Net[1].CurrentMacAddressSet = SK_TRUE;
380 #endif /* SK_MAX_NETS > 1 */
383 for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
384 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
385 ("Permanent MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
387 pAC->Addr.Net[i].PermanentMacAddress.a[0],
388 pAC->Addr.Net[i].PermanentMacAddress.a[1],
389 pAC->Addr.Net[i].PermanentMacAddress.a[2],
390 pAC->Addr.Net[i].PermanentMacAddress.a[3],
391 pAC->Addr.Net[i].PermanentMacAddress.a[4],
392 pAC->Addr.Net[i].PermanentMacAddress.a[5]))
394 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
395 ("Logical MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
397 pAC->Addr.Net[i].CurrentMacAddress.a[0],
398 pAC->Addr.Net[i].CurrentMacAddress.a[1],
399 pAC->Addr.Net[i].CurrentMacAddress.a[2],
400 pAC->Addr.Net[i].CurrentMacAddress.a[3],
401 pAC->Addr.Net[i].CurrentMacAddress.a[4],
402 pAC->Addr.Net[i].CurrentMacAddress.a[5]))
406 for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
407 pAPort = &pAC->Addr.Port[i];
409 /* Read permanent port addresses from Control Register File. */
410 for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
411 InAddr = (SK_U8 *) &pAPort->PermanentMacAddress.a[j];
412 SK_IN8(IoC, B2_MAC_2 + 8 * i + j, InAddr);
415 if (!pAPort->CurrentMacAddressSet) {
417 * Set the current and previous physical MAC address
418 * of this port to its permanent MAC address.
420 pAPort->CurrentMacAddress = pAPort->PermanentMacAddress;
421 pAPort->PreviousMacAddress = pAPort->PermanentMacAddress;
422 pAPort->CurrentMacAddressSet = SK_TRUE;
425 /* Set port's current physical MAC address. */
426 OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
428 if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
429 XM_OUTADDR(IoC, i, XM_SA, OutAddr);
432 GM_OUTADDR(IoC, i, GM_SRC_ADDR_1L, OutAddr);
435 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
436 ("SkAddrInit: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
437 pAPort->PermanentMacAddress.a[0],
438 pAPort->PermanentMacAddress.a[1],
439 pAPort->PermanentMacAddress.a[2],
440 pAPort->PermanentMacAddress.a[3],
441 pAPort->PermanentMacAddress.a[4],
442 pAPort->PermanentMacAddress.a[5]))
444 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
445 ("SkAddrInit: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
446 pAPort->CurrentMacAddress.a[0],
447 pAPort->CurrentMacAddress.a[1],
448 pAPort->CurrentMacAddress.a[2],
449 pAPort->CurrentMacAddress.a[3],
450 pAPort->CurrentMacAddress.a[4],
451 pAPort->CurrentMacAddress.a[5]))
454 /* pAC->Addr.InitDone = SK_INIT_IO; */
459 for (i = 0; i < SK_MAX_MACS; i++) {
460 if (pAC->Addr.Port[i].NextExactMatchRlmt <
461 SK_ADDR_FIRST_MATCH_RLMT) {
467 /* pAC->Addr.InitDone = SK_INIT_RUN; */
474 return (SK_ADDR_SUCCESS);
479 /******************************************************************************
481 * SkAddrMcClear - clear the multicast table
484 * This routine clears the multicast table.
486 * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
489 * It calls either SkAddrXmacMcClear or SkAddrGmacMcClear, according
490 * to the adapter in use. The real work is done there.
494 * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
495 * may be called after SK_INIT_IO without limitation
499 * SK_ADDR_ILLEGAL_PORT
502 SK_AC *pAC, /* adapter context */
503 SK_IOC IoC, /* I/O context */
504 SK_U32 PortNumber, /* Index of affected port */
505 int Flags) /* permanent/non-perm, sw-only */
509 if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
510 return (SK_ADDR_ILLEGAL_PORT);
513 if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
514 ReturnCode = SkAddrXmacMcClear(pAC, IoC, PortNumber, Flags);
517 ReturnCode = SkAddrGmacMcClear(pAC, IoC, PortNumber, Flags);
522 } /* SkAddrMcClear */
525 /******************************************************************************
527 * SkAddrXmacMcClear - clear the multicast table
530 * This routine clears the multicast table
531 * (either entry 2 or entries 3-16 and InexactFilter) of the given port.
532 * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
537 * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
538 * may be called after SK_INIT_IO without limitation
542 * SK_ADDR_ILLEGAL_PORT
544 int SkAddrXmacMcClear(
545 SK_AC *pAC, /* adapter context */
546 SK_IOC IoC, /* I/O context */
547 SK_U32 PortNumber, /* Index of affected port */
548 int Flags) /* permanent/non-perm, sw-only */
552 if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
554 /* Clear RLMT multicast addresses. */
555 pAC->Addr.Port[PortNumber].NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
557 else { /* not permanent => DRV */
559 /* Clear InexactFilter */
560 for (i = 0; i < 8; i++) {
561 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
564 /* Clear DRV multicast addresses. */
566 pAC->Addr.Port[PortNumber].NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
569 if (!(Flags & SK_MC_SW_ONLY)) {
570 (void) SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
573 return (SK_ADDR_SUCCESS);
575 } /* SkAddrXmacMcClear */
578 /******************************************************************************
580 * SkAddrGmacMcClear - clear the multicast table
583 * This routine clears the multicast hashing table (InexactFilter)
584 * (either the RLMT or the driver bits) of the given port.
586 * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
591 * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
592 * may be called after SK_INIT_IO without limitation
596 * SK_ADDR_ILLEGAL_PORT
598 int SkAddrGmacMcClear(
599 SK_AC *pAC, /* adapter context */
600 SK_IOC IoC, /* I/O context */
601 SK_U32 PortNumber, /* Index of affected port */
602 int Flags) /* permanent/non-perm, sw-only */
607 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
608 ("GMAC InexactFilter (not cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
609 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0],
610 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1],
611 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2],
612 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3],
613 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
614 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
615 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
616 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]))
619 /* Clear InexactFilter */
620 for (i = 0; i < 8; i++) {
621 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
624 if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
626 /* Copy DRV bits to InexactFilter. */
627 for (i = 0; i < 8; i++) {
628 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
629 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
631 /* Clear InexactRlmtFilter. */
632 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i] = 0;
636 else { /* not permanent => DRV */
638 /* Copy RLMT bits to InexactFilter. */
639 for (i = 0; i < 8; i++) {
640 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
641 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
643 /* Clear InexactDrvFilter. */
644 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i] = 0;
649 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
650 ("GMAC InexactFilter (cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
651 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0],
652 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1],
653 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2],
654 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3],
655 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
656 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
657 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
658 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]))
661 if (!(Flags & SK_MC_SW_ONLY)) {
662 (void) SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
665 return (SK_ADDR_SUCCESS);
667 } /* SkAddrGmacMcClear */
669 #ifndef SK_ADDR_CHEAT
671 /******************************************************************************
673 * SkXmacMcHash - hash multicast address
676 * This routine computes the hash value for a multicast address.
677 * A CRC32 algorithm is used.
680 * The code was adapted from the XaQti data sheet.
686 * Hash value of multicast address.
689 unsigned char *pMc) /* Multicast address */
697 for (Idx = 0; Idx < SK_MAC_ADDR_LEN; Idx++) {
699 for (Bit = 0; Bit < 8; Bit++, Data >>= 1) {
700 Crc = (Crc >> 1) ^ (((Crc ^ Data) & 1) ? XMAC_POLY : 0);
704 return (Crc & ((1 << HASH_BITS) - 1));
709 /******************************************************************************
711 * SkGmacMcHash - hash multicast address
714 * This routine computes the hash value for a multicast address.
715 * A CRC16 algorithm is used.
724 * Hash value of multicast address.
727 unsigned char *pMc) /* Multicast address */
736 for (Byte = 0; Byte < 6; Byte++) {
738 Data = (SK_U32) pMc[Byte];
740 /* Change bit order in byte. */
742 for (Bit = 0; Bit < 8; Bit++) {
744 Data |= 1L << (7 - Bit);
747 Data &= ~(1L << (7 - Bit));
753 for (Bit = 0; Bit < 8; Bit++) {
754 if (Crc & 0x80000000) {
755 Crc = (Crc << 1) ^ GMAC_POLY;
763 return (Crc & ((1 << HASH_BITS) - 1));
767 #endif /* not SK_ADDR_CHEAT */
769 /******************************************************************************
771 * SkAddrMcAdd - add a multicast address to a port
774 * This routine enables reception for a given address on the given port.
776 * It calls either SkAddrXmacMcAdd or SkAddrGmacMcAdd, according to the
777 * adapter in use. The real work is done there.
780 * The return code is only valid for SK_PROM_MODE_NONE.
784 * may be called after SK_INIT_DATA
787 * SK_MC_FILTERING_EXACT
788 * SK_MC_FILTERING_INEXACT
789 * SK_MC_ILLEGAL_ADDRESS
791 * SK_MC_RLMT_OVERFLOW
794 SK_AC *pAC, /* adapter context */
795 SK_IOC IoC, /* I/O context */
796 SK_U32 PortNumber, /* Port Number */
797 SK_MAC_ADDR *pMc, /* multicast address to be added */
798 int Flags) /* permanent/non-permanent */
802 if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
803 return (SK_ADDR_ILLEGAL_PORT);
806 if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
807 ReturnCode = SkAddrXmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
810 ReturnCode = SkAddrGmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
818 /******************************************************************************
820 * SkAddrXmacMcAdd - add a multicast address to a port
823 * This routine enables reception for a given address on the given port.
826 * The return code is only valid for SK_PROM_MODE_NONE.
828 * The multicast bit is only checked if there are no free exact match
833 * may be called after SK_INIT_DATA
836 * SK_MC_FILTERING_EXACT
837 * SK_MC_FILTERING_INEXACT
838 * SK_MC_ILLEGAL_ADDRESS
839 * SK_MC_RLMT_OVERFLOW
842 SK_AC *pAC, /* adapter context */
843 SK_IOC IoC, /* I/O context */
844 SK_U32 PortNumber, /* Port Number */
845 SK_MAC_ADDR *pMc, /* multicast address to be added */
846 int Flags) /* permanent/non-permanent */
850 #ifndef SK_ADDR_CHEAT
852 #endif /* !defined(SK_ADDR_CHEAT) */
854 if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
856 if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt <
857 SK_ADDR_FIRST_MATCH_RLMT) {
858 Next0[PortNumber] |= 1;
859 return (SK_MC_RLMT_OVERFLOW);
863 if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt >
864 SK_ADDR_LAST_MATCH_RLMT) {
865 return (SK_MC_RLMT_OVERFLOW);
868 /* Set a RLMT multicast address. */
870 pAC->Addr.Port[PortNumber].Exact[
871 pAC->Addr.Port[PortNumber].NextExactMatchRlmt++] = *pMc;
873 return (SK_MC_FILTERING_EXACT);
877 if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <
878 SK_ADDR_FIRST_MATCH_DRV) {
879 Next0[PortNumber] |= 2;
880 return (SK_MC_RLMT_OVERFLOW);
884 if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
886 /* Set exact match entry. */
887 pAC->Addr.Port[PortNumber].Exact[
888 pAC->Addr.Port[PortNumber].NextExactMatchDrv++] = *pMc;
890 /* Clear InexactFilter */
891 for (i = 0; i < 8; i++) {
892 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
896 if (!(pMc->a[0] & SK_MC_BIT)) {
897 /* Hashing only possible with multicast addresses. */
898 return (SK_MC_ILLEGAL_ADDRESS);
900 #ifndef SK_ADDR_CHEAT
901 /* Compute hash value of address. */
902 HashBit = 63 - SkXmacMcHash(&pMc->a[0]);
904 /* Add bit to InexactFilter. */
905 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[HashBit / 8] |=
907 #else /* SK_ADDR_CHEAT */
908 /* Set all bits in InexactFilter. */
909 for (i = 0; i < 8; i++) {
910 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
912 #endif /* SK_ADDR_CHEAT */
915 for (Inexact = 0, i = 0; i < 8; i++) {
916 Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
919 if (Inexact == 0 && pAC->Addr.Port[PortNumber].PromMode == 0) {
920 return (SK_MC_FILTERING_EXACT);
923 return (SK_MC_FILTERING_INEXACT);
926 } /* SkAddrXmacMcAdd */
929 /******************************************************************************
931 * SkAddrGmacMcAdd - add a multicast address to a port
934 * This routine enables reception for a given address on the given port.
937 * The return code is only valid for SK_PROM_MODE_NONE.
941 * may be called after SK_INIT_DATA
944 * SK_MC_FILTERING_INEXACT
945 * SK_MC_ILLEGAL_ADDRESS
948 SK_AC *pAC, /* adapter context */
949 SK_IOC IoC, /* I/O context */
950 SK_U32 PortNumber, /* Port Number */
951 SK_MAC_ADDR *pMc, /* multicast address to be added */
952 int Flags) /* permanent/non-permanent */
955 #ifndef SK_ADDR_CHEAT
957 #endif /* !defined(SK_ADDR_CHEAT) */
959 if (!(pMc->a[0] & SK_MC_BIT)) {
960 /* Hashing only possible with multicast addresses. */
961 return (SK_MC_ILLEGAL_ADDRESS);
964 #ifndef SK_ADDR_CHEAT
966 /* Compute hash value of address. */
967 HashBit = SkGmacMcHash(&pMc->a[0]);
969 if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
971 /* Add bit to InexactRlmtFilter. */
972 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[HashBit / 8] |=
975 /* Copy bit to InexactFilter. */
976 for (i = 0; i < 8; i++) {
977 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
978 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
981 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
982 ("GMAC InexactRlmtFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
983 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[0],
984 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[1],
985 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[2],
986 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[3],
987 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[4],
988 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[5],
989 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[6],
990 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[7]))
993 else { /* not permanent => DRV */
995 /* Add bit to InexactDrvFilter. */
996 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[HashBit / 8] |=
999 /* Copy bit to InexactFilter. */
1000 for (i = 0; i < 8; i++) {
1001 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
1002 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
1005 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1006 ("GMAC InexactDrvFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
1007 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[0],
1008 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[1],
1009 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[2],
1010 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[3],
1011 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[4],
1012 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[5],
1013 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[6],
1014 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[7]))
1018 #else /* SK_ADDR_CHEAT */
1020 /* Set all bits in InexactFilter. */
1021 for (i = 0; i < 8; i++) {
1022 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
1024 #endif /* SK_ADDR_CHEAT */
1026 return (SK_MC_FILTERING_INEXACT);
1028 } /* SkAddrGmacMcAdd */
1031 /******************************************************************************
1033 * SkAddrMcUpdate - update the HW MC address table and set the MAC address
1036 * This routine enables reception of the addresses contained in a local
1037 * table for a given port.
1038 * It also programs the port's current physical MAC address.
1040 * It calls either SkAddrXmacMcUpdate or SkAddrGmacMcUpdate, according
1041 * to the adapter in use. The real work is done there.
1044 * The return code is only valid for SK_PROM_MODE_NONE.
1048 * may be called after SK_INIT_IO
1051 * SK_MC_FILTERING_EXACT
1052 * SK_MC_FILTERING_INEXACT
1053 * SK_ADDR_ILLEGAL_PORT
1056 SK_AC *pAC, /* adapter context */
1057 SK_IOC IoC, /* I/O context */
1058 SK_U32 PortNumber) /* Port Number */
1062 if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
1063 return (SK_ADDR_ILLEGAL_PORT);
1066 if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
1067 ReturnCode = SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
1070 ReturnCode = SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
1073 return (ReturnCode);
1075 } /* SkAddrMcUpdate */
1078 /******************************************************************************
1080 * SkAddrXmacMcUpdate - update the HW MC address table and set the MAC address
1083 * This routine enables reception of the addresses contained in a local
1084 * table for a given port.
1085 * It also programs the port's current physical MAC address.
1088 * The return code is only valid for SK_PROM_MODE_NONE.
1092 * may be called after SK_INIT_IO
1095 * SK_MC_FILTERING_EXACT
1096 * SK_MC_FILTERING_INEXACT
1097 * SK_ADDR_ILLEGAL_PORT
1099 int SkAddrXmacMcUpdate(
1100 SK_AC *pAC, /* adapter context */
1101 SK_IOC IoC, /* I/O context */
1102 SK_U32 PortNumber) /* Port Number */
1107 SK_ADDR_PORT *pAPort;
1109 SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1110 ("SkAddrXmacMcUpdate on Port %u.\n", PortNumber))
1112 pAPort = &pAC->Addr.Port[PortNumber];
1115 SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1116 ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
1119 /* Start with 0 to also program the logical MAC address. */
1120 for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
1121 /* Set exact match address i on XMAC */
1122 OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
1123 XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
1126 /* Clear other permanent exact match addresses on XMAC */
1127 if (pAPort->NextExactMatchRlmt <= SK_ADDR_LAST_MATCH_RLMT) {
1129 SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchRlmt,
1130 SK_ADDR_LAST_MATCH_RLMT);
1133 for (i = pAPort->FirstExactMatchDrv; i < pAPort->NextExactMatchDrv; i++) {
1134 OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
1135 XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
1138 /* Clear other non-permanent exact match addresses on XMAC */
1139 if (pAPort->NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
1141 SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchDrv,
1142 SK_ADDR_LAST_MATCH_DRV);
1145 for (Inexact = 0, i = 0; i < 8; i++) {
1146 Inexact |= pAPort->InexactFilter.Bytes[i];
1149 if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
1151 /* Set all bits in 64-bit hash register. */
1152 XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
1154 /* Enable Hashing */
1155 SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
1157 else if (Inexact != 0) {
1159 /* Set 64-bit hash register to InexactFilter. */
1160 XM_OUTHASH(IoC, PortNumber, XM_HSM, &pAPort->InexactFilter.Bytes[0]);
1162 /* Enable Hashing */
1163 SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
1166 /* Disable Hashing */
1167 SkMacHashing(pAC, IoC, PortNumber, SK_FALSE);
1170 if (pAPort->PromMode != SK_PROM_MODE_NONE) {
1171 (void) SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
1174 /* Set port's current physical MAC address. */
1175 OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
1177 XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
1180 for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
1184 /* Get exact match address i from port PortNumber. */
1185 InAddr = (SK_U16 *) &InAddr8[0];
1187 XM_INADDR(IoC, PortNumber, XM_EXM(i), InAddr);
1189 SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1190 ("SkAddrXmacMcUpdate: MC address %d on Port %u: ",
1191 "%02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x\n",
1200 pAPort->Exact[i].a[0],
1201 pAPort->Exact[i].a[1],
1202 pAPort->Exact[i].a[2],
1203 pAPort->Exact[i].a[3],
1204 pAPort->Exact[i].a[4],
1205 pAPort->Exact[i].a[5]))
1209 /* Determine return value. */
1210 if (Inexact == 0 && pAPort->PromMode == 0) {
1211 return (SK_MC_FILTERING_EXACT);
1214 return (SK_MC_FILTERING_INEXACT);
1217 } /* SkAddrXmacMcUpdate */
1220 /******************************************************************************
1222 * SkAddrGmacMcUpdate - update the HW MC address table and set the MAC address
1225 * This routine enables reception of the addresses contained in a local
1226 * table for a given port.
1227 * It also programs the port's current physical MAC address.
1230 * The return code is only valid for SK_PROM_MODE_NONE.
1234 * may be called after SK_INIT_IO
1237 * SK_MC_FILTERING_EXACT
1238 * SK_MC_FILTERING_INEXACT
1239 * SK_ADDR_ILLEGAL_PORT
1241 int SkAddrGmacMcUpdate(
1242 SK_AC *pAC, /* adapter context */
1243 SK_IOC IoC, /* I/O context */
1244 SK_U32 PortNumber) /* Port Number */
1249 SK_ADDR_PORT *pAPort;
1251 SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1252 ("SkAddrGmacMcUpdate on Port %u.\n", PortNumber))
1254 pAPort = &pAC->Addr.Port[PortNumber];
1257 SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1258 ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
1261 for (Inexact = 0, i = 0; i < 8; i++) {
1262 Inexact |= pAPort->InexactFilter.Bytes[i];
1265 /* Set 64-bit hash register to InexactFilter. */
1266 GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1,
1267 &pAPort->InexactFilter.Bytes[0]);
1269 if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
1271 /* Set all bits in 64-bit hash register. */
1272 GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
1274 /* Enable Hashing */
1275 SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
1278 /* Enable Hashing. */
1279 SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
1282 if (pAPort->PromMode != SK_PROM_MODE_NONE) {
1283 (void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
1286 /* Set port's current physical MAC address. */
1287 OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
1288 GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
1290 /* Set port's current logical MAC address. */
1291 OutAddr = (SK_U16 *) &pAPort->Exact[0].a[0];
1292 GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_2L, OutAddr);
1295 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1296 ("SkAddrGmacMcUpdate: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
1297 pAPort->Exact[0].a[0],
1298 pAPort->Exact[0].a[1],
1299 pAPort->Exact[0].a[2],
1300 pAPort->Exact[0].a[3],
1301 pAPort->Exact[0].a[4],
1302 pAPort->Exact[0].a[5]))
1304 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1305 ("SkAddrGmacMcUpdate: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
1306 pAPort->CurrentMacAddress.a[0],
1307 pAPort->CurrentMacAddress.a[1],
1308 pAPort->CurrentMacAddress.a[2],
1309 pAPort->CurrentMacAddress.a[3],
1310 pAPort->CurrentMacAddress.a[4],
1311 pAPort->CurrentMacAddress.a[5]))
1314 /* Determine return value. */
1315 if (Inexact == 0 && pAPort->PromMode == 0) {
1316 return (SK_MC_FILTERING_EXACT);
1319 return (SK_MC_FILTERING_INEXACT);
1322 } /* SkAddrGmacMcUpdate */
1325 /******************************************************************************
1327 * SkAddrOverride - override a port's MAC address
1330 * This routine overrides the MAC address of one port.
1334 * may be called after SK_INIT_IO
1337 * SK_ADDR_SUCCESS if successful.
1338 * SK_ADDR_DUPLICATE_ADDRESS if duplicate MAC address.
1339 * SK_ADDR_MULTICAST_ADDRESS if multicast or broadcast address.
1340 * SK_ADDR_TOO_EARLY if SK_INIT_IO was not executed before.
1343 SK_AC *pAC, /* adapter context */
1344 SK_IOC IoC, /* I/O context */
1345 SK_U32 PortNumber, /* Port Number */
1346 SK_MAC_ADDR *pNewAddr, /* new MAC address */
1347 int Flags) /* logical/physical MAC address */
1354 NetNumber = pAC->Rlmt.Port[PortNumber].Net->NetNumber;
1356 if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
1357 return (SK_ADDR_ILLEGAL_PORT);
1360 if (pNewAddr != NULL && (pNewAddr->a[0] & SK_MC_BIT) != 0) {
1361 return (SK_ADDR_MULTICAST_ADDRESS);
1364 if (!pAC->Addr.Net[NetNumber].CurrentMacAddressSet) {
1365 return (SK_ADDR_TOO_EARLY);
1368 if (Flags & SK_ADDR_SET_LOGICAL) { /* Activate logical MAC address. */
1369 /* Parameter *pNewAddr is ignored. */
1370 for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
1371 if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
1372 return (SK_ADDR_TOO_EARLY);
1376 /* Set PortNumber to number of net's active port. */
1377 PortNumber = pAC->Rlmt.Net[NetNumber].
1378 Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
1380 pAC->Addr.Port[PortNumber].Exact[0] =
1381 pAC->Addr.Net[NetNumber].CurrentMacAddress;
1383 /* Write address to first exact match entry of active port. */
1384 (void) SkAddrMcUpdate(pAC, IoC, PortNumber);
1386 else if (Flags & SK_ADDR_CLEAR_LOGICAL) {
1387 /* Deactivate logical MAC address. */
1388 /* Parameter *pNewAddr is ignored. */
1389 for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
1390 if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
1391 return (SK_ADDR_TOO_EARLY);
1395 /* Set PortNumber to number of net's active port. */
1396 PortNumber = pAC->Rlmt.Net[NetNumber].
1397 Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
1399 for (i = 0; i < SK_MAC_ADDR_LEN; i++ ) {
1400 pAC->Addr.Port[PortNumber].Exact[0].a[i] = 0;
1403 /* Write address to first exact match entry of active port. */
1404 (void) SkAddrMcUpdate(pAC, IoC, PortNumber);
1406 else if (Flags & SK_ADDR_PHYSICAL_ADDRESS) { /* Physical MAC address. */
1407 if (SK_ADDR_EQUAL(pNewAddr->a,
1408 pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
1409 return (SK_ADDR_DUPLICATE_ADDRESS);
1412 for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
1413 if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
1414 return (SK_ADDR_TOO_EARLY);
1417 if (SK_ADDR_EQUAL(pNewAddr->a,
1418 pAC->Addr.Port[i].CurrentMacAddress.a)) {
1419 if (i == PortNumber) {
1420 return (SK_ADDR_SUCCESS);
1423 return (SK_ADDR_DUPLICATE_ADDRESS);
1428 pAC->Addr.Port[PortNumber].PreviousMacAddress =
1429 pAC->Addr.Port[PortNumber].CurrentMacAddress;
1430 pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
1432 /* Change port's physical MAC address. */
1433 OutAddr = (SK_U16 *) pNewAddr;
1435 if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
1436 XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
1439 GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
1442 /* Report address change to RLMT. */
1443 Para.Para32[0] = PortNumber;
1444 Para.Para32[0] = -1;
1445 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
1447 else { /* Logical MAC address. */
1448 if (SK_ADDR_EQUAL(pNewAddr->a,
1449 pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
1450 return (SK_ADDR_SUCCESS);
1453 for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
1454 if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
1455 return (SK_ADDR_TOO_EARLY);
1458 if (SK_ADDR_EQUAL(pNewAddr->a,
1459 pAC->Addr.Port[i].CurrentMacAddress.a)) {
1460 return (SK_ADDR_DUPLICATE_ADDRESS);
1465 * In case that the physical and the logical MAC addresses are equal
1466 * we must also change the physical MAC address here.
1467 * In this case we have an adapter which initially was programmed with
1468 * two identical MAC addresses.
1470 if (SK_ADDR_EQUAL(pAC->Addr.Port[PortNumber].CurrentMacAddress.a,
1471 pAC->Addr.Port[PortNumber].Exact[0].a)) {
1473 pAC->Addr.Port[PortNumber].PreviousMacAddress =
1474 pAC->Addr.Port[PortNumber].CurrentMacAddress;
1475 pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
1477 /* Report address change to RLMT. */
1478 Para.Para32[0] = PortNumber;
1479 Para.Para32[0] = -1;
1480 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
1483 /* Set PortNumber to number of net's active port. */
1484 PortNumber = pAC->Rlmt.Net[NetNumber].
1485 Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
1487 pAC->Addr.Net[NetNumber].CurrentMacAddress = *pNewAddr;
1488 pAC->Addr.Port[PortNumber].Exact[0] = *pNewAddr;
1490 SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1491 ("SkAddrOverride: Permanent MAC Address: %02X %02X %02X %02X %02X %02X\n",
1492 pAC->Addr.Net[NetNumber].PermanentMacAddress.a[0],
1493 pAC->Addr.Net[NetNumber].PermanentMacAddress.a[1],
1494 pAC->Addr.Net[NetNumber].PermanentMacAddress.a[2],
1495 pAC->Addr.Net[NetNumber].PermanentMacAddress.a[3],
1496 pAC->Addr.Net[NetNumber].PermanentMacAddress.a[4],
1497 pAC->Addr.Net[NetNumber].PermanentMacAddress.a[5]))
1499 SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1500 ("SkAddrOverride: New logical MAC Address: %02X %02X %02X %02X %02X %02X\n",
1501 pAC->Addr.Net[NetNumber].CurrentMacAddress.a[0],
1502 pAC->Addr.Net[NetNumber].CurrentMacAddress.a[1],
1503 pAC->Addr.Net[NetNumber].CurrentMacAddress.a[2],
1504 pAC->Addr.Net[NetNumber].CurrentMacAddress.a[3],
1505 pAC->Addr.Net[NetNumber].CurrentMacAddress.a[4],
1506 pAC->Addr.Net[NetNumber].CurrentMacAddress.a[5]))
1509 /* Write address to first exact match entry of active port. */
1510 (void) SkAddrMcUpdate(pAC, IoC, PortNumber);
1513 return (SK_ADDR_SUCCESS);
1515 } /* SkAddrOverride */
1518 /******************************************************************************
1520 * SkAddrPromiscuousChange - set promiscuous mode for given port
1523 * This routine manages promiscuous mode:
1528 * It calls either SkAddrXmacPromiscuousChange or
1529 * SkAddrGmacPromiscuousChange, according to the adapter in use.
1530 * The real work is done there.
1534 * may be called after SK_INIT_IO
1538 * SK_ADDR_ILLEGAL_PORT
1540 int SkAddrPromiscuousChange(
1541 SK_AC *pAC, /* adapter context */
1542 SK_IOC IoC, /* I/O context */
1543 SK_U32 PortNumber, /* port whose promiscuous mode changes */
1544 int NewPromMode) /* new promiscuous mode */
1548 if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
1549 return (SK_ADDR_ILLEGAL_PORT);
1552 if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
1553 ReturnCode = SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
1556 ReturnCode = SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
1559 return (ReturnCode);
1561 } /* SkAddrPromiscuousChange */
1564 /******************************************************************************
1566 * SkAddrXmacPromiscuousChange - set promiscuous mode for given port
1569 * This routine manages promiscuous mode:
1576 * may be called after SK_INIT_IO
1580 * SK_ADDR_ILLEGAL_PORT
1582 int SkAddrXmacPromiscuousChange(
1583 SK_AC *pAC, /* adapter context */
1584 SK_IOC IoC, /* I/O context */
1585 SK_U32 PortNumber, /* port whose promiscuous mode changes */
1586 int NewPromMode) /* new promiscuous mode */
1589 SK_BOOL InexactModeBit;
1592 SK_FILTER64 HwInexactFilter;
1593 SK_U16 LoMode; /* Lower 16 bits of XMAC Mode Register. */
1594 int CurPromMode = SK_PROM_MODE_NONE;
1596 /* Read CurPromMode from Hardware. */
1597 XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
1599 if ((LoMode & XM_MD_ENA_PROM) != 0) {
1600 /* Promiscuous mode! */
1601 CurPromMode |= SK_PROM_MODE_LLC;
1604 for (Inexact = 0xFF, i = 0; i < 8; i++) {
1605 Inexact &= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
1607 if (Inexact == 0xFF) {
1608 CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
1611 /* Get InexactModeBit (bit XM_MD_ENA_HASH in mode register) */
1612 XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
1614 InexactModeBit = (LoMode & XM_MD_ENA_HASH) != 0;
1616 /* Read 64-bit hash register from XMAC */
1617 XM_INHASH(IoC, PortNumber, XM_HSM, &HwInexactFilter.Bytes[0]);
1619 for (HwInexact = 0xFF, i = 0; i < 8; i++) {
1620 HwInexact &= HwInexactFilter.Bytes[i];
1623 if (InexactModeBit && (HwInexact == 0xFF)) {
1624 CurPromMode |= SK_PROM_MODE_ALL_MC;
1628 pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
1630 if (NewPromMode == CurPromMode) {
1631 return (SK_ADDR_SUCCESS);
1634 if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
1635 !(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC. */
1637 /* Set all bits in 64-bit hash register. */
1638 XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
1640 /* Enable Hashing */
1641 SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
1643 else if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
1644 !(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm MC. */
1645 for (Inexact = 0, i = 0; i < 8; i++) {
1646 Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
1649 /* Disable Hashing */
1650 SkMacHashing(pAC, IoC, PortNumber, SK_FALSE);
1653 /* Set 64-bit hash register to InexactFilter. */
1654 XM_OUTHASH(IoC, PortNumber, XM_HSM,
1655 &pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
1657 /* Enable Hashing */
1658 SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
1662 if ((NewPromMode & SK_PROM_MODE_LLC) &&
1663 !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */
1664 /* Set the MAC in Promiscuous Mode */
1665 SkMacPromiscMode(pAC, IoC, PortNumber, SK_TRUE);
1667 else if ((CurPromMode & SK_PROM_MODE_LLC) &&
1668 !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC. */
1669 /* Clear Promiscuous Mode */
1670 SkMacPromiscMode(pAC, IoC, PortNumber, SK_FALSE);
1673 return (SK_ADDR_SUCCESS);
1675 } /* SkAddrXmacPromiscuousChange */
1678 /******************************************************************************
1680 * SkAddrGmacPromiscuousChange - set promiscuous mode for given port
1683 * This routine manages promiscuous mode:
1690 * may be called after SK_INIT_IO
1694 * SK_ADDR_ILLEGAL_PORT
1696 int SkAddrGmacPromiscuousChange(
1697 SK_AC *pAC, /* adapter context */
1698 SK_IOC IoC, /* I/O context */
1699 SK_U32 PortNumber, /* port whose promiscuous mode changes */
1700 int NewPromMode) /* new promiscuous mode */
1702 SK_U16 ReceiveControl; /* GMAC Receive Control Register */
1703 int CurPromMode = SK_PROM_MODE_NONE;
1705 /* Read CurPromMode from Hardware. */
1706 GM_IN16(IoC, PortNumber, GM_RX_CTRL, &ReceiveControl);
1708 if ((ReceiveControl & (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA)) == 0) {
1709 /* Promiscuous mode! */
1710 CurPromMode |= SK_PROM_MODE_LLC;
1713 if ((ReceiveControl & GM_RXCR_MCF_ENA) == 0) {
1714 /* All Multicast mode! */
1715 CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
1718 pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
1720 if (NewPromMode == CurPromMode) {
1721 return (SK_ADDR_SUCCESS);
1724 if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
1725 !(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC */
1727 /* Set all bits in 64-bit hash register. */
1728 GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
1730 /* Enable Hashing */
1731 SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
1734 if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
1735 !(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm. MC */
1737 /* Set 64-bit hash register to InexactFilter. */
1738 GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1,
1739 &pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
1741 /* Enable Hashing. */
1742 SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
1745 if ((NewPromMode & SK_PROM_MODE_LLC) &&
1746 !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */
1748 /* Set the MAC to Promiscuous Mode. */
1749 SkMacPromiscMode(pAC, IoC, PortNumber, SK_TRUE);
1751 else if ((CurPromMode & SK_PROM_MODE_LLC) &&
1752 !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC */
1754 /* Clear Promiscuous Mode. */
1755 SkMacPromiscMode(pAC, IoC, PortNumber, SK_FALSE);
1758 return (SK_ADDR_SUCCESS);
1760 } /* SkAddrGmacPromiscuousChange */
1763 /******************************************************************************
1765 * SkAddrSwap - swap address info
1768 * This routine swaps address info of two ports.
1772 * may be called after SK_INIT_IO
1776 * SK_ADDR_ILLEGAL_PORT
1779 SK_AC *pAC, /* adapter context */
1780 SK_IOC IoC, /* I/O context */
1781 SK_U32 FromPortNumber, /* Port1 Index */
1782 SK_U32 ToPortNumber) /* Port2 Index */
1786 SK_MAC_ADDR MacAddr;
1789 if (FromPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
1790 return (SK_ADDR_ILLEGAL_PORT);
1793 if (ToPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
1794 return (SK_ADDR_ILLEGAL_PORT);
1797 if (pAC->Rlmt.Port[FromPortNumber].Net != pAC->Rlmt.Port[ToPortNumber].Net) {
1798 return (SK_ADDR_ILLEGAL_PORT);
1803 * - Exact Match Entries (GEnesis and Yukon)
1804 * Yukon uses first entry for the logical MAC
1805 * address (stored in the second GMAC register).
1806 * - FirstExactMatchRlmt (GEnesis only)
1807 * - NextExactMatchRlmt (GEnesis only)
1808 * - FirstExactMatchDrv (GEnesis only)
1809 * - NextExactMatchDrv (GEnesis only)
1810 * - 64-bit filter (InexactFilter)
1811 * - Promiscuous Mode
1815 for (i = 0; i < SK_ADDR_EXACT_MATCHES; i++) {
1816 MacAddr = pAC->Addr.Port[FromPortNumber].Exact[i];
1817 pAC->Addr.Port[FromPortNumber].Exact[i] =
1818 pAC->Addr.Port[ToPortNumber].Exact[i];
1819 pAC->Addr.Port[ToPortNumber].Exact[i] = MacAddr;
1822 for (i = 0; i < 8; i++) {
1823 Byte = pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i];
1824 pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i] =
1825 pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i];
1826 pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i] = Byte;
1829 i = pAC->Addr.Port[FromPortNumber].PromMode;
1830 pAC->Addr.Port[FromPortNumber].PromMode = pAC->Addr.Port[ToPortNumber].PromMode;
1831 pAC->Addr.Port[ToPortNumber].PromMode = i;
1833 if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
1834 DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt;
1835 pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt =
1836 pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt;
1837 pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt = DWord;
1839 DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt;
1840 pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt =
1841 pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt;
1842 pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt = DWord;
1844 DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv;
1845 pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv =
1846 pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv;
1847 pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv = DWord;
1849 DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchDrv;
1850 pAC->Addr.Port[FromPortNumber].NextExactMatchDrv =
1851 pAC->Addr.Port[ToPortNumber].NextExactMatchDrv;
1852 pAC->Addr.Port[ToPortNumber].NextExactMatchDrv = DWord;
1855 /* CAUTION: Solution works if only ports of one adapter are in use. */
1856 for (i = 0; (SK_U32) i < pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].
1857 Net->NetNumber].NumPorts; i++) {
1858 if (pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
1859 Port[i]->PortNumber == ToPortNumber) {
1860 pAC->Addr.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
1862 /* 20001207 RA: Was "ToPortNumber;". */
1866 (void) SkAddrMcUpdate(pAC, IoC, FromPortNumber);
1867 (void) SkAddrMcUpdate(pAC, IoC, ToPortNumber);
1869 return (SK_ADDR_SUCCESS);
1875 #endif /* __cplusplus */