1 /******************************************************************************
4 * Project: GEnesis, PCI Gigabit Ethernet Adapter
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.1.3.1 2011-02-28 14:53:19 lothar
30 * imported Ka-Ro specific additions to U-Boot 2009.08 for TX28
32 * Revision 1.48 2003/02/12 17:09:37 tschilli
33 * Fix in SkAddrOverride() to set both (physical and logical) MAC addresses
34 * in case that both addresses are identical.
36 * Revision 1.47 2002/09/17 06:31:10 tschilli
37 * Handling of SK_PROM_MODE_ALL_MC flag in SkAddrGmacMcUpdate()
38 * and SkAddrGmacPromiscuousChange() fixed.
41 * Revision 1.46 2002/08/22 07:55:41 tschilli
42 * New function SkGmacMcHash() for GMAC multicast hashing algorithm added.
45 * Revision 1.45 2002/08/15 12:29:35 tschilli
46 * SkAddrGmacMcUpdate() and SkAddrGmacPromiscuousChange() changed.
48 * Revision 1.44 2002/08/14 12:18:03 rschmidt
49 * Replaced direct handling of MAC Hashing (XMAC and GMAC)
50 * with routine SkMacHashing().
51 * Replaced wrong 3rd para 'i' with 'PortNumber' in SkMacPromiscMode().
53 * Revision 1.43 2002/08/13 09:37:43 rschmidt
54 * Corrected some SK_DBG_MSG outputs.
55 * Replaced wrong 2nd para pAC with IoC in SkMacPromiscMode().
58 * Revision 1.42 2002/08/12 11:24:36 rschmidt
59 * Remove setting of logical MAC address GM_SRC_ADDR_2 in SkAddrInit().
60 * Replaced direct handling of MAC Promiscuous Mode (XMAC and GMAC)
61 * with routine SkMacPromiscMode().
64 * Revision 1.41 2002/06/10 13:52:18 tschilli
65 * Changes for handling YUKON.
66 * All changes are internally and not visible to the programmer
69 * Revision 1.40 2001/02/14 14:04:59 rassmann
72 * Revision 1.39 2001/01/30 10:30:04 rassmann
75 * Revision 1.38 2001/01/25 16:26:52 rassmann
76 * Ensured that logical address overrides are done on net's active port.
78 * Revision 1.37 2001/01/22 13:41:34 rassmann
79 * Supporting two nets on dual-port adapters.
81 * Revision 1.36 2000/08/07 11:10:39 rassmann
84 * Revision 1.35 2000/05/04 09:38:41 rassmann
86 * Corrected multicast address hashing.
88 * Revision 1.34 1999/11/22 13:23:44 cgoos
89 * Changed license header to GPL.
91 * Revision 1.33 1999/05/28 10:56:06 rassmann
94 * Revision 1.32 1999/03/31 10:59:20 rassmann
95 * Returning Success instead of DupAddr if address shall be overridden
98 * Revision 1.31 1999/01/14 16:18:17 rassmann
99 * Corrected multicast initialization.
101 * Revision 1.30 1999/01/04 10:30:35 rassmann
102 * SkAddrOverride only possible after SK_INIT_IO phase.
104 * Revision 1.29 1998/12/29 13:13:10 rassmann
105 * An address override is now preserved in the SK_INIT_IO phase.
106 * All functions return an int now.
107 * Extended parameter checking.
109 * Revision 1.28 1998/12/01 11:45:53 rassmann
112 * Revision 1.27 1998/12/01 09:22:49 rassmann
113 * SkAddrMcAdd and SkAddrMcUpdate returned SK_MC_FILTERING_INEXACT
116 * Revision 1.26 1998/11/24 12:39:44 rassmann
117 * Reserved multicast entry for BPDU address.
118 * 13 multicast entries left for protocol.
120 * Revision 1.25 1998/11/17 16:54:23 rassmann
121 * Using exact match for up to 14 multicast addresses.
122 * Still receiving all multicasts if more addresses are added.
124 * Revision 1.24 1998/11/13 17:24:31 rassmann
125 * Changed return value of SkAddrOverride to int.
127 * Revision 1.23 1998/11/13 16:56:18 rassmann
128 * Added macro SK_ADDR_COMPARE.
129 * Changed return type of SkAddrOverride to SK_BOOL.
131 * Revision 1.22 1998/11/04 17:06:17 rassmann
132 * Corrected McUpdate and PromiscuousChange functions.
134 * Revision 1.21 1998/10/29 14:34:04 rassmann
135 * Clearing SK_ADDR struct at startup.
137 * Revision 1.20 1998/10/28 18:16:34 rassmann
138 * Avoiding I/Os before SK_INIT_RUN level.
139 * Aligning InexactFilter.
141 * Revision 1.19 1998/10/28 11:29:28 rassmann
142 * Programming physical address in SkAddrMcUpdate.
143 * Corrected programming of exact match entries.
145 * Revision 1.18 1998/10/28 10:34:48 rassmann
146 * Corrected reading of physical addresses.
148 * Revision 1.17 1998/10/28 10:26:13 rassmann
149 * Getting ports' current MAC addresses from EPROM now.
150 * Added debug output.
152 * Revision 1.16 1998/10/27 16:20:12 rassmann
153 * Reading MAC address byte by byte.
155 * Revision 1.15 1998/10/22 11:39:09 rassmann
156 * Corrected signed/unsigned mismatches.
158 * Revision 1.14 1998/10/19 17:12:35 rassmann
159 * Syntax corrections.
161 * Revision 1.13 1998/10/19 17:02:19 rassmann
162 * Now reading permanent MAC addresses from CRF.
164 * Revision 1.12 1998/10/15 15:15:48 rassmann
165 * Changed Flags Parameters from SK_U8 to int.
168 * Revision 1.11 1998/09/24 19:15:12 rassmann
171 * Revision 1.10 1998/09/18 20:18:54 rassmann
173 * Implemented swapping.
175 * Revision 1.9 1998/09/16 11:32:00 rassmann
176 * Including skdrv1st.h again. :(
178 * Revision 1.8 1998/09/16 11:09:34 rassmann
179 * Syntax corrections.
181 * Revision 1.7 1998/09/14 17:06:34 rassmann
184 * Revision 1.6 1998/09/07 08:45:41 rassmann
185 * Syntax corrections.
187 * Revision 1.5 1998/09/04 19:40:19 rassmann
188 * Interface enhancements.
190 * Revision 1.4 1998/09/04 12:14:12 rassmann
193 * Revision 1.3 1998/09/02 16:56:40 rassmann
196 * Revision 1.2 1998/08/27 14:26:09 rassmann
199 * Revision 1.1 1998/08/21 08:30:22 rassmann
200 * First public version.
202 ******************************************************************************/
204 /******************************************************************************
208 * This module is intended to manage multicast addresses, address override,
209 * and promiscuous mode on GEnesis and Yukon adapters.
212 * port address: physical MAC address
213 * 1st exact match: logical MAC address (GEnesis only)
214 * 2nd exact match: RLMT multicast (GEnesis only)
215 * exact match 3-13: OS-specific multicasts (GEnesis only)
217 * Include File Hierarchy:
222 ******************************************************************************/
227 static const char SysKonnectFileId[] =
228 "@(#) $Id$ (C) SysKonnect.";
229 #endif /* !defined(lint) */
234 #error C++ is not yet supported.
236 #endif /* cplusplus */
238 #include "h/skdrv1st.h"
239 #include "h/skdrv2nd.h"
241 /* defines ********************************************************************/
244 #define XMAC_POLY 0xEDB88320UL /* CRC32-Poly - XMAC: Little Endian */
245 #define GMAC_POLY 0x04C11DB7L /* CRC16-Poly - GMAC: Little Endian */
246 #define HASH_BITS 6 /* #bits in hash */
247 #define SK_MC_BIT 0x01
249 /* Error numbers and messages. */
251 #define SKERR_ADDR_E001 (SK_ERRBASE_ADDR + 0)
252 #define SKERR_ADDR_E001MSG "Bad Flags."
253 #define SKERR_ADDR_E002 (SKERR_ADDR_E001 + 1)
254 #define SKERR_ADDR_E002MSG "New Error."
256 /* typedefs *******************************************************************/
260 /* global variables ***********************************************************/
262 /* 64-bit hash values with all bits set. */
264 SK_U16 OnesHash[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
266 /* local variables ************************************************************/
269 static int Next0[SK_MAX_MACS] = {0, 0};
272 /* functions ******************************************************************/
274 /******************************************************************************
276 * SkAddrInit - initialize data, set state to init
283 * This routine clears the multicast tables and resets promiscuous mode.
284 * Some entries are reserved for the "logical MAC address", the
285 * SK-RLMT multicast address, and the BPDU multicast address.
291 * All permanent MAC addresses are read from EPROM.
292 * If the current MAC addresses are not already set in software,
293 * they are set to the values of the permanent addresses.
294 * The current addresses are written to the corresponding MAC.
309 SK_AC *pAC, /* the adapter context */
310 SK_IOC IoC, /* I/O context */
311 int Level) /* initialization level */
317 SK_ADDR_PORT *pAPort;
321 SK_MEMSET((char *) &pAC->Addr, 0, sizeof(SK_ADDR));
323 for (i = 0; i < SK_MAX_MACS; i++) {
324 pAPort = &pAC->Addr.Port[i];
325 pAPort->PromMode = SK_PROM_MODE_NONE;
327 pAPort->FirstExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
328 pAPort->FirstExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
329 pAPort->NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
330 pAPort->NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
333 for (i = 0; i < SK_MAX_MACS; i++) {
334 if (pAC->Addr.Port[i].NextExactMatchRlmt <
335 SK_ADDR_FIRST_MATCH_RLMT) {
340 /* pAC->Addr.InitDone = SK_INIT_DATA; */
344 for (i = 0; i < SK_MAX_NETS; i++) {
345 pAC->Addr.Net[i].ActivePort = pAC->Rlmt.Net[i].ActivePort;
348 for (i = 0; i < SK_MAX_MACS; i++) {
349 if (pAC->Addr.Port[i].NextExactMatchRlmt <
350 SK_ADDR_FIRST_MATCH_RLMT) {
356 /* Read permanent logical MAC address from Control Register File. */
357 for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
358 InAddr = (SK_U8 *) &pAC->Addr.Net[0].PermanentMacAddress.a[j];
359 SK_IN8(IoC, B2_MAC_1 + j, InAddr);
362 if (!pAC->Addr.Net[0].CurrentMacAddressSet) {
363 /* Set the current logical MAC address to the permanent one. */
364 pAC->Addr.Net[0].CurrentMacAddress =
365 pAC->Addr.Net[0].PermanentMacAddress;
366 pAC->Addr.Net[0].CurrentMacAddressSet = SK_TRUE;
369 /* Set the current logical MAC address. */
370 pAC->Addr.Port[pAC->Addr.Net[0].ActivePort].Exact[0] =
371 pAC->Addr.Net[0].CurrentMacAddress;
373 /* Set logical MAC address for net 2 to (log | 3). */
374 if (!pAC->Addr.Net[1].CurrentMacAddressSet) {
375 pAC->Addr.Net[1].PermanentMacAddress =
376 pAC->Addr.Net[0].PermanentMacAddress;
377 pAC->Addr.Net[1].PermanentMacAddress.a[5] |= 3;
378 /* Set the current logical MAC address to the permanent one. */
379 pAC->Addr.Net[1].CurrentMacAddress =
380 pAC->Addr.Net[1].PermanentMacAddress;
381 pAC->Addr.Net[1].CurrentMacAddressSet = SK_TRUE;
383 #endif /* SK_MAX_NETS > 1 */
386 for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
387 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
388 ("Permanent MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
390 pAC->Addr.Net[i].PermanentMacAddress.a[0],
391 pAC->Addr.Net[i].PermanentMacAddress.a[1],
392 pAC->Addr.Net[i].PermanentMacAddress.a[2],
393 pAC->Addr.Net[i].PermanentMacAddress.a[3],
394 pAC->Addr.Net[i].PermanentMacAddress.a[4],
395 pAC->Addr.Net[i].PermanentMacAddress.a[5]))
397 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
398 ("Logical MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
400 pAC->Addr.Net[i].CurrentMacAddress.a[0],
401 pAC->Addr.Net[i].CurrentMacAddress.a[1],
402 pAC->Addr.Net[i].CurrentMacAddress.a[2],
403 pAC->Addr.Net[i].CurrentMacAddress.a[3],
404 pAC->Addr.Net[i].CurrentMacAddress.a[4],
405 pAC->Addr.Net[i].CurrentMacAddress.a[5]))
409 for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
410 pAPort = &pAC->Addr.Port[i];
412 /* Read permanent port addresses from Control Register File. */
413 for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
414 InAddr = (SK_U8 *) &pAPort->PermanentMacAddress.a[j];
415 SK_IN8(IoC, B2_MAC_2 + 8 * i + j, InAddr);
418 if (!pAPort->CurrentMacAddressSet) {
420 * Set the current and previous physical MAC address
421 * of this port to its permanent MAC address.
423 pAPort->CurrentMacAddress = pAPort->PermanentMacAddress;
424 pAPort->PreviousMacAddress = pAPort->PermanentMacAddress;
425 pAPort->CurrentMacAddressSet = SK_TRUE;
428 /* Set port's current physical MAC address. */
429 OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
431 if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
432 XM_OUTADDR(IoC, i, XM_SA, OutAddr);
435 GM_OUTADDR(IoC, i, GM_SRC_ADDR_1L, OutAddr);
438 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
439 ("SkAddrInit: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
440 pAPort->PermanentMacAddress.a[0],
441 pAPort->PermanentMacAddress.a[1],
442 pAPort->PermanentMacAddress.a[2],
443 pAPort->PermanentMacAddress.a[3],
444 pAPort->PermanentMacAddress.a[4],
445 pAPort->PermanentMacAddress.a[5]))
447 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
448 ("SkAddrInit: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
449 pAPort->CurrentMacAddress.a[0],
450 pAPort->CurrentMacAddress.a[1],
451 pAPort->CurrentMacAddress.a[2],
452 pAPort->CurrentMacAddress.a[3],
453 pAPort->CurrentMacAddress.a[4],
454 pAPort->CurrentMacAddress.a[5]))
457 /* pAC->Addr.InitDone = SK_INIT_IO; */
462 for (i = 0; i < SK_MAX_MACS; i++) {
463 if (pAC->Addr.Port[i].NextExactMatchRlmt <
464 SK_ADDR_FIRST_MATCH_RLMT) {
470 /* pAC->Addr.InitDone = SK_INIT_RUN; */
477 return (SK_ADDR_SUCCESS);
482 /******************************************************************************
484 * SkAddrMcClear - clear the multicast table
487 * This routine clears the multicast table.
489 * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
492 * It calls either SkAddrXmacMcClear or SkAddrGmacMcClear, according
493 * to the adapter in use. The real work is done there.
497 * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
498 * may be called after SK_INIT_IO without limitation
502 * SK_ADDR_ILLEGAL_PORT
505 SK_AC *pAC, /* adapter context */
506 SK_IOC IoC, /* I/O context */
507 SK_U32 PortNumber, /* Index of affected port */
508 int Flags) /* permanent/non-perm, sw-only */
512 if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
513 return (SK_ADDR_ILLEGAL_PORT);
516 if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
517 ReturnCode = SkAddrXmacMcClear(pAC, IoC, PortNumber, Flags);
520 ReturnCode = SkAddrGmacMcClear(pAC, IoC, PortNumber, Flags);
525 } /* SkAddrMcClear */
528 /******************************************************************************
530 * SkAddrXmacMcClear - clear the multicast table
533 * This routine clears the multicast table
534 * (either entry 2 or entries 3-16 and InexactFilter) of the given port.
535 * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
540 * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
541 * may be called after SK_INIT_IO without limitation
545 * SK_ADDR_ILLEGAL_PORT
547 int SkAddrXmacMcClear(
548 SK_AC *pAC, /* adapter context */
549 SK_IOC IoC, /* I/O context */
550 SK_U32 PortNumber, /* Index of affected port */
551 int Flags) /* permanent/non-perm, sw-only */
555 if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
557 /* Clear RLMT multicast addresses. */
558 pAC->Addr.Port[PortNumber].NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
560 else { /* not permanent => DRV */
562 /* Clear InexactFilter */
563 for (i = 0; i < 8; i++) {
564 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
567 /* Clear DRV multicast addresses. */
569 pAC->Addr.Port[PortNumber].NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
572 if (!(Flags & SK_MC_SW_ONLY)) {
573 (void) SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
576 return (SK_ADDR_SUCCESS);
578 } /* SkAddrXmacMcClear */
581 /******************************************************************************
583 * SkAddrGmacMcClear - clear the multicast table
586 * This routine clears the multicast hashing table (InexactFilter)
587 * (either the RLMT or the driver bits) of the given port.
589 * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
594 * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
595 * may be called after SK_INIT_IO without limitation
599 * SK_ADDR_ILLEGAL_PORT
601 int SkAddrGmacMcClear(
602 SK_AC *pAC, /* adapter context */
603 SK_IOC IoC, /* I/O context */
604 SK_U32 PortNumber, /* Index of affected port */
605 int Flags) /* permanent/non-perm, sw-only */
610 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
611 ("GMAC InexactFilter (not cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
612 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0],
613 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1],
614 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2],
615 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3],
616 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
617 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
618 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
619 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]))
622 /* Clear InexactFilter */
623 for (i = 0; i < 8; i++) {
624 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
627 if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
629 /* Copy DRV bits to InexactFilter. */
630 for (i = 0; i < 8; i++) {
631 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
632 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
634 /* Clear InexactRlmtFilter. */
635 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i] = 0;
639 else { /* not permanent => DRV */
641 /* Copy RLMT bits to InexactFilter. */
642 for (i = 0; i < 8; i++) {
643 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
644 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
646 /* Clear InexactDrvFilter. */
647 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i] = 0;
652 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
653 ("GMAC InexactFilter (cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
654 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0],
655 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1],
656 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2],
657 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3],
658 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
659 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
660 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
661 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]))
664 if (!(Flags & SK_MC_SW_ONLY)) {
665 (void) SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
668 return (SK_ADDR_SUCCESS);
670 } /* SkAddrGmacMcClear */
672 #ifndef SK_ADDR_CHEAT
674 /******************************************************************************
676 * SkXmacMcHash - hash multicast address
679 * This routine computes the hash value for a multicast address.
680 * A CRC32 algorithm is used.
683 * The code was adapted from the XaQti data sheet.
689 * Hash value of multicast address.
692 unsigned char *pMc) /* Multicast address */
700 for (Idx = 0; Idx < SK_MAC_ADDR_LEN; Idx++) {
702 for (Bit = 0; Bit < 8; Bit++, Data >>= 1) {
703 Crc = (Crc >> 1) ^ (((Crc ^ Data) & 1) ? XMAC_POLY : 0);
707 return (Crc & ((1 << HASH_BITS) - 1));
712 /******************************************************************************
714 * SkGmacMcHash - hash multicast address
717 * This routine computes the hash value for a multicast address.
718 * A CRC16 algorithm is used.
727 * Hash value of multicast address.
730 unsigned char *pMc) /* Multicast address */
739 for (Byte = 0; Byte < 6; Byte++) {
741 Data = (SK_U32) pMc[Byte];
743 /* Change bit order in byte. */
745 for (Bit = 0; Bit < 8; Bit++) {
747 Data |= 1L << (7 - Bit);
750 Data &= ~(1L << (7 - Bit));
756 for (Bit = 0; Bit < 8; Bit++) {
757 if (Crc & 0x80000000) {
758 Crc = (Crc << 1) ^ GMAC_POLY;
766 return (Crc & ((1 << HASH_BITS) - 1));
770 #endif /* not SK_ADDR_CHEAT */
772 /******************************************************************************
774 * SkAddrMcAdd - add a multicast address to a port
777 * This routine enables reception for a given address on the given port.
779 * It calls either SkAddrXmacMcAdd or SkAddrGmacMcAdd, according to the
780 * adapter in use. The real work is done there.
783 * The return code is only valid for SK_PROM_MODE_NONE.
787 * may be called after SK_INIT_DATA
790 * SK_MC_FILTERING_EXACT
791 * SK_MC_FILTERING_INEXACT
792 * SK_MC_ILLEGAL_ADDRESS
794 * SK_MC_RLMT_OVERFLOW
797 SK_AC *pAC, /* adapter context */
798 SK_IOC IoC, /* I/O context */
799 SK_U32 PortNumber, /* Port Number */
800 SK_MAC_ADDR *pMc, /* multicast address to be added */
801 int Flags) /* permanent/non-permanent */
805 if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
806 return (SK_ADDR_ILLEGAL_PORT);
809 if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
810 ReturnCode = SkAddrXmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
813 ReturnCode = SkAddrGmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
821 /******************************************************************************
823 * SkAddrXmacMcAdd - add a multicast address to a port
826 * This routine enables reception for a given address on the given port.
829 * The return code is only valid for SK_PROM_MODE_NONE.
831 * The multicast bit is only checked if there are no free exact match
836 * may be called after SK_INIT_DATA
839 * SK_MC_FILTERING_EXACT
840 * SK_MC_FILTERING_INEXACT
841 * SK_MC_ILLEGAL_ADDRESS
842 * SK_MC_RLMT_OVERFLOW
845 SK_AC *pAC, /* adapter context */
846 SK_IOC IoC, /* I/O context */
847 SK_U32 PortNumber, /* Port Number */
848 SK_MAC_ADDR *pMc, /* multicast address to be added */
849 int Flags) /* permanent/non-permanent */
853 #ifndef SK_ADDR_CHEAT
855 #endif /* !defined(SK_ADDR_CHEAT) */
857 if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
859 if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt <
860 SK_ADDR_FIRST_MATCH_RLMT) {
861 Next0[PortNumber] |= 1;
862 return (SK_MC_RLMT_OVERFLOW);
866 if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt >
867 SK_ADDR_LAST_MATCH_RLMT) {
868 return (SK_MC_RLMT_OVERFLOW);
871 /* Set a RLMT multicast address. */
873 pAC->Addr.Port[PortNumber].Exact[
874 pAC->Addr.Port[PortNumber].NextExactMatchRlmt++] = *pMc;
876 return (SK_MC_FILTERING_EXACT);
880 if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <
881 SK_ADDR_FIRST_MATCH_DRV) {
882 Next0[PortNumber] |= 2;
883 return (SK_MC_RLMT_OVERFLOW);
887 if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
889 /* Set exact match entry. */
890 pAC->Addr.Port[PortNumber].Exact[
891 pAC->Addr.Port[PortNumber].NextExactMatchDrv++] = *pMc;
893 /* Clear InexactFilter */
894 for (i = 0; i < 8; i++) {
895 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
899 if (!(pMc->a[0] & SK_MC_BIT)) {
900 /* Hashing only possible with multicast addresses. */
901 return (SK_MC_ILLEGAL_ADDRESS);
903 #ifndef SK_ADDR_CHEAT
904 /* Compute hash value of address. */
905 HashBit = 63 - SkXmacMcHash(&pMc->a[0]);
907 /* Add bit to InexactFilter. */
908 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[HashBit / 8] |=
910 #else /* SK_ADDR_CHEAT */
911 /* Set all bits in InexactFilter. */
912 for (i = 0; i < 8; i++) {
913 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
915 #endif /* SK_ADDR_CHEAT */
918 for (Inexact = 0, i = 0; i < 8; i++) {
919 Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
922 if (Inexact == 0 && pAC->Addr.Port[PortNumber].PromMode == 0) {
923 return (SK_MC_FILTERING_EXACT);
926 return (SK_MC_FILTERING_INEXACT);
929 } /* SkAddrXmacMcAdd */
932 /******************************************************************************
934 * SkAddrGmacMcAdd - add a multicast address to a port
937 * This routine enables reception for a given address on the given port.
940 * The return code is only valid for SK_PROM_MODE_NONE.
944 * may be called after SK_INIT_DATA
947 * SK_MC_FILTERING_INEXACT
948 * SK_MC_ILLEGAL_ADDRESS
951 SK_AC *pAC, /* adapter context */
952 SK_IOC IoC, /* I/O context */
953 SK_U32 PortNumber, /* Port Number */
954 SK_MAC_ADDR *pMc, /* multicast address to be added */
955 int Flags) /* permanent/non-permanent */
958 #ifndef SK_ADDR_CHEAT
960 #endif /* !defined(SK_ADDR_CHEAT) */
962 if (!(pMc->a[0] & SK_MC_BIT)) {
963 /* Hashing only possible with multicast addresses. */
964 return (SK_MC_ILLEGAL_ADDRESS);
967 #ifndef SK_ADDR_CHEAT
969 /* Compute hash value of address. */
970 HashBit = SkGmacMcHash(&pMc->a[0]);
972 if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
974 /* Add bit to InexactRlmtFilter. */
975 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[HashBit / 8] |=
978 /* Copy bit to InexactFilter. */
979 for (i = 0; i < 8; i++) {
980 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
981 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
984 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
985 ("GMAC InexactRlmtFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
986 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[0],
987 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[1],
988 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[2],
989 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[3],
990 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[4],
991 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[5],
992 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[6],
993 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[7]))
996 else { /* not permanent => DRV */
998 /* Add bit to InexactDrvFilter. */
999 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[HashBit / 8] |=
1002 /* Copy bit to InexactFilter. */
1003 for (i = 0; i < 8; i++) {
1004 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
1005 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
1008 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1009 ("GMAC InexactDrvFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
1010 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[0],
1011 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[1],
1012 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[2],
1013 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[3],
1014 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[4],
1015 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[5],
1016 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[6],
1017 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[7]))
1021 #else /* SK_ADDR_CHEAT */
1023 /* Set all bits in InexactFilter. */
1024 for (i = 0; i < 8; i++) {
1025 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
1027 #endif /* SK_ADDR_CHEAT */
1029 return (SK_MC_FILTERING_INEXACT);
1031 } /* SkAddrGmacMcAdd */
1034 /******************************************************************************
1036 * SkAddrMcUpdate - update the HW MC address table and set the MAC address
1039 * This routine enables reception of the addresses contained in a local
1040 * table for a given port.
1041 * It also programs the port's current physical MAC address.
1043 * It calls either SkAddrXmacMcUpdate or SkAddrGmacMcUpdate, according
1044 * to the adapter in use. The real work is done there.
1047 * The return code is only valid for SK_PROM_MODE_NONE.
1051 * may be called after SK_INIT_IO
1054 * SK_MC_FILTERING_EXACT
1055 * SK_MC_FILTERING_INEXACT
1056 * SK_ADDR_ILLEGAL_PORT
1059 SK_AC *pAC, /* adapter context */
1060 SK_IOC IoC, /* I/O context */
1061 SK_U32 PortNumber) /* Port Number */
1065 if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
1066 return (SK_ADDR_ILLEGAL_PORT);
1069 if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
1070 ReturnCode = SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
1073 ReturnCode = SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
1076 return (ReturnCode);
1078 } /* SkAddrMcUpdate */
1081 /******************************************************************************
1083 * SkAddrXmacMcUpdate - update the HW MC address table and set the MAC address
1086 * This routine enables reception of the addresses contained in a local
1087 * table for a given port.
1088 * It also programs the port's current physical MAC address.
1091 * The return code is only valid for SK_PROM_MODE_NONE.
1095 * may be called after SK_INIT_IO
1098 * SK_MC_FILTERING_EXACT
1099 * SK_MC_FILTERING_INEXACT
1100 * SK_ADDR_ILLEGAL_PORT
1102 int SkAddrXmacMcUpdate(
1103 SK_AC *pAC, /* adapter context */
1104 SK_IOC IoC, /* I/O context */
1105 SK_U32 PortNumber) /* Port Number */
1110 SK_ADDR_PORT *pAPort;
1112 SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1113 ("SkAddrXmacMcUpdate on Port %u.\n", PortNumber))
1115 pAPort = &pAC->Addr.Port[PortNumber];
1118 SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1119 ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
1122 /* Start with 0 to also program the logical MAC address. */
1123 for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
1124 /* Set exact match address i on XMAC */
1125 OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
1126 XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
1129 /* Clear other permanent exact match addresses on XMAC */
1130 if (pAPort->NextExactMatchRlmt <= SK_ADDR_LAST_MATCH_RLMT) {
1132 SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchRlmt,
1133 SK_ADDR_LAST_MATCH_RLMT);
1136 for (i = pAPort->FirstExactMatchDrv; i < pAPort->NextExactMatchDrv; i++) {
1137 OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
1138 XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
1141 /* Clear other non-permanent exact match addresses on XMAC */
1142 if (pAPort->NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
1144 SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchDrv,
1145 SK_ADDR_LAST_MATCH_DRV);
1148 for (Inexact = 0, i = 0; i < 8; i++) {
1149 Inexact |= pAPort->InexactFilter.Bytes[i];
1152 if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
1154 /* Set all bits in 64-bit hash register. */
1155 XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
1157 /* Enable Hashing */
1158 SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
1160 else if (Inexact != 0) {
1162 /* Set 64-bit hash register to InexactFilter. */
1163 XM_OUTHASH(IoC, PortNumber, XM_HSM, &pAPort->InexactFilter.Bytes[0]);
1165 /* Enable Hashing */
1166 SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
1169 /* Disable Hashing */
1170 SkMacHashing(pAC, IoC, PortNumber, SK_FALSE);
1173 if (pAPort->PromMode != SK_PROM_MODE_NONE) {
1174 (void) SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
1177 /* Set port's current physical MAC address. */
1178 OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
1180 XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
1183 for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
1187 /* Get exact match address i from port PortNumber. */
1188 InAddr = (SK_U16 *) &InAddr8[0];
1190 XM_INADDR(IoC, PortNumber, XM_EXM(i), InAddr);
1192 SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1193 ("SkAddrXmacMcUpdate: MC address %d on Port %u: ",
1194 "%02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x\n",
1203 pAPort->Exact[i].a[0],
1204 pAPort->Exact[i].a[1],
1205 pAPort->Exact[i].a[2],
1206 pAPort->Exact[i].a[3],
1207 pAPort->Exact[i].a[4],
1208 pAPort->Exact[i].a[5]))
1212 /* Determine return value. */
1213 if (Inexact == 0 && pAPort->PromMode == 0) {
1214 return (SK_MC_FILTERING_EXACT);
1217 return (SK_MC_FILTERING_INEXACT);
1220 } /* SkAddrXmacMcUpdate */
1223 /******************************************************************************
1225 * SkAddrGmacMcUpdate - update the HW MC address table and set the MAC address
1228 * This routine enables reception of the addresses contained in a local
1229 * table for a given port.
1230 * It also programs the port's current physical MAC address.
1233 * The return code is only valid for SK_PROM_MODE_NONE.
1237 * may be called after SK_INIT_IO
1240 * SK_MC_FILTERING_EXACT
1241 * SK_MC_FILTERING_INEXACT
1242 * SK_ADDR_ILLEGAL_PORT
1244 int SkAddrGmacMcUpdate(
1245 SK_AC *pAC, /* adapter context */
1246 SK_IOC IoC, /* I/O context */
1247 SK_U32 PortNumber) /* Port Number */
1252 SK_ADDR_PORT *pAPort;
1254 SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1255 ("SkAddrGmacMcUpdate on Port %u.\n", PortNumber))
1257 pAPort = &pAC->Addr.Port[PortNumber];
1260 SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1261 ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
1264 for (Inexact = 0, i = 0; i < 8; i++) {
1265 Inexact |= pAPort->InexactFilter.Bytes[i];
1268 /* Set 64-bit hash register to InexactFilter. */
1269 GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1,
1270 &pAPort->InexactFilter.Bytes[0]);
1272 if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
1274 /* Set all bits in 64-bit hash register. */
1275 GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
1277 /* Enable Hashing */
1278 SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
1281 /* Enable Hashing. */
1282 SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
1285 if (pAPort->PromMode != SK_PROM_MODE_NONE) {
1286 (void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
1289 /* Set port's current physical MAC address. */
1290 OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
1291 GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
1293 /* Set port's current logical MAC address. */
1294 OutAddr = (SK_U16 *) &pAPort->Exact[0].a[0];
1295 GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_2L, OutAddr);
1298 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1299 ("SkAddrGmacMcUpdate: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
1300 pAPort->Exact[0].a[0],
1301 pAPort->Exact[0].a[1],
1302 pAPort->Exact[0].a[2],
1303 pAPort->Exact[0].a[3],
1304 pAPort->Exact[0].a[4],
1305 pAPort->Exact[0].a[5]))
1307 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1308 ("SkAddrGmacMcUpdate: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
1309 pAPort->CurrentMacAddress.a[0],
1310 pAPort->CurrentMacAddress.a[1],
1311 pAPort->CurrentMacAddress.a[2],
1312 pAPort->CurrentMacAddress.a[3],
1313 pAPort->CurrentMacAddress.a[4],
1314 pAPort->CurrentMacAddress.a[5]))
1317 /* Determine return value. */
1318 if (Inexact == 0 && pAPort->PromMode == 0) {
1319 return (SK_MC_FILTERING_EXACT);
1322 return (SK_MC_FILTERING_INEXACT);
1325 } /* SkAddrGmacMcUpdate */
1328 /******************************************************************************
1330 * SkAddrOverride - override a port's MAC address
1333 * This routine overrides the MAC address of one port.
1337 * may be called after SK_INIT_IO
1340 * SK_ADDR_SUCCESS if successful.
1341 * SK_ADDR_DUPLICATE_ADDRESS if duplicate MAC address.
1342 * SK_ADDR_MULTICAST_ADDRESS if multicast or broadcast address.
1343 * SK_ADDR_TOO_EARLY if SK_INIT_IO was not executed before.
1346 SK_AC *pAC, /* adapter context */
1347 SK_IOC IoC, /* I/O context */
1348 SK_U32 PortNumber, /* Port Number */
1349 SK_MAC_ADDR *pNewAddr, /* new MAC address */
1350 int Flags) /* logical/physical MAC address */
1357 NetNumber = pAC->Rlmt.Port[PortNumber].Net->NetNumber;
1359 if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
1360 return (SK_ADDR_ILLEGAL_PORT);
1363 if (pNewAddr != NULL && (pNewAddr->a[0] & SK_MC_BIT) != 0) {
1364 return (SK_ADDR_MULTICAST_ADDRESS);
1367 if (!pAC->Addr.Net[NetNumber].CurrentMacAddressSet) {
1368 return (SK_ADDR_TOO_EARLY);
1371 if (Flags & SK_ADDR_SET_LOGICAL) { /* Activate logical MAC address. */
1372 /* Parameter *pNewAddr is ignored. */
1373 for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
1374 if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
1375 return (SK_ADDR_TOO_EARLY);
1379 /* Set PortNumber to number of net's active port. */
1380 PortNumber = pAC->Rlmt.Net[NetNumber].
1381 Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
1383 pAC->Addr.Port[PortNumber].Exact[0] =
1384 pAC->Addr.Net[NetNumber].CurrentMacAddress;
1386 /* Write address to first exact match entry of active port. */
1387 (void) SkAddrMcUpdate(pAC, IoC, PortNumber);
1389 else if (Flags & SK_ADDR_CLEAR_LOGICAL) {
1390 /* Deactivate logical MAC address. */
1391 /* Parameter *pNewAddr is ignored. */
1392 for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
1393 if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
1394 return (SK_ADDR_TOO_EARLY);
1398 /* Set PortNumber to number of net's active port. */
1399 PortNumber = pAC->Rlmt.Net[NetNumber].
1400 Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
1402 for (i = 0; i < SK_MAC_ADDR_LEN; i++ ) {
1403 pAC->Addr.Port[PortNumber].Exact[0].a[i] = 0;
1406 /* Write address to first exact match entry of active port. */
1407 (void) SkAddrMcUpdate(pAC, IoC, PortNumber);
1409 else if (Flags & SK_ADDR_PHYSICAL_ADDRESS) { /* Physical MAC address. */
1410 if (SK_ADDR_EQUAL(pNewAddr->a,
1411 pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
1412 return (SK_ADDR_DUPLICATE_ADDRESS);
1415 for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
1416 if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
1417 return (SK_ADDR_TOO_EARLY);
1420 if (SK_ADDR_EQUAL(pNewAddr->a,
1421 pAC->Addr.Port[i].CurrentMacAddress.a)) {
1422 if (i == PortNumber) {
1423 return (SK_ADDR_SUCCESS);
1426 return (SK_ADDR_DUPLICATE_ADDRESS);
1431 pAC->Addr.Port[PortNumber].PreviousMacAddress =
1432 pAC->Addr.Port[PortNumber].CurrentMacAddress;
1433 pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
1435 /* Change port's physical MAC address. */
1436 OutAddr = (SK_U16 *) pNewAddr;
1438 if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
1439 XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
1442 GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
1445 /* Report address change to RLMT. */
1446 Para.Para32[0] = PortNumber;
1447 Para.Para32[0] = -1;
1448 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
1450 else { /* Logical MAC address. */
1451 if (SK_ADDR_EQUAL(pNewAddr->a,
1452 pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
1453 return (SK_ADDR_SUCCESS);
1456 for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
1457 if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
1458 return (SK_ADDR_TOO_EARLY);
1461 if (SK_ADDR_EQUAL(pNewAddr->a,
1462 pAC->Addr.Port[i].CurrentMacAddress.a)) {
1463 return (SK_ADDR_DUPLICATE_ADDRESS);
1468 * In case that the physical and the logical MAC addresses are equal
1469 * we must also change the physical MAC address here.
1470 * In this case we have an adapter which initially was programmed with
1471 * two identical MAC addresses.
1473 if (SK_ADDR_EQUAL(pAC->Addr.Port[PortNumber].CurrentMacAddress.a,
1474 pAC->Addr.Port[PortNumber].Exact[0].a)) {
1476 pAC->Addr.Port[PortNumber].PreviousMacAddress =
1477 pAC->Addr.Port[PortNumber].CurrentMacAddress;
1478 pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
1480 /* Report address change to RLMT. */
1481 Para.Para32[0] = PortNumber;
1482 Para.Para32[0] = -1;
1483 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
1486 /* Set PortNumber to number of net's active port. */
1487 PortNumber = pAC->Rlmt.Net[NetNumber].
1488 Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
1490 pAC->Addr.Net[NetNumber].CurrentMacAddress = *pNewAddr;
1491 pAC->Addr.Port[PortNumber].Exact[0] = *pNewAddr;
1493 SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1494 ("SkAddrOverride: Permanent MAC Address: %02X %02X %02X %02X %02X %02X\n",
1495 pAC->Addr.Net[NetNumber].PermanentMacAddress.a[0],
1496 pAC->Addr.Net[NetNumber].PermanentMacAddress.a[1],
1497 pAC->Addr.Net[NetNumber].PermanentMacAddress.a[2],
1498 pAC->Addr.Net[NetNumber].PermanentMacAddress.a[3],
1499 pAC->Addr.Net[NetNumber].PermanentMacAddress.a[4],
1500 pAC->Addr.Net[NetNumber].PermanentMacAddress.a[5]))
1502 SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1503 ("SkAddrOverride: New logical MAC Address: %02X %02X %02X %02X %02X %02X\n",
1504 pAC->Addr.Net[NetNumber].CurrentMacAddress.a[0],
1505 pAC->Addr.Net[NetNumber].CurrentMacAddress.a[1],
1506 pAC->Addr.Net[NetNumber].CurrentMacAddress.a[2],
1507 pAC->Addr.Net[NetNumber].CurrentMacAddress.a[3],
1508 pAC->Addr.Net[NetNumber].CurrentMacAddress.a[4],
1509 pAC->Addr.Net[NetNumber].CurrentMacAddress.a[5]))
1512 /* Write address to first exact match entry of active port. */
1513 (void) SkAddrMcUpdate(pAC, IoC, PortNumber);
1516 return (SK_ADDR_SUCCESS);
1518 } /* SkAddrOverride */
1521 /******************************************************************************
1523 * SkAddrPromiscuousChange - set promiscuous mode for given port
1526 * This routine manages promiscuous mode:
1531 * It calls either SkAddrXmacPromiscuousChange or
1532 * SkAddrGmacPromiscuousChange, according to the adapter in use.
1533 * The real work is done there.
1537 * may be called after SK_INIT_IO
1541 * SK_ADDR_ILLEGAL_PORT
1543 int SkAddrPromiscuousChange(
1544 SK_AC *pAC, /* adapter context */
1545 SK_IOC IoC, /* I/O context */
1546 SK_U32 PortNumber, /* port whose promiscuous mode changes */
1547 int NewPromMode) /* new promiscuous mode */
1551 if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
1552 return (SK_ADDR_ILLEGAL_PORT);
1555 if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
1556 ReturnCode = SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
1559 ReturnCode = SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
1562 return (ReturnCode);
1564 } /* SkAddrPromiscuousChange */
1567 /******************************************************************************
1569 * SkAddrXmacPromiscuousChange - set promiscuous mode for given port
1572 * This routine manages promiscuous mode:
1579 * may be called after SK_INIT_IO
1583 * SK_ADDR_ILLEGAL_PORT
1585 int SkAddrXmacPromiscuousChange(
1586 SK_AC *pAC, /* adapter context */
1587 SK_IOC IoC, /* I/O context */
1588 SK_U32 PortNumber, /* port whose promiscuous mode changes */
1589 int NewPromMode) /* new promiscuous mode */
1592 SK_BOOL InexactModeBit;
1595 SK_FILTER64 HwInexactFilter;
1596 SK_U16 LoMode; /* Lower 16 bits of XMAC Mode Register. */
1597 int CurPromMode = SK_PROM_MODE_NONE;
1599 /* Read CurPromMode from Hardware. */
1600 XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
1602 if ((LoMode & XM_MD_ENA_PROM) != 0) {
1603 /* Promiscuous mode! */
1604 CurPromMode |= SK_PROM_MODE_LLC;
1607 for (Inexact = 0xFF, i = 0; i < 8; i++) {
1608 Inexact &= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
1610 if (Inexact == 0xFF) {
1611 CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
1614 /* Get InexactModeBit (bit XM_MD_ENA_HASH in mode register) */
1615 XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
1617 InexactModeBit = (LoMode & XM_MD_ENA_HASH) != 0;
1619 /* Read 64-bit hash register from XMAC */
1620 XM_INHASH(IoC, PortNumber, XM_HSM, &HwInexactFilter.Bytes[0]);
1622 for (HwInexact = 0xFF, i = 0; i < 8; i++) {
1623 HwInexact &= HwInexactFilter.Bytes[i];
1626 if (InexactModeBit && (HwInexact == 0xFF)) {
1627 CurPromMode |= SK_PROM_MODE_ALL_MC;
1631 pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
1633 if (NewPromMode == CurPromMode) {
1634 return (SK_ADDR_SUCCESS);
1637 if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
1638 !(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC. */
1640 /* Set all bits in 64-bit hash register. */
1641 XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
1643 /* Enable Hashing */
1644 SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
1646 else if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
1647 !(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm MC. */
1648 for (Inexact = 0, i = 0; i < 8; i++) {
1649 Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
1652 /* Disable Hashing */
1653 SkMacHashing(pAC, IoC, PortNumber, SK_FALSE);
1656 /* Set 64-bit hash register to InexactFilter. */
1657 XM_OUTHASH(IoC, PortNumber, XM_HSM,
1658 &pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
1660 /* Enable Hashing */
1661 SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
1665 if ((NewPromMode & SK_PROM_MODE_LLC) &&
1666 !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */
1667 /* Set the MAC in Promiscuous Mode */
1668 SkMacPromiscMode(pAC, IoC, PortNumber, SK_TRUE);
1670 else if ((CurPromMode & SK_PROM_MODE_LLC) &&
1671 !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC. */
1672 /* Clear Promiscuous Mode */
1673 SkMacPromiscMode(pAC, IoC, PortNumber, SK_FALSE);
1676 return (SK_ADDR_SUCCESS);
1678 } /* SkAddrXmacPromiscuousChange */
1681 /******************************************************************************
1683 * SkAddrGmacPromiscuousChange - set promiscuous mode for given port
1686 * This routine manages promiscuous mode:
1693 * may be called after SK_INIT_IO
1697 * SK_ADDR_ILLEGAL_PORT
1699 int SkAddrGmacPromiscuousChange(
1700 SK_AC *pAC, /* adapter context */
1701 SK_IOC IoC, /* I/O context */
1702 SK_U32 PortNumber, /* port whose promiscuous mode changes */
1703 int NewPromMode) /* new promiscuous mode */
1705 SK_U16 ReceiveControl; /* GMAC Receive Control Register */
1706 int CurPromMode = SK_PROM_MODE_NONE;
1708 /* Read CurPromMode from Hardware. */
1709 GM_IN16(IoC, PortNumber, GM_RX_CTRL, &ReceiveControl);
1711 if ((ReceiveControl & (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA)) == 0) {
1712 /* Promiscuous mode! */
1713 CurPromMode |= SK_PROM_MODE_LLC;
1716 if ((ReceiveControl & GM_RXCR_MCF_ENA) == 0) {
1717 /* All Multicast mode! */
1718 CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
1721 pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
1723 if (NewPromMode == CurPromMode) {
1724 return (SK_ADDR_SUCCESS);
1727 if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
1728 !(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC */
1730 /* Set all bits in 64-bit hash register. */
1731 GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
1733 /* Enable Hashing */
1734 SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
1737 if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
1738 !(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm. MC */
1740 /* Set 64-bit hash register to InexactFilter. */
1741 GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1,
1742 &pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
1744 /* Enable Hashing. */
1745 SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
1748 if ((NewPromMode & SK_PROM_MODE_LLC) &&
1749 !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */
1751 /* Set the MAC to Promiscuous Mode. */
1752 SkMacPromiscMode(pAC, IoC, PortNumber, SK_TRUE);
1754 else if ((CurPromMode & SK_PROM_MODE_LLC) &&
1755 !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC */
1757 /* Clear Promiscuous Mode. */
1758 SkMacPromiscMode(pAC, IoC, PortNumber, SK_FALSE);
1761 return (SK_ADDR_SUCCESS);
1763 } /* SkAddrGmacPromiscuousChange */
1766 /******************************************************************************
1768 * SkAddrSwap - swap address info
1771 * This routine swaps address info of two ports.
1775 * may be called after SK_INIT_IO
1779 * SK_ADDR_ILLEGAL_PORT
1782 SK_AC *pAC, /* adapter context */
1783 SK_IOC IoC, /* I/O context */
1784 SK_U32 FromPortNumber, /* Port1 Index */
1785 SK_U32 ToPortNumber) /* Port2 Index */
1789 SK_MAC_ADDR MacAddr;
1792 if (FromPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
1793 return (SK_ADDR_ILLEGAL_PORT);
1796 if (ToPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
1797 return (SK_ADDR_ILLEGAL_PORT);
1800 if (pAC->Rlmt.Port[FromPortNumber].Net != pAC->Rlmt.Port[ToPortNumber].Net) {
1801 return (SK_ADDR_ILLEGAL_PORT);
1806 * - Exact Match Entries (GEnesis and Yukon)
1807 * Yukon uses first entry for the logical MAC
1808 * address (stored in the second GMAC register).
1809 * - FirstExactMatchRlmt (GEnesis only)
1810 * - NextExactMatchRlmt (GEnesis only)
1811 * - FirstExactMatchDrv (GEnesis only)
1812 * - NextExactMatchDrv (GEnesis only)
1813 * - 64-bit filter (InexactFilter)
1814 * - Promiscuous Mode
1818 for (i = 0; i < SK_ADDR_EXACT_MATCHES; i++) {
1819 MacAddr = pAC->Addr.Port[FromPortNumber].Exact[i];
1820 pAC->Addr.Port[FromPortNumber].Exact[i] =
1821 pAC->Addr.Port[ToPortNumber].Exact[i];
1822 pAC->Addr.Port[ToPortNumber].Exact[i] = MacAddr;
1825 for (i = 0; i < 8; i++) {
1826 Byte = pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i];
1827 pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i] =
1828 pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i];
1829 pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i] = Byte;
1832 i = pAC->Addr.Port[FromPortNumber].PromMode;
1833 pAC->Addr.Port[FromPortNumber].PromMode = pAC->Addr.Port[ToPortNumber].PromMode;
1834 pAC->Addr.Port[ToPortNumber].PromMode = i;
1836 if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
1837 DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt;
1838 pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt =
1839 pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt;
1840 pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt = DWord;
1842 DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt;
1843 pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt =
1844 pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt;
1845 pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt = DWord;
1847 DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv;
1848 pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv =
1849 pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv;
1850 pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv = DWord;
1852 DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchDrv;
1853 pAC->Addr.Port[FromPortNumber].NextExactMatchDrv =
1854 pAC->Addr.Port[ToPortNumber].NextExactMatchDrv;
1855 pAC->Addr.Port[ToPortNumber].NextExactMatchDrv = DWord;
1858 /* CAUTION: Solution works if only ports of one adapter are in use. */
1859 for (i = 0; (SK_U32) i < pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].
1860 Net->NetNumber].NumPorts; i++) {
1861 if (pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
1862 Port[i]->PortNumber == ToPortNumber) {
1863 pAC->Addr.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
1865 /* 20001207 RA: Was "ToPortNumber;". */
1869 (void) SkAddrMcUpdate(pAC, IoC, FromPortNumber);
1870 (void) SkAddrMcUpdate(pAC, IoC, ToPortNumber);
1872 return (SK_ADDR_SUCCESS);
1878 #endif /* __cplusplus */