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 ******************************************************************************/
226 static const char SysKonnectFileId
[] =
227 "@(#) $Id: skaddr.c,v 1.48 2003/02/12 17:09:37 tschilli Exp $ (C) SysKonnect.";
228 #endif /* !defined(lint) */
233 #error C++ is not yet supported.
235 #endif /* cplusplus */
237 #include "h/skdrv1st.h"
238 #include "h/skdrv2nd.h"
240 /* defines ********************************************************************/
243 #define XMAC_POLY 0xEDB88320UL /* CRC32-Poly - XMAC: Little Endian */
244 #define GMAC_POLY 0x04C11DB7L /* CRC16-Poly - GMAC: Little Endian */
245 #define HASH_BITS 6 /* #bits in hash */
246 #define SK_MC_BIT 0x01
248 /* Error numbers and messages. */
250 #define SKERR_ADDR_E001 (SK_ERRBASE_ADDR + 0)
251 #define SKERR_ADDR_E001MSG "Bad Flags."
252 #define SKERR_ADDR_E002 (SKERR_ADDR_E001 + 1)
253 #define SKERR_ADDR_E002MSG "New Error."
255 /* typedefs *******************************************************************/
259 /* global variables ***********************************************************/
261 /* 64-bit hash values with all bits set. */
263 SK_U16 OnesHash
[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
265 /* local variables ************************************************************/
268 static int Next0
[SK_MAX_MACS
] = {0, 0};
271 /* functions ******************************************************************/
273 /******************************************************************************
275 * SkAddrInit - initialize data, set state to init
282 * This routine clears the multicast tables and resets promiscuous mode.
283 * Some entries are reserved for the "logical MAC address", the
284 * SK-RLMT multicast address, and the BPDU multicast address.
290 * All permanent MAC addresses are read from EPROM.
291 * If the current MAC addresses are not already set in software,
292 * they are set to the values of the permanent addresses.
293 * The current addresses are written to the corresponding MAC.
308 SK_AC
*pAC
, /* the adapter context */
309 SK_IOC IoC
, /* I/O context */
310 int Level
) /* initialization level */
316 SK_ADDR_PORT
*pAPort
;
320 SK_MEMSET((char *) &pAC
->Addr
, 0, sizeof(SK_ADDR
));
322 for (i
= 0; i
< SK_MAX_MACS
; i
++) {
323 pAPort
= &pAC
->Addr
.Port
[i
];
324 pAPort
->PromMode
= SK_PROM_MODE_NONE
;
326 pAPort
->FirstExactMatchRlmt
= SK_ADDR_FIRST_MATCH_RLMT
;
327 pAPort
->FirstExactMatchDrv
= SK_ADDR_FIRST_MATCH_DRV
;
328 pAPort
->NextExactMatchRlmt
= SK_ADDR_FIRST_MATCH_RLMT
;
329 pAPort
->NextExactMatchDrv
= SK_ADDR_FIRST_MATCH_DRV
;
332 for (i
= 0; i
< SK_MAX_MACS
; i
++) {
333 if (pAC
->Addr
.Port
[i
].NextExactMatchRlmt
<
334 SK_ADDR_FIRST_MATCH_RLMT
) {
339 /* pAC->Addr.InitDone = SK_INIT_DATA; */
343 for (i
= 0; i
< SK_MAX_NETS
; i
++) {
344 pAC
->Addr
.Net
[i
].ActivePort
= pAC
->Rlmt
.Net
[i
].ActivePort
;
347 for (i
= 0; i
< SK_MAX_MACS
; i
++) {
348 if (pAC
->Addr
.Port
[i
].NextExactMatchRlmt
<
349 SK_ADDR_FIRST_MATCH_RLMT
) {
355 /* Read permanent logical MAC address from Control Register File. */
356 for (j
= 0; j
< SK_MAC_ADDR_LEN
; j
++) {
357 InAddr
= (SK_U8
*) &pAC
->Addr
.Net
[0].PermanentMacAddress
.a
[j
];
358 SK_IN8(IoC
, B2_MAC_1
+ j
, InAddr
);
361 if (!pAC
->Addr
.Net
[0].CurrentMacAddressSet
) {
362 /* Set the current logical MAC address to the permanent one. */
363 pAC
->Addr
.Net
[0].CurrentMacAddress
=
364 pAC
->Addr
.Net
[0].PermanentMacAddress
;
365 pAC
->Addr
.Net
[0].CurrentMacAddressSet
= SK_TRUE
;
368 /* Set the current logical MAC address. */
369 pAC
->Addr
.Port
[pAC
->Addr
.Net
[0].ActivePort
].Exact
[0] =
370 pAC
->Addr
.Net
[0].CurrentMacAddress
;
372 /* Set logical MAC address for net 2 to (log | 3). */
373 if (!pAC
->Addr
.Net
[1].CurrentMacAddressSet
) {
374 pAC
->Addr
.Net
[1].PermanentMacAddress
=
375 pAC
->Addr
.Net
[0].PermanentMacAddress
;
376 pAC
->Addr
.Net
[1].PermanentMacAddress
.a
[5] |= 3;
377 /* Set the current logical MAC address to the permanent one. */
378 pAC
->Addr
.Net
[1].CurrentMacAddress
=
379 pAC
->Addr
.Net
[1].PermanentMacAddress
;
380 pAC
->Addr
.Net
[1].CurrentMacAddressSet
= SK_TRUE
;
382 #endif /* SK_MAX_NETS > 1 */
385 for (i
= 0; i
< (SK_U32
) pAC
->GIni
.GIMacsFound
; i
++) {
386 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_INIT
,
387 ("Permanent MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
389 pAC
->Addr
.Net
[i
].PermanentMacAddress
.a
[0],
390 pAC
->Addr
.Net
[i
].PermanentMacAddress
.a
[1],
391 pAC
->Addr
.Net
[i
].PermanentMacAddress
.a
[2],
392 pAC
->Addr
.Net
[i
].PermanentMacAddress
.a
[3],
393 pAC
->Addr
.Net
[i
].PermanentMacAddress
.a
[4],
394 pAC
->Addr
.Net
[i
].PermanentMacAddress
.a
[5]))
396 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_INIT
,
397 ("Logical MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
399 pAC
->Addr
.Net
[i
].CurrentMacAddress
.a
[0],
400 pAC
->Addr
.Net
[i
].CurrentMacAddress
.a
[1],
401 pAC
->Addr
.Net
[i
].CurrentMacAddress
.a
[2],
402 pAC
->Addr
.Net
[i
].CurrentMacAddress
.a
[3],
403 pAC
->Addr
.Net
[i
].CurrentMacAddress
.a
[4],
404 pAC
->Addr
.Net
[i
].CurrentMacAddress
.a
[5]))
408 for (i
= 0; i
< (SK_U32
) pAC
->GIni
.GIMacsFound
; i
++) {
409 pAPort
= &pAC
->Addr
.Port
[i
];
411 /* Read permanent port addresses from Control Register File. */
412 for (j
= 0; j
< SK_MAC_ADDR_LEN
; j
++) {
413 InAddr
= (SK_U8
*) &pAPort
->PermanentMacAddress
.a
[j
];
414 SK_IN8(IoC
, B2_MAC_2
+ 8 * i
+ j
, InAddr
);
417 if (!pAPort
->CurrentMacAddressSet
) {
419 * Set the current and previous physical MAC address
420 * of this port to its permanent MAC address.
422 pAPort
->CurrentMacAddress
= pAPort
->PermanentMacAddress
;
423 pAPort
->PreviousMacAddress
= pAPort
->PermanentMacAddress
;
424 pAPort
->CurrentMacAddressSet
= SK_TRUE
;
427 /* Set port's current physical MAC address. */
428 OutAddr
= (SK_U16
*) &pAPort
->CurrentMacAddress
.a
[0];
430 if (pAC
->GIni
.GIChipId
== CHIP_ID_GENESIS
) {
431 XM_OUTADDR(IoC
, i
, XM_SA
, OutAddr
);
434 GM_OUTADDR(IoC
, i
, GM_SRC_ADDR_1L
, OutAddr
);
437 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_INIT
,
438 ("SkAddrInit: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
439 pAPort
->PermanentMacAddress
.a
[0],
440 pAPort
->PermanentMacAddress
.a
[1],
441 pAPort
->PermanentMacAddress
.a
[2],
442 pAPort
->PermanentMacAddress
.a
[3],
443 pAPort
->PermanentMacAddress
.a
[4],
444 pAPort
->PermanentMacAddress
.a
[5]))
446 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_INIT
,
447 ("SkAddrInit: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
448 pAPort
->CurrentMacAddress
.a
[0],
449 pAPort
->CurrentMacAddress
.a
[1],
450 pAPort
->CurrentMacAddress
.a
[2],
451 pAPort
->CurrentMacAddress
.a
[3],
452 pAPort
->CurrentMacAddress
.a
[4],
453 pAPort
->CurrentMacAddress
.a
[5]))
456 /* pAC->Addr.InitDone = SK_INIT_IO; */
461 for (i
= 0; i
< SK_MAX_MACS
; i
++) {
462 if (pAC
->Addr
.Port
[i
].NextExactMatchRlmt
<
463 SK_ADDR_FIRST_MATCH_RLMT
) {
469 /* pAC->Addr.InitDone = SK_INIT_RUN; */
476 return (SK_ADDR_SUCCESS
);
481 /******************************************************************************
483 * SkAddrMcClear - clear the multicast table
486 * This routine clears the multicast table.
488 * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
491 * It calls either SkAddrXmacMcClear or SkAddrGmacMcClear, according
492 * to the adapter in use. The real work is done there.
496 * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
497 * may be called after SK_INIT_IO without limitation
501 * SK_ADDR_ILLEGAL_PORT
504 SK_AC
*pAC
, /* adapter context */
505 SK_IOC IoC
, /* I/O context */
506 SK_U32 PortNumber
, /* Index of affected port */
507 int Flags
) /* permanent/non-perm, sw-only */
511 if (PortNumber
>= (SK_U32
) pAC
->GIni
.GIMacsFound
) {
512 return (SK_ADDR_ILLEGAL_PORT
);
515 if (pAC
->GIni
.GIChipId
== CHIP_ID_GENESIS
) {
516 ReturnCode
= SkAddrXmacMcClear(pAC
, IoC
, PortNumber
, Flags
);
519 ReturnCode
= SkAddrGmacMcClear(pAC
, IoC
, PortNumber
, Flags
);
524 } /* SkAddrMcClear */
527 /******************************************************************************
529 * SkAddrXmacMcClear - clear the multicast table
532 * This routine clears the multicast table
533 * (either entry 2 or entries 3-16 and InexactFilter) of the given port.
534 * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
539 * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
540 * may be called after SK_INIT_IO without limitation
544 * SK_ADDR_ILLEGAL_PORT
546 int SkAddrXmacMcClear(
547 SK_AC
*pAC
, /* adapter context */
548 SK_IOC IoC
, /* I/O context */
549 SK_U32 PortNumber
, /* Index of affected port */
550 int Flags
) /* permanent/non-perm, sw-only */
554 if (Flags
& SK_ADDR_PERMANENT
) { /* permanent => RLMT */
556 /* Clear RLMT multicast addresses. */
557 pAC
->Addr
.Port
[PortNumber
].NextExactMatchRlmt
= SK_ADDR_FIRST_MATCH_RLMT
;
559 else { /* not permanent => DRV */
561 /* Clear InexactFilter */
562 for (i
= 0; i
< 8; i
++) {
563 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] = 0;
566 /* Clear DRV multicast addresses. */
568 pAC
->Addr
.Port
[PortNumber
].NextExactMatchDrv
= SK_ADDR_FIRST_MATCH_DRV
;
571 if (!(Flags
& SK_MC_SW_ONLY
)) {
572 (void) SkAddrXmacMcUpdate(pAC
, IoC
, PortNumber
);
575 return (SK_ADDR_SUCCESS
);
577 } /* SkAddrXmacMcClear */
580 /******************************************************************************
582 * SkAddrGmacMcClear - clear the multicast table
585 * This routine clears the multicast hashing table (InexactFilter)
586 * (either the RLMT or the driver bits) of the given port.
588 * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
593 * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
594 * may be called after SK_INIT_IO without limitation
598 * SK_ADDR_ILLEGAL_PORT
600 int SkAddrGmacMcClear(
601 SK_AC
*pAC
, /* adapter context */
602 SK_IOC IoC
, /* I/O context */
603 SK_U32 PortNumber
, /* Index of affected port */
604 int Flags
) /* permanent/non-perm, sw-only */
609 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
610 ("GMAC InexactFilter (not cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
611 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[0],
612 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[1],
613 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[2],
614 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[3],
615 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[4],
616 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[5],
617 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[6],
618 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[7]))
621 /* Clear InexactFilter */
622 for (i
= 0; i
< 8; i
++) {
623 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] = 0;
626 if (Flags
& SK_ADDR_PERMANENT
) { /* permanent => RLMT */
628 /* Copy DRV bits to InexactFilter. */
629 for (i
= 0; i
< 8; i
++) {
630 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] |=
631 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[i
];
633 /* Clear InexactRlmtFilter. */
634 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[i
] = 0;
638 else { /* not permanent => DRV */
640 /* Copy RLMT bits to InexactFilter. */
641 for (i
= 0; i
< 8; i
++) {
642 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] |=
643 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[i
];
645 /* Clear InexactDrvFilter. */
646 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[i
] = 0;
651 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
652 ("GMAC InexactFilter (cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
653 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[0],
654 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[1],
655 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[2],
656 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[3],
657 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[4],
658 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[5],
659 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[6],
660 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[7]))
663 if (!(Flags
& SK_MC_SW_ONLY
)) {
664 (void) SkAddrGmacMcUpdate(pAC
, IoC
, PortNumber
);
667 return (SK_ADDR_SUCCESS
);
669 } /* SkAddrGmacMcClear */
671 #ifndef SK_ADDR_CHEAT
673 /******************************************************************************
675 * SkXmacMcHash - hash multicast address
678 * This routine computes the hash value for a multicast address.
679 * A CRC32 algorithm is used.
682 * The code was adapted from the XaQti data sheet.
688 * Hash value of multicast address.
691 unsigned char *pMc
) /* Multicast address */
699 for (Idx
= 0; Idx
< SK_MAC_ADDR_LEN
; Idx
++) {
701 for (Bit
= 0; Bit
< 8; Bit
++, Data
>>= 1) {
702 Crc
= (Crc
>> 1) ^ (((Crc
^ Data
) & 1) ? XMAC_POLY
: 0);
706 return (Crc
& ((1 << HASH_BITS
) - 1));
711 /******************************************************************************
713 * SkGmacMcHash - hash multicast address
716 * This routine computes the hash value for a multicast address.
717 * A CRC16 algorithm is used.
726 * Hash value of multicast address.
729 unsigned char *pMc
) /* Multicast address */
738 for (Byte
= 0; Byte
< 6; Byte
++) {
740 Data
= (SK_U32
) pMc
[Byte
];
742 /* Change bit order in byte. */
744 for (Bit
= 0; Bit
< 8; Bit
++) {
746 Data
|= 1L << (7 - Bit
);
749 Data
&= ~(1L << (7 - Bit
));
755 for (Bit
= 0; Bit
< 8; Bit
++) {
756 if (Crc
& 0x80000000) {
757 Crc
= (Crc
<< 1) ^ GMAC_POLY
;
765 return (Crc
& ((1 << HASH_BITS
) - 1));
769 #endif /* not SK_ADDR_CHEAT */
771 /******************************************************************************
773 * SkAddrMcAdd - add a multicast address to a port
776 * This routine enables reception for a given address on the given port.
778 * It calls either SkAddrXmacMcAdd or SkAddrGmacMcAdd, according to the
779 * adapter in use. The real work is done there.
782 * The return code is only valid for SK_PROM_MODE_NONE.
786 * may be called after SK_INIT_DATA
789 * SK_MC_FILTERING_EXACT
790 * SK_MC_FILTERING_INEXACT
791 * SK_MC_ILLEGAL_ADDRESS
793 * SK_MC_RLMT_OVERFLOW
796 SK_AC
*pAC
, /* adapter context */
797 SK_IOC IoC
, /* I/O context */
798 SK_U32 PortNumber
, /* Port Number */
799 SK_MAC_ADDR
*pMc
, /* multicast address to be added */
800 int Flags
) /* permanent/non-permanent */
804 if (PortNumber
>= (SK_U32
) pAC
->GIni
.GIMacsFound
) {
805 return (SK_ADDR_ILLEGAL_PORT
);
808 if (pAC
->GIni
.GIChipId
== CHIP_ID_GENESIS
) {
809 ReturnCode
= SkAddrXmacMcAdd(pAC
, IoC
, PortNumber
, pMc
, Flags
);
812 ReturnCode
= SkAddrGmacMcAdd(pAC
, IoC
, PortNumber
, pMc
, Flags
);
820 /******************************************************************************
822 * SkAddrXmacMcAdd - add a multicast address to a port
825 * This routine enables reception for a given address on the given port.
828 * The return code is only valid for SK_PROM_MODE_NONE.
830 * The multicast bit is only checked if there are no free exact match
835 * may be called after SK_INIT_DATA
838 * SK_MC_FILTERING_EXACT
839 * SK_MC_FILTERING_INEXACT
840 * SK_MC_ILLEGAL_ADDRESS
841 * SK_MC_RLMT_OVERFLOW
844 SK_AC
*pAC
, /* adapter context */
845 SK_IOC IoC
, /* I/O context */
846 SK_U32 PortNumber
, /* Port Number */
847 SK_MAC_ADDR
*pMc
, /* multicast address to be added */
848 int Flags
) /* permanent/non-permanent */
852 #ifndef SK_ADDR_CHEAT
854 #endif /* !defined(SK_ADDR_CHEAT) */
856 if (Flags
& SK_ADDR_PERMANENT
) { /* permanent => RLMT */
858 if (pAC
->Addr
.Port
[PortNumber
].NextExactMatchRlmt
<
859 SK_ADDR_FIRST_MATCH_RLMT
) {
860 Next0
[PortNumber
] |= 1;
861 return (SK_MC_RLMT_OVERFLOW
);
865 if (pAC
->Addr
.Port
[PortNumber
].NextExactMatchRlmt
>
866 SK_ADDR_LAST_MATCH_RLMT
) {
867 return (SK_MC_RLMT_OVERFLOW
);
870 /* Set a RLMT multicast address. */
872 pAC
->Addr
.Port
[PortNumber
].Exact
[
873 pAC
->Addr
.Port
[PortNumber
].NextExactMatchRlmt
++] = *pMc
;
875 return (SK_MC_FILTERING_EXACT
);
879 if (pAC
->Addr
.Port
[PortNumber
].NextExactMatchDrv
<
880 SK_ADDR_FIRST_MATCH_DRV
) {
881 Next0
[PortNumber
] |= 2;
882 return (SK_MC_RLMT_OVERFLOW
);
886 if (pAC
->Addr
.Port
[PortNumber
].NextExactMatchDrv
<= SK_ADDR_LAST_MATCH_DRV
) {
888 /* Set exact match entry. */
889 pAC
->Addr
.Port
[PortNumber
].Exact
[
890 pAC
->Addr
.Port
[PortNumber
].NextExactMatchDrv
++] = *pMc
;
892 /* Clear InexactFilter */
893 for (i
= 0; i
< 8; i
++) {
894 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] = 0;
898 if (!(pMc
->a
[0] & SK_MC_BIT
)) {
899 /* Hashing only possible with multicast addresses. */
900 return (SK_MC_ILLEGAL_ADDRESS
);
902 #ifndef SK_ADDR_CHEAT
903 /* Compute hash value of address. */
904 HashBit
= 63 - SkXmacMcHash(&pMc
->a
[0]);
906 /* Add bit to InexactFilter. */
907 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[HashBit
/ 8] |=
909 #else /* SK_ADDR_CHEAT */
910 /* Set all bits in InexactFilter. */
911 for (i
= 0; i
< 8; i
++) {
912 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] = 0xFF;
914 #endif /* SK_ADDR_CHEAT */
917 for (Inexact
= 0, i
= 0; i
< 8; i
++) {
918 Inexact
|= pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
];
921 if (Inexact
== 0 && pAC
->Addr
.Port
[PortNumber
].PromMode
== 0) {
922 return (SK_MC_FILTERING_EXACT
);
925 return (SK_MC_FILTERING_INEXACT
);
928 } /* SkAddrXmacMcAdd */
931 /******************************************************************************
933 * SkAddrGmacMcAdd - add a multicast address to a port
936 * This routine enables reception for a given address on the given port.
939 * The return code is only valid for SK_PROM_MODE_NONE.
943 * may be called after SK_INIT_DATA
946 * SK_MC_FILTERING_INEXACT
947 * SK_MC_ILLEGAL_ADDRESS
950 SK_AC
*pAC
, /* adapter context */
951 SK_IOC IoC
, /* I/O context */
952 SK_U32 PortNumber
, /* Port Number */
953 SK_MAC_ADDR
*pMc
, /* multicast address to be added */
954 int Flags
) /* permanent/non-permanent */
957 #ifndef SK_ADDR_CHEAT
959 #endif /* !defined(SK_ADDR_CHEAT) */
961 if (!(pMc
->a
[0] & SK_MC_BIT
)) {
962 /* Hashing only possible with multicast addresses. */
963 return (SK_MC_ILLEGAL_ADDRESS
);
966 #ifndef SK_ADDR_CHEAT
968 /* Compute hash value of address. */
969 HashBit
= SkGmacMcHash(&pMc
->a
[0]);
971 if (Flags
& SK_ADDR_PERMANENT
) { /* permanent => RLMT */
973 /* Add bit to InexactRlmtFilter. */
974 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[HashBit
/ 8] |=
977 /* Copy bit to InexactFilter. */
978 for (i
= 0; i
< 8; i
++) {
979 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] |=
980 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[i
];
983 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
984 ("GMAC InexactRlmtFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
985 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[0],
986 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[1],
987 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[2],
988 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[3],
989 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[4],
990 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[5],
991 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[6],
992 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[7]))
995 else { /* not permanent => DRV */
997 /* Add bit to InexactDrvFilter. */
998 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[HashBit
/ 8] |=
1001 /* Copy bit to InexactFilter. */
1002 for (i
= 0; i
< 8; i
++) {
1003 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] |=
1004 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[i
];
1007 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
1008 ("GMAC InexactDrvFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
1009 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[0],
1010 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[1],
1011 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[2],
1012 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[3],
1013 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[4],
1014 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[5],
1015 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[6],
1016 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[7]))
1020 #else /* SK_ADDR_CHEAT */
1022 /* Set all bits in InexactFilter. */
1023 for (i
= 0; i
< 8; i
++) {
1024 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] = 0xFF;
1026 #endif /* SK_ADDR_CHEAT */
1028 return (SK_MC_FILTERING_INEXACT
);
1030 } /* SkAddrGmacMcAdd */
1033 /******************************************************************************
1035 * SkAddrMcUpdate - update the HW MC address table and set the MAC address
1038 * This routine enables reception of the addresses contained in a local
1039 * table for a given port.
1040 * It also programs the port's current physical MAC address.
1042 * It calls either SkAddrXmacMcUpdate or SkAddrGmacMcUpdate, according
1043 * to the adapter in use. The real work is done there.
1046 * The return code is only valid for SK_PROM_MODE_NONE.
1050 * may be called after SK_INIT_IO
1053 * SK_MC_FILTERING_EXACT
1054 * SK_MC_FILTERING_INEXACT
1055 * SK_ADDR_ILLEGAL_PORT
1058 SK_AC
*pAC
, /* adapter context */
1059 SK_IOC IoC
, /* I/O context */
1060 SK_U32 PortNumber
) /* Port Number */
1064 if (PortNumber
>= (SK_U32
) pAC
->GIni
.GIMacsFound
) {
1065 return (SK_ADDR_ILLEGAL_PORT
);
1068 if (pAC
->GIni
.GIChipId
== CHIP_ID_GENESIS
) {
1069 ReturnCode
= SkAddrXmacMcUpdate(pAC
, IoC
, PortNumber
);
1072 ReturnCode
= SkAddrGmacMcUpdate(pAC
, IoC
, PortNumber
);
1075 return (ReturnCode
);
1077 } /* SkAddrMcUpdate */
1080 /******************************************************************************
1082 * SkAddrXmacMcUpdate - update the HW MC address table and set the MAC address
1085 * This routine enables reception of the addresses contained in a local
1086 * table for a given port.
1087 * It also programs the port's current physical MAC address.
1090 * The return code is only valid for SK_PROM_MODE_NONE.
1094 * may be called after SK_INIT_IO
1097 * SK_MC_FILTERING_EXACT
1098 * SK_MC_FILTERING_INEXACT
1099 * SK_ADDR_ILLEGAL_PORT
1101 int SkAddrXmacMcUpdate(
1102 SK_AC
*pAC
, /* adapter context */
1103 SK_IOC IoC
, /* I/O context */
1104 SK_U32 PortNumber
) /* Port Number */
1109 SK_ADDR_PORT
*pAPort
;
1111 SK_DBG_MSG(pAC
,SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
1112 ("SkAddrXmacMcUpdate on Port %u.\n", PortNumber
))
1114 pAPort
= &pAC
->Addr
.Port
[PortNumber
];
1117 SK_DBG_MSG(pAC
,SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
1118 ("Next0 on Port %d: %d\n", PortNumber
, Next0
[PortNumber
]))
1121 /* Start with 0 to also program the logical MAC address. */
1122 for (i
= 0; i
< pAPort
->NextExactMatchRlmt
; i
++) {
1123 /* Set exact match address i on XMAC */
1124 OutAddr
= (SK_U16
*) &pAPort
->Exact
[i
].a
[0];
1125 XM_OUTADDR(IoC
, PortNumber
, XM_EXM(i
), OutAddr
);
1128 /* Clear other permanent exact match addresses on XMAC */
1129 if (pAPort
->NextExactMatchRlmt
<= SK_ADDR_LAST_MATCH_RLMT
) {
1131 SkXmClrExactAddr(pAC
, IoC
, PortNumber
, pAPort
->NextExactMatchRlmt
,
1132 SK_ADDR_LAST_MATCH_RLMT
);
1135 for (i
= pAPort
->FirstExactMatchDrv
; i
< pAPort
->NextExactMatchDrv
; i
++) {
1136 OutAddr
= (SK_U16
*) &pAPort
->Exact
[i
].a
[0];
1137 XM_OUTADDR(IoC
, PortNumber
, XM_EXM(i
), OutAddr
);
1140 /* Clear other non-permanent exact match addresses on XMAC */
1141 if (pAPort
->NextExactMatchDrv
<= SK_ADDR_LAST_MATCH_DRV
) {
1143 SkXmClrExactAddr(pAC
, IoC
, PortNumber
, pAPort
->NextExactMatchDrv
,
1144 SK_ADDR_LAST_MATCH_DRV
);
1147 for (Inexact
= 0, i
= 0; i
< 8; i
++) {
1148 Inexact
|= pAPort
->InexactFilter
.Bytes
[i
];
1151 if (pAPort
->PromMode
& SK_PROM_MODE_ALL_MC
) {
1153 /* Set all bits in 64-bit hash register. */
1154 XM_OUTHASH(IoC
, PortNumber
, XM_HSM
, &OnesHash
);
1156 /* Enable Hashing */
1157 SkMacHashing(pAC
, IoC
, PortNumber
, SK_TRUE
);
1159 else if (Inexact
!= 0) {
1161 /* Set 64-bit hash register to InexactFilter. */
1162 XM_OUTHASH(IoC
, PortNumber
, XM_HSM
, &pAPort
->InexactFilter
.Bytes
[0]);
1164 /* Enable Hashing */
1165 SkMacHashing(pAC
, IoC
, PortNumber
, SK_TRUE
);
1168 /* Disable Hashing */
1169 SkMacHashing(pAC
, IoC
, PortNumber
, SK_FALSE
);
1172 if (pAPort
->PromMode
!= SK_PROM_MODE_NONE
) {
1173 (void) SkAddrXmacPromiscuousChange(pAC
, IoC
, PortNumber
, pAPort
->PromMode
);
1176 /* Set port's current physical MAC address. */
1177 OutAddr
= (SK_U16
*) &pAPort
->CurrentMacAddress
.a
[0];
1179 XM_OUTADDR(IoC
, PortNumber
, XM_SA
, OutAddr
);
1182 for (i
= 0; i
< pAPort
->NextExactMatchRlmt
; i
++) {
1186 /* Get exact match address i from port PortNumber. */
1187 InAddr
= (SK_U16
*) &InAddr8
[0];
1189 XM_INADDR(IoC
, PortNumber
, XM_EXM(i
), InAddr
);
1191 SK_DBG_MSG(pAC
,SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
1192 ("SkAddrXmacMcUpdate: MC address %d on Port %u: ",
1193 "%02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x\n",
1202 pAPort
->Exact
[i
].a
[0],
1203 pAPort
->Exact
[i
].a
[1],
1204 pAPort
->Exact
[i
].a
[2],
1205 pAPort
->Exact
[i
].a
[3],
1206 pAPort
->Exact
[i
].a
[4],
1207 pAPort
->Exact
[i
].a
[5]))
1211 /* Determine return value. */
1212 if (Inexact
== 0 && pAPort
->PromMode
== 0) {
1213 return (SK_MC_FILTERING_EXACT
);
1216 return (SK_MC_FILTERING_INEXACT
);
1219 } /* SkAddrXmacMcUpdate */
1222 /******************************************************************************
1224 * SkAddrGmacMcUpdate - update the HW MC address table and set the MAC address
1227 * This routine enables reception of the addresses contained in a local
1228 * table for a given port.
1229 * It also programs the port's current physical MAC address.
1232 * The return code is only valid for SK_PROM_MODE_NONE.
1236 * may be called after SK_INIT_IO
1239 * SK_MC_FILTERING_EXACT
1240 * SK_MC_FILTERING_INEXACT
1241 * SK_ADDR_ILLEGAL_PORT
1243 int SkAddrGmacMcUpdate(
1244 SK_AC
*pAC
, /* adapter context */
1245 SK_IOC IoC
, /* I/O context */
1246 SK_U32 PortNumber
) /* Port Number */
1251 SK_ADDR_PORT
*pAPort
;
1253 SK_DBG_MSG(pAC
,SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
1254 ("SkAddrGmacMcUpdate on Port %u.\n", PortNumber
))
1256 pAPort
= &pAC
->Addr
.Port
[PortNumber
];
1259 SK_DBG_MSG(pAC
,SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
1260 ("Next0 on Port %d: %d\n", PortNumber
, Next0
[PortNumber
]))
1263 for (Inexact
= 0, i
= 0; i
< 8; i
++) {
1264 Inexact
|= pAPort
->InexactFilter
.Bytes
[i
];
1267 /* Set 64-bit hash register to InexactFilter. */
1268 GM_OUTHASH(IoC
, PortNumber
, GM_MC_ADDR_H1
,
1269 &pAPort
->InexactFilter
.Bytes
[0]);
1271 if (pAPort
->PromMode
& SK_PROM_MODE_ALL_MC
) {
1273 /* Set all bits in 64-bit hash register. */
1274 GM_OUTHASH(IoC
, PortNumber
, GM_MC_ADDR_H1
, &OnesHash
);
1276 /* Enable Hashing */
1277 SkMacHashing(pAC
, IoC
, PortNumber
, SK_TRUE
);
1280 /* Enable Hashing. */
1281 SkMacHashing(pAC
, IoC
, PortNumber
, SK_TRUE
);
1284 if (pAPort
->PromMode
!= SK_PROM_MODE_NONE
) {
1285 (void) SkAddrGmacPromiscuousChange(pAC
, IoC
, PortNumber
, pAPort
->PromMode
);
1288 /* Set port's current physical MAC address. */
1289 OutAddr
= (SK_U16
*) &pAPort
->CurrentMacAddress
.a
[0];
1290 GM_OUTADDR(IoC
, PortNumber
, GM_SRC_ADDR_1L
, OutAddr
);
1292 /* Set port's current logical MAC address. */
1293 OutAddr
= (SK_U16
*) &pAPort
->Exact
[0].a
[0];
1294 GM_OUTADDR(IoC
, PortNumber
, GM_SRC_ADDR_2L
, OutAddr
);
1297 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
1298 ("SkAddrGmacMcUpdate: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
1299 pAPort
->Exact
[0].a
[0],
1300 pAPort
->Exact
[0].a
[1],
1301 pAPort
->Exact
[0].a
[2],
1302 pAPort
->Exact
[0].a
[3],
1303 pAPort
->Exact
[0].a
[4],
1304 pAPort
->Exact
[0].a
[5]))
1306 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
1307 ("SkAddrGmacMcUpdate: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
1308 pAPort
->CurrentMacAddress
.a
[0],
1309 pAPort
->CurrentMacAddress
.a
[1],
1310 pAPort
->CurrentMacAddress
.a
[2],
1311 pAPort
->CurrentMacAddress
.a
[3],
1312 pAPort
->CurrentMacAddress
.a
[4],
1313 pAPort
->CurrentMacAddress
.a
[5]))
1316 /* Determine return value. */
1317 if (Inexact
== 0 && pAPort
->PromMode
== 0) {
1318 return (SK_MC_FILTERING_EXACT
);
1321 return (SK_MC_FILTERING_INEXACT
);
1324 } /* SkAddrGmacMcUpdate */
1327 /******************************************************************************
1329 * SkAddrOverride - override a port's MAC address
1332 * This routine overrides the MAC address of one port.
1336 * may be called after SK_INIT_IO
1339 * SK_ADDR_SUCCESS if successful.
1340 * SK_ADDR_DUPLICATE_ADDRESS if duplicate MAC address.
1341 * SK_ADDR_MULTICAST_ADDRESS if multicast or broadcast address.
1342 * SK_ADDR_TOO_EARLY if SK_INIT_IO was not executed before.
1345 SK_AC
*pAC
, /* adapter context */
1346 SK_IOC IoC
, /* I/O context */
1347 SK_U32 PortNumber
, /* Port Number */
1348 SK_MAC_ADDR
*pNewAddr
, /* new MAC address */
1349 int Flags
) /* logical/physical MAC address */
1356 NetNumber
= pAC
->Rlmt
.Port
[PortNumber
].Net
->NetNumber
;
1358 if (PortNumber
>= (SK_U32
) pAC
->GIni
.GIMacsFound
) {
1359 return (SK_ADDR_ILLEGAL_PORT
);
1362 if (pNewAddr
!= NULL
&& (pNewAddr
->a
[0] & SK_MC_BIT
) != 0) {
1363 return (SK_ADDR_MULTICAST_ADDRESS
);
1366 if (!pAC
->Addr
.Net
[NetNumber
].CurrentMacAddressSet
) {
1367 return (SK_ADDR_TOO_EARLY
);
1370 if (Flags
& SK_ADDR_SET_LOGICAL
) { /* Activate logical MAC address. */
1371 /* Parameter *pNewAddr is ignored. */
1372 for (i
= 0; i
< (SK_U32
) pAC
->GIni
.GIMacsFound
; i
++) {
1373 if (!pAC
->Addr
.Port
[i
].CurrentMacAddressSet
) {
1374 return (SK_ADDR_TOO_EARLY
);
1378 /* Set PortNumber to number of net's active port. */
1379 PortNumber
= pAC
->Rlmt
.Net
[NetNumber
].
1380 Port
[pAC
->Addr
.Net
[NetNumber
].ActivePort
]->PortNumber
;
1382 pAC
->Addr
.Port
[PortNumber
].Exact
[0] =
1383 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
;
1385 /* Write address to first exact match entry of active port. */
1386 (void) SkAddrMcUpdate(pAC
, IoC
, PortNumber
);
1388 else if (Flags
& SK_ADDR_CLEAR_LOGICAL
) {
1389 /* Deactivate logical MAC address. */
1390 /* Parameter *pNewAddr is ignored. */
1391 for (i
= 0; i
< (SK_U32
) pAC
->GIni
.GIMacsFound
; i
++) {
1392 if (!pAC
->Addr
.Port
[i
].CurrentMacAddressSet
) {
1393 return (SK_ADDR_TOO_EARLY
);
1397 /* Set PortNumber to number of net's active port. */
1398 PortNumber
= pAC
->Rlmt
.Net
[NetNumber
].
1399 Port
[pAC
->Addr
.Net
[NetNumber
].ActivePort
]->PortNumber
;
1401 for (i
= 0; i
< SK_MAC_ADDR_LEN
; i
++ ) {
1402 pAC
->Addr
.Port
[PortNumber
].Exact
[0].a
[i
] = 0;
1405 /* Write address to first exact match entry of active port. */
1406 (void) SkAddrMcUpdate(pAC
, IoC
, PortNumber
);
1408 else if (Flags
& SK_ADDR_PHYSICAL_ADDRESS
) { /* Physical MAC address. */
1409 if (SK_ADDR_EQUAL(pNewAddr
->a
,
1410 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
.a
)) {
1411 return (SK_ADDR_DUPLICATE_ADDRESS
);
1414 for (i
= 0; i
< (SK_U32
) pAC
->GIni
.GIMacsFound
; i
++) {
1415 if (!pAC
->Addr
.Port
[i
].CurrentMacAddressSet
) {
1416 return (SK_ADDR_TOO_EARLY
);
1419 if (SK_ADDR_EQUAL(pNewAddr
->a
,
1420 pAC
->Addr
.Port
[i
].CurrentMacAddress
.a
)) {
1421 if (i
== PortNumber
) {
1422 return (SK_ADDR_SUCCESS
);
1425 return (SK_ADDR_DUPLICATE_ADDRESS
);
1430 pAC
->Addr
.Port
[PortNumber
].PreviousMacAddress
=
1431 pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
;
1432 pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
= *pNewAddr
;
1434 /* Change port's physical MAC address. */
1435 OutAddr
= (SK_U16
*) pNewAddr
;
1437 if (pAC
->GIni
.GIChipId
== CHIP_ID_GENESIS
) {
1438 XM_OUTADDR(IoC
, PortNumber
, XM_SA
, OutAddr
);
1441 GM_OUTADDR(IoC
, PortNumber
, GM_SRC_ADDR_1L
, OutAddr
);
1444 /* Report address change to RLMT. */
1445 Para
.Para32
[0] = PortNumber
;
1446 Para
.Para32
[0] = -1;
1447 SkEventQueue(pAC
, SKGE_RLMT
, SK_RLMT_PORT_ADDR
, Para
);
1449 else { /* Logical MAC address. */
1450 if (SK_ADDR_EQUAL(pNewAddr
->a
,
1451 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
.a
)) {
1452 return (SK_ADDR_SUCCESS
);
1455 for (i
= 0; i
< (SK_U32
) pAC
->GIni
.GIMacsFound
; i
++) {
1456 if (!pAC
->Addr
.Port
[i
].CurrentMacAddressSet
) {
1457 return (SK_ADDR_TOO_EARLY
);
1460 if (SK_ADDR_EQUAL(pNewAddr
->a
,
1461 pAC
->Addr
.Port
[i
].CurrentMacAddress
.a
)) {
1462 return (SK_ADDR_DUPLICATE_ADDRESS
);
1467 * In case that the physical and the logical MAC addresses are equal
1468 * we must also change the physical MAC address here.
1469 * In this case we have an adapter which initially was programmed with
1470 * two identical MAC addresses.
1472 if (SK_ADDR_EQUAL(pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
.a
,
1473 pAC
->Addr
.Port
[PortNumber
].Exact
[0].a
)) {
1475 pAC
->Addr
.Port
[PortNumber
].PreviousMacAddress
=
1476 pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
;
1477 pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
= *pNewAddr
;
1479 /* Report address change to RLMT. */
1480 Para
.Para32
[0] = PortNumber
;
1481 Para
.Para32
[0] = -1;
1482 SkEventQueue(pAC
, SKGE_RLMT
, SK_RLMT_PORT_ADDR
, Para
);
1485 /* Set PortNumber to number of net's active port. */
1486 PortNumber
= pAC
->Rlmt
.Net
[NetNumber
].
1487 Port
[pAC
->Addr
.Net
[NetNumber
].ActivePort
]->PortNumber
;
1489 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
= *pNewAddr
;
1490 pAC
->Addr
.Port
[PortNumber
].Exact
[0] = *pNewAddr
;
1492 SK_DBG_MSG(pAC
,SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
1493 ("SkAddrOverride: Permanent MAC Address: %02X %02X %02X %02X %02X %02X\n",
1494 pAC
->Addr
.Net
[NetNumber
].PermanentMacAddress
.a
[0],
1495 pAC
->Addr
.Net
[NetNumber
].PermanentMacAddress
.a
[1],
1496 pAC
->Addr
.Net
[NetNumber
].PermanentMacAddress
.a
[2],
1497 pAC
->Addr
.Net
[NetNumber
].PermanentMacAddress
.a
[3],
1498 pAC
->Addr
.Net
[NetNumber
].PermanentMacAddress
.a
[4],
1499 pAC
->Addr
.Net
[NetNumber
].PermanentMacAddress
.a
[5]))
1501 SK_DBG_MSG(pAC
,SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
1502 ("SkAddrOverride: New logical MAC Address: %02X %02X %02X %02X %02X %02X\n",
1503 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
.a
[0],
1504 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
.a
[1],
1505 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
.a
[2],
1506 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
.a
[3],
1507 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
.a
[4],
1508 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
.a
[5]))
1511 /* Write address to first exact match entry of active port. */
1512 (void) SkAddrMcUpdate(pAC
, IoC
, PortNumber
);
1515 return (SK_ADDR_SUCCESS
);
1517 } /* SkAddrOverride */
1520 /******************************************************************************
1522 * SkAddrPromiscuousChange - set promiscuous mode for given port
1525 * This routine manages promiscuous mode:
1530 * It calls either SkAddrXmacPromiscuousChange or
1531 * SkAddrGmacPromiscuousChange, according to the adapter in use.
1532 * The real work is done there.
1536 * may be called after SK_INIT_IO
1540 * SK_ADDR_ILLEGAL_PORT
1542 int SkAddrPromiscuousChange(
1543 SK_AC
*pAC
, /* adapter context */
1544 SK_IOC IoC
, /* I/O context */
1545 SK_U32 PortNumber
, /* port whose promiscuous mode changes */
1546 int NewPromMode
) /* new promiscuous mode */
1550 if (PortNumber
>= (SK_U32
) pAC
->GIni
.GIMacsFound
) {
1551 return (SK_ADDR_ILLEGAL_PORT
);
1554 if (pAC
->GIni
.GIChipId
== CHIP_ID_GENESIS
) {
1555 ReturnCode
= SkAddrXmacPromiscuousChange(pAC
, IoC
, PortNumber
, NewPromMode
);
1558 ReturnCode
= SkAddrGmacPromiscuousChange(pAC
, IoC
, PortNumber
, NewPromMode
);
1561 return (ReturnCode
);
1563 } /* SkAddrPromiscuousChange */
1566 /******************************************************************************
1568 * SkAddrXmacPromiscuousChange - set promiscuous mode for given port
1571 * This routine manages promiscuous mode:
1578 * may be called after SK_INIT_IO
1582 * SK_ADDR_ILLEGAL_PORT
1584 int SkAddrXmacPromiscuousChange(
1585 SK_AC
*pAC
, /* adapter context */
1586 SK_IOC IoC
, /* I/O context */
1587 SK_U32 PortNumber
, /* port whose promiscuous mode changes */
1588 int NewPromMode
) /* new promiscuous mode */
1591 SK_BOOL InexactModeBit
;
1594 SK_FILTER64 HwInexactFilter
;
1595 SK_U16 LoMode
; /* Lower 16 bits of XMAC Mode Register. */
1596 int CurPromMode
= SK_PROM_MODE_NONE
;
1598 /* Read CurPromMode from Hardware. */
1599 XM_IN16(IoC
, PortNumber
, XM_MODE
, &LoMode
);
1601 if ((LoMode
& XM_MD_ENA_PROM
) != 0) {
1602 /* Promiscuous mode! */
1603 CurPromMode
|= SK_PROM_MODE_LLC
;
1606 for (Inexact
= 0xFF, i
= 0; i
< 8; i
++) {
1607 Inexact
&= pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
];
1609 if (Inexact
== 0xFF) {
1610 CurPromMode
|= (pAC
->Addr
.Port
[PortNumber
].PromMode
& SK_PROM_MODE_ALL_MC
);
1613 /* Get InexactModeBit (bit XM_MD_ENA_HASH in mode register) */
1614 XM_IN16(IoC
, PortNumber
, XM_MODE
, &LoMode
);
1616 InexactModeBit
= (LoMode
& XM_MD_ENA_HASH
) != 0;
1618 /* Read 64-bit hash register from XMAC */
1619 XM_INHASH(IoC
, PortNumber
, XM_HSM
, &HwInexactFilter
.Bytes
[0]);
1621 for (HwInexact
= 0xFF, i
= 0; i
< 8; i
++) {
1622 HwInexact
&= HwInexactFilter
.Bytes
[i
];
1625 if (InexactModeBit
&& (HwInexact
== 0xFF)) {
1626 CurPromMode
|= SK_PROM_MODE_ALL_MC
;
1630 pAC
->Addr
.Port
[PortNumber
].PromMode
= NewPromMode
;
1632 if (NewPromMode
== CurPromMode
) {
1633 return (SK_ADDR_SUCCESS
);
1636 if ((NewPromMode
& SK_PROM_MODE_ALL_MC
) &&
1637 !(CurPromMode
& SK_PROM_MODE_ALL_MC
)) { /* All MC. */
1639 /* Set all bits in 64-bit hash register. */
1640 XM_OUTHASH(IoC
, PortNumber
, XM_HSM
, &OnesHash
);
1642 /* Enable Hashing */
1643 SkMacHashing(pAC
, IoC
, PortNumber
, SK_TRUE
);
1645 else if ((CurPromMode
& SK_PROM_MODE_ALL_MC
) &&
1646 !(NewPromMode
& SK_PROM_MODE_ALL_MC
)) { /* Norm MC. */
1647 for (Inexact
= 0, i
= 0; i
< 8; i
++) {
1648 Inexact
|= pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
];
1651 /* Disable Hashing */
1652 SkMacHashing(pAC
, IoC
, PortNumber
, SK_FALSE
);
1655 /* Set 64-bit hash register to InexactFilter. */
1656 XM_OUTHASH(IoC
, PortNumber
, XM_HSM
,
1657 &pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[0]);
1659 /* Enable Hashing */
1660 SkMacHashing(pAC
, IoC
, PortNumber
, SK_TRUE
);
1664 if ((NewPromMode
& SK_PROM_MODE_LLC
) &&
1665 !(CurPromMode
& SK_PROM_MODE_LLC
)) { /* Prom. LLC */
1666 /* Set the MAC in Promiscuous Mode */
1667 SkMacPromiscMode(pAC
, IoC
, PortNumber
, SK_TRUE
);
1669 else if ((CurPromMode
& SK_PROM_MODE_LLC
) &&
1670 !(NewPromMode
& SK_PROM_MODE_LLC
)) { /* Norm. LLC. */
1671 /* Clear Promiscuous Mode */
1672 SkMacPromiscMode(pAC
, IoC
, PortNumber
, SK_FALSE
);
1675 return (SK_ADDR_SUCCESS
);
1677 } /* SkAddrXmacPromiscuousChange */
1680 /******************************************************************************
1682 * SkAddrGmacPromiscuousChange - set promiscuous mode for given port
1685 * This routine manages promiscuous mode:
1692 * may be called after SK_INIT_IO
1696 * SK_ADDR_ILLEGAL_PORT
1698 int SkAddrGmacPromiscuousChange(
1699 SK_AC
*pAC
, /* adapter context */
1700 SK_IOC IoC
, /* I/O context */
1701 SK_U32 PortNumber
, /* port whose promiscuous mode changes */
1702 int NewPromMode
) /* new promiscuous mode */
1704 SK_U16 ReceiveControl
; /* GMAC Receive Control Register */
1705 int CurPromMode
= SK_PROM_MODE_NONE
;
1707 /* Read CurPromMode from Hardware. */
1708 GM_IN16(IoC
, PortNumber
, GM_RX_CTRL
, &ReceiveControl
);
1710 if ((ReceiveControl
& (GM_RXCR_UCF_ENA
| GM_RXCR_MCF_ENA
)) == 0) {
1711 /* Promiscuous mode! */
1712 CurPromMode
|= SK_PROM_MODE_LLC
;
1715 if ((ReceiveControl
& GM_RXCR_MCF_ENA
) == 0) {
1716 /* All Multicast mode! */
1717 CurPromMode
|= (pAC
->Addr
.Port
[PortNumber
].PromMode
& SK_PROM_MODE_ALL_MC
);
1720 pAC
->Addr
.Port
[PortNumber
].PromMode
= NewPromMode
;
1722 if (NewPromMode
== CurPromMode
) {
1723 return (SK_ADDR_SUCCESS
);
1726 if ((NewPromMode
& SK_PROM_MODE_ALL_MC
) &&
1727 !(CurPromMode
& SK_PROM_MODE_ALL_MC
)) { /* All MC */
1729 /* Set all bits in 64-bit hash register. */
1730 GM_OUTHASH(IoC
, PortNumber
, GM_MC_ADDR_H1
, &OnesHash
);
1732 /* Enable Hashing */
1733 SkMacHashing(pAC
, IoC
, PortNumber
, SK_TRUE
);
1736 if ((CurPromMode
& SK_PROM_MODE_ALL_MC
) &&
1737 !(NewPromMode
& SK_PROM_MODE_ALL_MC
)) { /* Norm. MC */
1739 /* Set 64-bit hash register to InexactFilter. */
1740 GM_OUTHASH(IoC
, PortNumber
, GM_MC_ADDR_H1
,
1741 &pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[0]);
1743 /* Enable Hashing. */
1744 SkMacHashing(pAC
, IoC
, PortNumber
, SK_TRUE
);
1747 if ((NewPromMode
& SK_PROM_MODE_LLC
) &&
1748 !(CurPromMode
& SK_PROM_MODE_LLC
)) { /* Prom. LLC */
1750 /* Set the MAC to Promiscuous Mode. */
1751 SkMacPromiscMode(pAC
, IoC
, PortNumber
, SK_TRUE
);
1753 else if ((CurPromMode
& SK_PROM_MODE_LLC
) &&
1754 !(NewPromMode
& SK_PROM_MODE_LLC
)) { /* Norm. LLC */
1756 /* Clear Promiscuous Mode. */
1757 SkMacPromiscMode(pAC
, IoC
, PortNumber
, SK_FALSE
);
1760 return (SK_ADDR_SUCCESS
);
1762 } /* SkAddrGmacPromiscuousChange */
1765 /******************************************************************************
1767 * SkAddrSwap - swap address info
1770 * This routine swaps address info of two ports.
1774 * may be called after SK_INIT_IO
1778 * SK_ADDR_ILLEGAL_PORT
1781 SK_AC
*pAC
, /* adapter context */
1782 SK_IOC IoC
, /* I/O context */
1783 SK_U32 FromPortNumber
, /* Port1 Index */
1784 SK_U32 ToPortNumber
) /* Port2 Index */
1788 SK_MAC_ADDR MacAddr
;
1791 if (FromPortNumber
>= (SK_U32
) pAC
->GIni
.GIMacsFound
) {
1792 return (SK_ADDR_ILLEGAL_PORT
);
1795 if (ToPortNumber
>= (SK_U32
) pAC
->GIni
.GIMacsFound
) {
1796 return (SK_ADDR_ILLEGAL_PORT
);
1799 if (pAC
->Rlmt
.Port
[FromPortNumber
].Net
!= pAC
->Rlmt
.Port
[ToPortNumber
].Net
) {
1800 return (SK_ADDR_ILLEGAL_PORT
);
1805 * - Exact Match Entries (GEnesis and Yukon)
1806 * Yukon uses first entry for the logical MAC
1807 * address (stored in the second GMAC register).
1808 * - FirstExactMatchRlmt (GEnesis only)
1809 * - NextExactMatchRlmt (GEnesis only)
1810 * - FirstExactMatchDrv (GEnesis only)
1811 * - NextExactMatchDrv (GEnesis only)
1812 * - 64-bit filter (InexactFilter)
1813 * - Promiscuous Mode
1817 for (i
= 0; i
< SK_ADDR_EXACT_MATCHES
; i
++) {
1818 MacAddr
= pAC
->Addr
.Port
[FromPortNumber
].Exact
[i
];
1819 pAC
->Addr
.Port
[FromPortNumber
].Exact
[i
] =
1820 pAC
->Addr
.Port
[ToPortNumber
].Exact
[i
];
1821 pAC
->Addr
.Port
[ToPortNumber
].Exact
[i
] = MacAddr
;
1824 for (i
= 0; i
< 8; i
++) {
1825 Byte
= pAC
->Addr
.Port
[FromPortNumber
].InexactFilter
.Bytes
[i
];
1826 pAC
->Addr
.Port
[FromPortNumber
].InexactFilter
.Bytes
[i
] =
1827 pAC
->Addr
.Port
[ToPortNumber
].InexactFilter
.Bytes
[i
];
1828 pAC
->Addr
.Port
[ToPortNumber
].InexactFilter
.Bytes
[i
] = Byte
;
1831 i
= pAC
->Addr
.Port
[FromPortNumber
].PromMode
;
1832 pAC
->Addr
.Port
[FromPortNumber
].PromMode
= pAC
->Addr
.Port
[ToPortNumber
].PromMode
;
1833 pAC
->Addr
.Port
[ToPortNumber
].PromMode
= i
;
1835 if (pAC
->GIni
.GIChipId
== CHIP_ID_GENESIS
) {
1836 DWord
= pAC
->Addr
.Port
[FromPortNumber
].FirstExactMatchRlmt
;
1837 pAC
->Addr
.Port
[FromPortNumber
].FirstExactMatchRlmt
=
1838 pAC
->Addr
.Port
[ToPortNumber
].FirstExactMatchRlmt
;
1839 pAC
->Addr
.Port
[ToPortNumber
].FirstExactMatchRlmt
= DWord
;
1841 DWord
= pAC
->Addr
.Port
[FromPortNumber
].NextExactMatchRlmt
;
1842 pAC
->Addr
.Port
[FromPortNumber
].NextExactMatchRlmt
=
1843 pAC
->Addr
.Port
[ToPortNumber
].NextExactMatchRlmt
;
1844 pAC
->Addr
.Port
[ToPortNumber
].NextExactMatchRlmt
= DWord
;
1846 DWord
= pAC
->Addr
.Port
[FromPortNumber
].FirstExactMatchDrv
;
1847 pAC
->Addr
.Port
[FromPortNumber
].FirstExactMatchDrv
=
1848 pAC
->Addr
.Port
[ToPortNumber
].FirstExactMatchDrv
;
1849 pAC
->Addr
.Port
[ToPortNumber
].FirstExactMatchDrv
= DWord
;
1851 DWord
= pAC
->Addr
.Port
[FromPortNumber
].NextExactMatchDrv
;
1852 pAC
->Addr
.Port
[FromPortNumber
].NextExactMatchDrv
=
1853 pAC
->Addr
.Port
[ToPortNumber
].NextExactMatchDrv
;
1854 pAC
->Addr
.Port
[ToPortNumber
].NextExactMatchDrv
= DWord
;
1857 /* CAUTION: Solution works if only ports of one adapter are in use. */
1858 for (i
= 0; (SK_U32
) i
< pAC
->Rlmt
.Net
[pAC
->Rlmt
.Port
[ToPortNumber
].
1859 Net
->NetNumber
].NumPorts
; i
++) {
1860 if (pAC
->Rlmt
.Net
[pAC
->Rlmt
.Port
[ToPortNumber
].Net
->NetNumber
].
1861 Port
[i
]->PortNumber
== ToPortNumber
) {
1862 pAC
->Addr
.Net
[pAC
->Rlmt
.Port
[ToPortNumber
].Net
->NetNumber
].
1864 /* 20001207 RA: Was "ToPortNumber;". */
1868 (void) SkAddrMcUpdate(pAC
, IoC
, FromPortNumber
);
1869 (void) SkAddrMcUpdate(pAC
, IoC
, ToPortNumber
);
1871 return (SK_ADDR_SUCCESS
);
1877 #endif /* __cplusplus */
1879 #endif /* CONFIG_SK98 */