1 /******************************************************************************
4 * Project: Gigabit Ethernet Adapters, ADDR-Module
5 * Version: $Revision: 1.52 $
6 * Date: $Date: 2003/06/02 13:46:15 $
7 * Purpose: Manage Addresses (Multicast and Unicast) and Promiscuous Mode.
9 ******************************************************************************/
11 /******************************************************************************
13 * (C)Copyright 1998-2002 SysKonnect GmbH.
14 * (C)Copyright 2002-2003 Marvell.
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
21 * The information in this file is provided "AS IS" without warranty.
23 ******************************************************************************/
25 /******************************************************************************
29 * This module is intended to manage multicast addresses, address override,
30 * and promiscuous mode on GEnesis and Yukon adapters.
33 * port address: physical MAC address
34 * 1st exact match: logical MAC address (GEnesis only)
35 * 2nd exact match: RLMT multicast (GEnesis only)
36 * exact match 3-13: OS-specific multicasts (GEnesis only)
38 * Include File Hierarchy:
43 ******************************************************************************/
45 #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
46 static const char SysKonnectFileId
[] =
47 "@(#) $Id: skaddr.c,v 1.52 2003/06/02 13:46:15 tschilli Exp $ (C) Marvell.";
48 #endif /* DEBUG ||!LINT || !SK_SLIM */
54 #endif /* cplusplus */
56 #include "h/skdrv1st.h"
57 #include "h/skdrv2nd.h"
59 /* defines ********************************************************************/
62 #define XMAC_POLY 0xEDB88320UL /* CRC32-Poly - XMAC: Little Endian */
63 #define GMAC_POLY 0x04C11DB7L /* CRC16-Poly - GMAC: Little Endian */
64 #define HASH_BITS 6 /* #bits in hash */
65 #define SK_MC_BIT 0x01
67 /* Error numbers and messages. */
69 #define SKERR_ADDR_E001 (SK_ERRBASE_ADDR + 0)
70 #define SKERR_ADDR_E001MSG "Bad Flags."
71 #define SKERR_ADDR_E002 (SKERR_ADDR_E001 + 1)
72 #define SKERR_ADDR_E002MSG "New Error."
74 /* typedefs *******************************************************************/
78 /* global variables ***********************************************************/
80 /* 64-bit hash values with all bits set. */
82 static const SK_U16 OnesHash
[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
84 /* local variables ************************************************************/
87 static int Next0
[SK_MAX_MACS
] = {0};
90 /* functions ******************************************************************/
92 /******************************************************************************
94 * SkAddrInit - initialize data, set state to init
101 * This routine clears the multicast tables and resets promiscuous mode.
102 * Some entries are reserved for the "logical MAC address", the
103 * SK-RLMT multicast address, and the BPDU multicast address.
109 * All permanent MAC addresses are read from EPROM.
110 * If the current MAC addresses are not already set in software,
111 * they are set to the values of the permanent addresses.
112 * The current addresses are written to the corresponding MAC.
127 SK_AC
*pAC
, /* the adapter context */
128 SK_IOC IoC
, /* I/O context */
129 int Level
) /* initialization level */
135 SK_ADDR_PORT
*pAPort
;
139 SK_MEMSET((char *) &pAC
->Addr
, (SK_U8
) 0,
140 (SK_U16
) sizeof(SK_ADDR
));
142 for (i
= 0; i
< SK_MAX_MACS
; i
++) {
143 pAPort
= &pAC
->Addr
.Port
[i
];
144 pAPort
->PromMode
= SK_PROM_MODE_NONE
;
146 pAPort
->FirstExactMatchRlmt
= SK_ADDR_FIRST_MATCH_RLMT
;
147 pAPort
->FirstExactMatchDrv
= SK_ADDR_FIRST_MATCH_DRV
;
148 pAPort
->NextExactMatchRlmt
= SK_ADDR_FIRST_MATCH_RLMT
;
149 pAPort
->NextExactMatchDrv
= SK_ADDR_FIRST_MATCH_DRV
;
152 for (i
= 0; i
< SK_MAX_MACS
; i
++) {
153 if (pAC
->Addr
.Port
[i
].NextExactMatchRlmt
<
154 SK_ADDR_FIRST_MATCH_RLMT
) {
159 /* pAC->Addr.InitDone = SK_INIT_DATA; */
164 for (i
= 0; i
< SK_MAX_NETS
; i
++) {
165 pAC
->Addr
.Net
[i
].ActivePort
= pAC
->Rlmt
.Net
[i
].ActivePort
;
167 #endif /* !SK_NO_RLMT */
169 for (i
= 0; i
< SK_MAX_MACS
; i
++) {
170 if (pAC
->Addr
.Port
[i
].NextExactMatchRlmt
<
171 SK_ADDR_FIRST_MATCH_RLMT
) {
177 /* Read permanent logical MAC address from Control Register File. */
178 for (j
= 0; j
< SK_MAC_ADDR_LEN
; j
++) {
179 InAddr
= (SK_U8
*) &pAC
->Addr
.Net
[0].PermanentMacAddress
.a
[j
];
180 SK_IN8(IoC
, B2_MAC_1
+ j
, InAddr
);
183 if (!pAC
->Addr
.Net
[0].CurrentMacAddressSet
) {
184 /* Set the current logical MAC address to the permanent one. */
185 pAC
->Addr
.Net
[0].CurrentMacAddress
=
186 pAC
->Addr
.Net
[0].PermanentMacAddress
;
187 pAC
->Addr
.Net
[0].CurrentMacAddressSet
= SK_TRUE
;
190 /* Set the current logical MAC address. */
191 pAC
->Addr
.Port
[pAC
->Addr
.Net
[0].ActivePort
].Exact
[0] =
192 pAC
->Addr
.Net
[0].CurrentMacAddress
;
194 /* Set logical MAC address for net 2 to (log | 3). */
195 if (!pAC
->Addr
.Net
[1].CurrentMacAddressSet
) {
196 pAC
->Addr
.Net
[1].PermanentMacAddress
=
197 pAC
->Addr
.Net
[0].PermanentMacAddress
;
198 pAC
->Addr
.Net
[1].PermanentMacAddress
.a
[5] |= 3;
199 /* Set the current logical MAC address to the permanent one. */
200 pAC
->Addr
.Net
[1].CurrentMacAddress
=
201 pAC
->Addr
.Net
[1].PermanentMacAddress
;
202 pAC
->Addr
.Net
[1].CurrentMacAddressSet
= SK_TRUE
;
204 #endif /* SK_MAX_NETS > 1 */
207 for (i
= 0; i
< (SK_U32
) pAC
->GIni
.GIMacsFound
; i
++) {
208 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_INIT
,
209 ("Permanent MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
211 pAC
->Addr
.Net
[i
].PermanentMacAddress
.a
[0],
212 pAC
->Addr
.Net
[i
].PermanentMacAddress
.a
[1],
213 pAC
->Addr
.Net
[i
].PermanentMacAddress
.a
[2],
214 pAC
->Addr
.Net
[i
].PermanentMacAddress
.a
[3],
215 pAC
->Addr
.Net
[i
].PermanentMacAddress
.a
[4],
216 pAC
->Addr
.Net
[i
].PermanentMacAddress
.a
[5]))
218 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_INIT
,
219 ("Logical MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
221 pAC
->Addr
.Net
[i
].CurrentMacAddress
.a
[0],
222 pAC
->Addr
.Net
[i
].CurrentMacAddress
.a
[1],
223 pAC
->Addr
.Net
[i
].CurrentMacAddress
.a
[2],
224 pAC
->Addr
.Net
[i
].CurrentMacAddress
.a
[3],
225 pAC
->Addr
.Net
[i
].CurrentMacAddress
.a
[4],
226 pAC
->Addr
.Net
[i
].CurrentMacAddress
.a
[5]))
230 for (i
= 0; i
< (SK_U32
) pAC
->GIni
.GIMacsFound
; i
++) {
231 pAPort
= &pAC
->Addr
.Port
[i
];
233 /* Read permanent port addresses from Control Register File. */
234 for (j
= 0; j
< SK_MAC_ADDR_LEN
; j
++) {
235 InAddr
= (SK_U8
*) &pAPort
->PermanentMacAddress
.a
[j
];
236 SK_IN8(IoC
, B2_MAC_2
+ 8 * i
+ j
, InAddr
);
239 if (!pAPort
->CurrentMacAddressSet
) {
241 * Set the current and previous physical MAC address
242 * of this port to its permanent MAC address.
244 pAPort
->CurrentMacAddress
= pAPort
->PermanentMacAddress
;
245 pAPort
->PreviousMacAddress
= pAPort
->PermanentMacAddress
;
246 pAPort
->CurrentMacAddressSet
= SK_TRUE
;
249 /* Set port's current physical MAC address. */
250 OutAddr
= (SK_U16
*) &pAPort
->CurrentMacAddress
.a
[0];
252 if (pAC
->GIni
.GIGenesis
) {
253 XM_OUTADDR(IoC
, i
, XM_SA
, OutAddr
);
257 if (!pAC
->GIni
.GIGenesis
) {
258 GM_OUTADDR(IoC
, i
, GM_SRC_ADDR_1L
, OutAddr
);
262 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_INIT
,
263 ("SkAddrInit: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
264 pAPort
->PermanentMacAddress
.a
[0],
265 pAPort
->PermanentMacAddress
.a
[1],
266 pAPort
->PermanentMacAddress
.a
[2],
267 pAPort
->PermanentMacAddress
.a
[3],
268 pAPort
->PermanentMacAddress
.a
[4],
269 pAPort
->PermanentMacAddress
.a
[5]))
271 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_INIT
,
272 ("SkAddrInit: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
273 pAPort
->CurrentMacAddress
.a
[0],
274 pAPort
->CurrentMacAddress
.a
[1],
275 pAPort
->CurrentMacAddress
.a
[2],
276 pAPort
->CurrentMacAddress
.a
[3],
277 pAPort
->CurrentMacAddress
.a
[4],
278 pAPort
->CurrentMacAddress
.a
[5]))
281 /* pAC->Addr.InitDone = SK_INIT_IO; */
286 for (i
= 0; i
< SK_MAX_MACS
; i
++) {
287 if (pAC
->Addr
.Port
[i
].NextExactMatchRlmt
<
288 SK_ADDR_FIRST_MATCH_RLMT
) {
294 /* pAC->Addr.InitDone = SK_INIT_RUN; */
301 return (SK_ADDR_SUCCESS
);
307 /******************************************************************************
309 * SkAddrMcClear - clear the multicast table
312 * This routine clears the multicast table.
314 * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
317 * It calls either SkAddrXmacMcClear or SkAddrGmacMcClear, according
318 * to the adapter in use. The real work is done there.
322 * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
323 * may be called after SK_INIT_IO without limitation
327 * SK_ADDR_ILLEGAL_PORT
330 SK_AC
*pAC
, /* adapter context */
331 SK_IOC IoC
, /* I/O context */
332 SK_U32 PortNumber
, /* Index of affected port */
333 int Flags
) /* permanent/non-perm, sw-only */
337 if (PortNumber
>= (SK_U32
) pAC
->GIni
.GIMacsFound
) {
338 return (SK_ADDR_ILLEGAL_PORT
);
341 if (pAC
->GIni
.GIGenesis
) {
342 ReturnCode
= SkAddrXmacMcClear(pAC
, IoC
, PortNumber
, Flags
);
345 ReturnCode
= SkAddrGmacMcClear(pAC
, IoC
, PortNumber
, Flags
);
350 } /* SkAddrMcClear */
352 #endif /* !SK_SLIM */
356 /******************************************************************************
358 * SkAddrXmacMcClear - clear the multicast table
361 * This routine clears the multicast table
362 * (either entry 2 or entries 3-16 and InexactFilter) of the given port.
363 * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
368 * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
369 * may be called after SK_INIT_IO without limitation
373 * SK_ADDR_ILLEGAL_PORT
375 int SkAddrXmacMcClear(
376 SK_AC
*pAC
, /* adapter context */
377 SK_IOC IoC
, /* I/O context */
378 SK_U32 PortNumber
, /* Index of affected port */
379 int Flags
) /* permanent/non-perm, sw-only */
383 if (Flags
& SK_ADDR_PERMANENT
) { /* permanent => RLMT */
385 /* Clear RLMT multicast addresses. */
386 pAC
->Addr
.Port
[PortNumber
].NextExactMatchRlmt
= SK_ADDR_FIRST_MATCH_RLMT
;
388 else { /* not permanent => DRV */
390 /* Clear InexactFilter */
391 for (i
= 0; i
< 8; i
++) {
392 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] = 0;
395 /* Clear DRV multicast addresses. */
397 pAC
->Addr
.Port
[PortNumber
].NextExactMatchDrv
= SK_ADDR_FIRST_MATCH_DRV
;
400 if (!(Flags
& SK_MC_SW_ONLY
)) {
401 (void) SkAddrXmacMcUpdate(pAC
, IoC
, PortNumber
);
404 return (SK_ADDR_SUCCESS
);
406 } /* SkAddrXmacMcClear */
408 #endif /* !SK_SLIM */
412 /******************************************************************************
414 * SkAddrGmacMcClear - clear the multicast table
417 * This routine clears the multicast hashing table (InexactFilter)
418 * (either the RLMT or the driver bits) of the given port.
420 * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
425 * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
426 * may be called after SK_INIT_IO without limitation
430 * SK_ADDR_ILLEGAL_PORT
432 int SkAddrGmacMcClear(
433 SK_AC
*pAC
, /* adapter context */
434 SK_IOC IoC
, /* I/O context */
435 SK_U32 PortNumber
, /* Index of affected port */
436 int Flags
) /* permanent/non-perm, sw-only */
441 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
442 ("GMAC InexactFilter (not cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
443 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[0],
444 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[1],
445 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[2],
446 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[3],
447 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[4],
448 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[5],
449 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[6],
450 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[7]))
453 /* Clear InexactFilter */
454 for (i
= 0; i
< 8; i
++) {
455 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] = 0;
458 if (Flags
& SK_ADDR_PERMANENT
) { /* permanent => RLMT */
460 /* Copy DRV bits to InexactFilter. */
461 for (i
= 0; i
< 8; i
++) {
462 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] |=
463 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[i
];
465 /* Clear InexactRlmtFilter. */
466 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[i
] = 0;
470 else { /* not permanent => DRV */
472 /* Copy RLMT bits to InexactFilter. */
473 for (i
= 0; i
< 8; i
++) {
474 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] |=
475 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[i
];
477 /* Clear InexactDrvFilter. */
478 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[i
] = 0;
483 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
484 ("GMAC InexactFilter (cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
485 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[0],
486 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[1],
487 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[2],
488 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[3],
489 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[4],
490 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[5],
491 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[6],
492 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[7]))
495 if (!(Flags
& SK_MC_SW_ONLY
)) {
496 (void) SkAddrGmacMcUpdate(pAC
, IoC
, PortNumber
);
499 return (SK_ADDR_SUCCESS
);
501 } /* SkAddrGmacMcClear */
503 #ifndef SK_ADDR_CHEAT
505 /******************************************************************************
507 * SkXmacMcHash - hash multicast address
510 * This routine computes the hash value for a multicast address.
511 * A CRC32 algorithm is used.
514 * The code was adapted from the XaQti data sheet.
520 * Hash value of multicast address.
523 unsigned char *pMc
) /* Multicast address */
531 for (Idx
= 0; Idx
< SK_MAC_ADDR_LEN
; Idx
++) {
533 for (Bit
= 0; Bit
< 8; Bit
++, Data
>>= 1) {
534 Crc
= (Crc
>> 1) ^ (((Crc
^ Data
) & 1) ? XMAC_POLY
: 0);
538 return (Crc
& ((1 << HASH_BITS
) - 1));
543 /******************************************************************************
545 * SkGmacMcHash - hash multicast address
548 * This routine computes the hash value for a multicast address.
549 * A CRC16 algorithm is used.
558 * Hash value of multicast address.
561 unsigned char *pMc
) /* Multicast address */
570 for (Byte
= 0; Byte
< 6; Byte
++) {
572 Data
= (SK_U32
) pMc
[Byte
];
574 /* Change bit order in byte. */
576 for (Bit
= 0; Bit
< 8; Bit
++) {
578 Data
|= 1L << (7 - Bit
);
581 Data
&= ~(1L << (7 - Bit
));
587 for (Bit
= 0; Bit
< 8; Bit
++) {
588 if (Crc
& 0x80000000) {
589 Crc
= (Crc
<< 1) ^ GMAC_POLY
;
597 return (Crc
& ((1 << HASH_BITS
) - 1));
601 #endif /* !SK_ADDR_CHEAT */
603 /******************************************************************************
605 * SkAddrMcAdd - add a multicast address to a port
608 * This routine enables reception for a given address on the given port.
610 * It calls either SkAddrXmacMcAdd or SkAddrGmacMcAdd, according to the
611 * adapter in use. The real work is done there.
614 * The return code is only valid for SK_PROM_MODE_NONE.
618 * may be called after SK_INIT_DATA
621 * SK_MC_FILTERING_EXACT
622 * SK_MC_FILTERING_INEXACT
623 * SK_MC_ILLEGAL_ADDRESS
625 * SK_MC_RLMT_OVERFLOW
628 SK_AC
*pAC
, /* adapter context */
629 SK_IOC IoC
, /* I/O context */
630 SK_U32 PortNumber
, /* Port Number */
631 SK_MAC_ADDR
*pMc
, /* multicast address to be added */
632 int Flags
) /* permanent/non-permanent */
636 if (PortNumber
>= (SK_U32
) pAC
->GIni
.GIMacsFound
) {
637 return (SK_ADDR_ILLEGAL_PORT
);
640 if (pAC
->GIni
.GIGenesis
) {
641 ReturnCode
= SkAddrXmacMcAdd(pAC
, IoC
, PortNumber
, pMc
, Flags
);
644 ReturnCode
= SkAddrGmacMcAdd(pAC
, IoC
, PortNumber
, pMc
, Flags
);
652 /******************************************************************************
654 * SkAddrXmacMcAdd - add a multicast address to a port
657 * This routine enables reception for a given address on the given port.
660 * The return code is only valid for SK_PROM_MODE_NONE.
662 * The multicast bit is only checked if there are no free exact match
667 * may be called after SK_INIT_DATA
670 * SK_MC_FILTERING_EXACT
671 * SK_MC_FILTERING_INEXACT
672 * SK_MC_ILLEGAL_ADDRESS
673 * SK_MC_RLMT_OVERFLOW
676 SK_AC
*pAC
, /* adapter context */
677 SK_IOC IoC
, /* I/O context */
678 SK_U32 PortNumber
, /* Port Number */
679 SK_MAC_ADDR
*pMc
, /* multicast address to be added */
680 int Flags
) /* permanent/non-permanent */
684 #ifndef SK_ADDR_CHEAT
686 #endif /* !defined(SK_ADDR_CHEAT) */
688 if (Flags
& SK_ADDR_PERMANENT
) { /* permanent => RLMT */
690 if (pAC
->Addr
.Port
[PortNumber
].NextExactMatchRlmt
<
691 SK_ADDR_FIRST_MATCH_RLMT
) {
692 Next0
[PortNumber
] |= 1;
693 return (SK_MC_RLMT_OVERFLOW
);
697 if (pAC
->Addr
.Port
[PortNumber
].NextExactMatchRlmt
>
698 SK_ADDR_LAST_MATCH_RLMT
) {
699 return (SK_MC_RLMT_OVERFLOW
);
702 /* Set a RLMT multicast address. */
704 pAC
->Addr
.Port
[PortNumber
].Exact
[
705 pAC
->Addr
.Port
[PortNumber
].NextExactMatchRlmt
++] = *pMc
;
707 return (SK_MC_FILTERING_EXACT
);
711 if (pAC
->Addr
.Port
[PortNumber
].NextExactMatchDrv
<
712 SK_ADDR_FIRST_MATCH_DRV
) {
713 Next0
[PortNumber
] |= 2;
714 return (SK_MC_RLMT_OVERFLOW
);
718 if (pAC
->Addr
.Port
[PortNumber
].NextExactMatchDrv
<= SK_ADDR_LAST_MATCH_DRV
) {
720 /* Set exact match entry. */
721 pAC
->Addr
.Port
[PortNumber
].Exact
[
722 pAC
->Addr
.Port
[PortNumber
].NextExactMatchDrv
++] = *pMc
;
724 /* Clear InexactFilter */
725 for (i
= 0; i
< 8; i
++) {
726 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] = 0;
730 if (!(pMc
->a
[0] & SK_MC_BIT
)) {
731 /* Hashing only possible with multicast addresses */
732 return (SK_MC_ILLEGAL_ADDRESS
);
734 #ifndef SK_ADDR_CHEAT
735 /* Compute hash value of address. */
736 HashBit
= 63 - SkXmacMcHash(&pMc
->a
[0]);
738 /* Add bit to InexactFilter. */
739 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[HashBit
/ 8] |=
741 #else /* SK_ADDR_CHEAT */
742 /* Set all bits in InexactFilter. */
743 for (i
= 0; i
< 8; i
++) {
744 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] = 0xFF;
746 #endif /* SK_ADDR_CHEAT */
749 for (Inexact
= 0, i
= 0; i
< 8; i
++) {
750 Inexact
|= pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
];
753 if (Inexact
== 0 && pAC
->Addr
.Port
[PortNumber
].PromMode
== 0) {
754 return (SK_MC_FILTERING_EXACT
);
757 return (SK_MC_FILTERING_INEXACT
);
760 } /* SkAddrXmacMcAdd */
763 /******************************************************************************
765 * SkAddrGmacMcAdd - add a multicast address to a port
768 * This routine enables reception for a given address on the given port.
771 * The return code is only valid for SK_PROM_MODE_NONE.
775 * may be called after SK_INIT_DATA
778 * SK_MC_FILTERING_INEXACT
779 * SK_MC_ILLEGAL_ADDRESS
782 SK_AC
*pAC
, /* adapter context */
783 SK_IOC IoC
, /* I/O context */
784 SK_U32 PortNumber
, /* Port Number */
785 SK_MAC_ADDR
*pMc
, /* multicast address to be added */
786 int Flags
) /* permanent/non-permanent */
789 #ifndef SK_ADDR_CHEAT
791 #endif /* !defined(SK_ADDR_CHEAT) */
793 if (!(pMc
->a
[0] & SK_MC_BIT
)) {
794 /* Hashing only possible with multicast addresses */
795 return (SK_MC_ILLEGAL_ADDRESS
);
798 #ifndef SK_ADDR_CHEAT
800 /* Compute hash value of address. */
801 HashBit
= SkGmacMcHash(&pMc
->a
[0]);
803 if (Flags
& SK_ADDR_PERMANENT
) { /* permanent => RLMT */
805 /* Add bit to InexactRlmtFilter. */
806 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[HashBit
/ 8] |=
809 /* Copy bit to InexactFilter. */
810 for (i
= 0; i
< 8; i
++) {
811 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] |=
812 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[i
];
815 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
816 ("GMAC InexactRlmtFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
817 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[0],
818 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[1],
819 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[2],
820 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[3],
821 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[4],
822 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[5],
823 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[6],
824 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[7]))
827 else { /* not permanent => DRV */
829 /* Add bit to InexactDrvFilter. */
830 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[HashBit
/ 8] |=
833 /* Copy bit to InexactFilter. */
834 for (i
= 0; i
< 8; i
++) {
835 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] |=
836 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[i
];
839 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
840 ("GMAC InexactDrvFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
841 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[0],
842 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[1],
843 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[2],
844 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[3],
845 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[4],
846 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[5],
847 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[6],
848 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[7]))
852 #else /* SK_ADDR_CHEAT */
854 /* Set all bits in InexactFilter. */
855 for (i
= 0; i
< 8; i
++) {
856 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] = 0xFF;
858 #endif /* SK_ADDR_CHEAT */
860 return (SK_MC_FILTERING_INEXACT
);
862 } /* SkAddrGmacMcAdd */
864 #endif /* !SK_SLIM */
866 /******************************************************************************
868 * SkAddrMcUpdate - update the HW MC address table and set the MAC address
871 * This routine enables reception of the addresses contained in a local
872 * table for a given port.
873 * It also programs the port's current physical MAC address.
875 * It calls either SkAddrXmacMcUpdate or SkAddrGmacMcUpdate, according
876 * to the adapter in use. The real work is done there.
879 * The return code is only valid for SK_PROM_MODE_NONE.
883 * may be called after SK_INIT_IO
886 * SK_MC_FILTERING_EXACT
887 * SK_MC_FILTERING_INEXACT
888 * SK_ADDR_ILLEGAL_PORT
891 SK_AC
*pAC
, /* adapter context */
892 SK_IOC IoC
, /* I/O context */
893 SK_U32 PortNumber
) /* Port Number */
896 #if (!defined(SK_SLIM) || defined(DEBUG))
897 if (PortNumber
>= (SK_U32
) pAC
->GIni
.GIMacsFound
) {
898 return (SK_ADDR_ILLEGAL_PORT
);
900 #endif /* !SK_SLIM || DEBUG */
903 if (pAC
->GIni
.GIGenesis
) {
904 ReturnCode
= SkAddrXmacMcUpdate(pAC
, IoC
, PortNumber
);
908 if (!pAC
->GIni
.GIGenesis
) {
909 ReturnCode
= SkAddrGmacMcUpdate(pAC
, IoC
, PortNumber
);
914 } /* SkAddrMcUpdate */
919 /******************************************************************************
921 * SkAddrXmacMcUpdate - update the HW MC address table and set the MAC address
924 * This routine enables reception of the addresses contained in a local
925 * table for a given port.
926 * It also programs the port's current physical MAC address.
929 * The return code is only valid for SK_PROM_MODE_NONE.
933 * may be called after SK_INIT_IO
936 * SK_MC_FILTERING_EXACT
937 * SK_MC_FILTERING_INEXACT
938 * SK_ADDR_ILLEGAL_PORT
940 int SkAddrXmacMcUpdate(
941 SK_AC
*pAC
, /* adapter context */
942 SK_IOC IoC
, /* I/O context */
943 SK_U32 PortNumber
) /* Port Number */
948 SK_ADDR_PORT
*pAPort
;
950 SK_DBG_MSG(pAC
,SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
951 ("SkAddrXmacMcUpdate on Port %u.\n", PortNumber
))
953 pAPort
= &pAC
->Addr
.Port
[PortNumber
];
956 SK_DBG_MSG(pAC
,SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
957 ("Next0 on Port %d: %d\n", PortNumber
, Next0
[PortNumber
]))
960 /* Start with 0 to also program the logical MAC address. */
961 for (i
= 0; i
< pAPort
->NextExactMatchRlmt
; i
++) {
962 /* Set exact match address i on XMAC */
963 OutAddr
= (SK_U16
*) &pAPort
->Exact
[i
].a
[0];
964 XM_OUTADDR(IoC
, PortNumber
, XM_EXM(i
), OutAddr
);
967 /* Clear other permanent exact match addresses on XMAC */
968 if (pAPort
->NextExactMatchRlmt
<= SK_ADDR_LAST_MATCH_RLMT
) {
970 SkXmClrExactAddr(pAC
, IoC
, PortNumber
, pAPort
->NextExactMatchRlmt
,
971 SK_ADDR_LAST_MATCH_RLMT
);
974 for (i
= pAPort
->FirstExactMatchDrv
; i
< pAPort
->NextExactMatchDrv
; i
++) {
975 OutAddr
= (SK_U16
*) &pAPort
->Exact
[i
].a
[0];
976 XM_OUTADDR(IoC
, PortNumber
, XM_EXM(i
), OutAddr
);
979 /* Clear other non-permanent exact match addresses on XMAC */
980 if (pAPort
->NextExactMatchDrv
<= SK_ADDR_LAST_MATCH_DRV
) {
982 SkXmClrExactAddr(pAC
, IoC
, PortNumber
, pAPort
->NextExactMatchDrv
,
983 SK_ADDR_LAST_MATCH_DRV
);
986 for (Inexact
= 0, i
= 0; i
< 8; i
++) {
987 Inexact
|= pAPort
->InexactFilter
.Bytes
[i
];
990 if (pAPort
->PromMode
& SK_PROM_MODE_ALL_MC
) {
992 /* Set all bits in 64-bit hash register. */
993 XM_OUTHASH(IoC
, PortNumber
, XM_HSM
, &OnesHash
);
996 SkMacHashing(pAC
, IoC
, (int) PortNumber
, SK_TRUE
);
998 else if (Inexact
!= 0) {
1000 /* Set 64-bit hash register to InexactFilter. */
1001 XM_OUTHASH(IoC
, PortNumber
, XM_HSM
, &pAPort
->InexactFilter
.Bytes
[0]);
1003 /* Enable Hashing */
1004 SkMacHashing(pAC
, IoC
, (int) PortNumber
, SK_TRUE
);
1007 /* Disable Hashing */
1008 SkMacHashing(pAC
, IoC
, (int) PortNumber
, SK_FALSE
);
1011 if (pAPort
->PromMode
!= SK_PROM_MODE_NONE
) {
1012 (void) SkAddrXmacPromiscuousChange(pAC
, IoC
, PortNumber
, pAPort
->PromMode
);
1015 /* Set port's current physical MAC address. */
1016 OutAddr
= (SK_U16
*) &pAPort
->CurrentMacAddress
.a
[0];
1018 XM_OUTADDR(IoC
, PortNumber
, XM_SA
, OutAddr
);
1021 for (i
= 0; i
< pAPort
->NextExactMatchRlmt
; i
++) {
1025 /* Get exact match address i from port PortNumber. */
1026 InAddr
= (SK_U16
*) &InAddr8
[0];
1028 XM_INADDR(IoC
, PortNumber
, XM_EXM(i
), InAddr
);
1030 SK_DBG_MSG(pAC
,SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
1031 ("SkAddrXmacMcUpdate: MC address %d on Port %u: ",
1032 "%02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x\n",
1041 pAPort
->Exact
[i
].a
[0],
1042 pAPort
->Exact
[i
].a
[1],
1043 pAPort
->Exact
[i
].a
[2],
1044 pAPort
->Exact
[i
].a
[3],
1045 pAPort
->Exact
[i
].a
[4],
1046 pAPort
->Exact
[i
].a
[5]))
1050 /* Determine return value. */
1051 if (Inexact
== 0 && pAPort
->PromMode
== 0) {
1052 return (SK_MC_FILTERING_EXACT
);
1055 return (SK_MC_FILTERING_INEXACT
);
1058 } /* SkAddrXmacMcUpdate */
1060 #endif /* GENESIS */
1064 /******************************************************************************
1066 * SkAddrGmacMcUpdate - update the HW MC address table and set the MAC address
1069 * This routine enables reception of the addresses contained in a local
1070 * table for a given port.
1071 * It also programs the port's current physical MAC address.
1074 * The return code is only valid for SK_PROM_MODE_NONE.
1078 * may be called after SK_INIT_IO
1081 * SK_MC_FILTERING_EXACT
1082 * SK_MC_FILTERING_INEXACT
1083 * SK_ADDR_ILLEGAL_PORT
1085 int SkAddrGmacMcUpdate(
1086 SK_AC
*pAC
, /* adapter context */
1087 SK_IOC IoC
, /* I/O context */
1088 SK_U32 PortNumber
) /* Port Number */
1093 #endif /* not SK_SLIM */
1095 SK_ADDR_PORT
*pAPort
;
1097 SK_DBG_MSG(pAC
,SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
1098 ("SkAddrGmacMcUpdate on Port %u.\n", PortNumber
))
1100 pAPort
= &pAC
->Addr
.Port
[PortNumber
];
1103 SK_DBG_MSG(pAC
,SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
1104 ("Next0 on Port %d: %d\n", PortNumber
, Next0
[PortNumber
]))
1108 for (Inexact
= 0, i
= 0; i
< 8; i
++) {
1109 Inexact
|= pAPort
->InexactFilter
.Bytes
[i
];
1112 /* Set 64-bit hash register to InexactFilter. */
1113 GM_OUTHASH(IoC
, PortNumber
, GM_MC_ADDR_H1
,
1114 &pAPort
->InexactFilter
.Bytes
[0]);
1116 if (pAPort
->PromMode
& SK_PROM_MODE_ALL_MC
) {
1118 /* Set all bits in 64-bit hash register. */
1119 GM_OUTHASH(IoC
, PortNumber
, GM_MC_ADDR_H1
, &OnesHash
);
1121 /* Enable Hashing */
1122 SkMacHashing(pAC
, IoC
, (int) PortNumber
, SK_TRUE
);
1125 /* Enable Hashing. */
1126 SkMacHashing(pAC
, IoC
, (int) PortNumber
, SK_TRUE
);
1129 if (pAPort
->PromMode
!= SK_PROM_MODE_NONE
) {
1130 (void) SkAddrGmacPromiscuousChange(pAC
, IoC
, PortNumber
, pAPort
->PromMode
);
1134 /* Set all bits in 64-bit hash register. */
1135 GM_OUTHASH(IoC
, PortNumber
, GM_MC_ADDR_H1
, &OnesHash
);
1137 /* Enable Hashing */
1138 SkMacHashing(pAC
, IoC
, (int) PortNumber
, SK_TRUE
);
1140 (void) SkAddrGmacPromiscuousChange(pAC
, IoC
, PortNumber
, pAPort
->PromMode
);
1142 #endif /* SK_SLIM */
1144 /* Set port's current physical MAC address. */
1145 OutAddr
= (SK_U16
*) &pAPort
->CurrentMacAddress
.a
[0];
1146 GM_OUTADDR(IoC
, PortNumber
, GM_SRC_ADDR_1L
, OutAddr
);
1148 /* Set port's current logical MAC address. */
1149 OutAddr
= (SK_U16
*) &pAPort
->Exact
[0].a
[0];
1150 GM_OUTADDR(IoC
, PortNumber
, GM_SRC_ADDR_2L
, OutAddr
);
1153 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
1154 ("SkAddrGmacMcUpdate: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
1155 pAPort
->Exact
[0].a
[0],
1156 pAPort
->Exact
[0].a
[1],
1157 pAPort
->Exact
[0].a
[2],
1158 pAPort
->Exact
[0].a
[3],
1159 pAPort
->Exact
[0].a
[4],
1160 pAPort
->Exact
[0].a
[5]))
1162 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
1163 ("SkAddrGmacMcUpdate: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
1164 pAPort
->CurrentMacAddress
.a
[0],
1165 pAPort
->CurrentMacAddress
.a
[1],
1166 pAPort
->CurrentMacAddress
.a
[2],
1167 pAPort
->CurrentMacAddress
.a
[3],
1168 pAPort
->CurrentMacAddress
.a
[4],
1169 pAPort
->CurrentMacAddress
.a
[5]))
1173 /* Determine return value. */
1174 if (Inexact
== 0 && pAPort
->PromMode
== 0) {
1175 return (SK_MC_FILTERING_EXACT
);
1178 return (SK_MC_FILTERING_INEXACT
);
1181 return (SK_MC_FILTERING_INEXACT
);
1182 #endif /* SK_SLIM */
1184 } /* SkAddrGmacMcUpdate */
1190 /******************************************************************************
1192 * SkAddrOverride - override a port's MAC address
1195 * This routine overrides the MAC address of one port.
1199 * may be called after SK_INIT_IO
1202 * SK_ADDR_SUCCESS if successful.
1203 * SK_ADDR_DUPLICATE_ADDRESS if duplicate MAC address.
1204 * SK_ADDR_MULTICAST_ADDRESS if multicast or broadcast address.
1205 * SK_ADDR_TOO_EARLY if SK_INIT_IO was not executed before.
1208 SK_AC
*pAC
, /* adapter context */
1209 SK_IOC IoC
, /* I/O context */
1210 SK_U32 PortNumber
, /* Port Number */
1211 SK_MAC_ADDR SK_FAR
*pNewAddr
, /* new MAC address */
1212 int Flags
) /* logical/physical MAC address */
1216 #endif /* !SK_NO_RLMT */
1219 SK_U16 SK_FAR
*OutAddr
;
1222 NetNumber
= pAC
->Rlmt
.Port
[PortNumber
].Net
->NetNumber
;
1225 #endif /* SK_NO_RLMT */
1226 #if (!defined(SK_SLIM) || defined(DEBUG))
1227 if (PortNumber
>= (SK_U32
) pAC
->GIni
.GIMacsFound
) {
1228 return (SK_ADDR_ILLEGAL_PORT
);
1230 #endif /* !SK_SLIM || DEBUG */
1231 if (pNewAddr
!= NULL
&& (pNewAddr
->a
[0] & SK_MC_BIT
) != 0) {
1232 return (SK_ADDR_MULTICAST_ADDRESS
);
1235 if (!pAC
->Addr
.Net
[NetNumber
].CurrentMacAddressSet
) {
1236 return (SK_ADDR_TOO_EARLY
);
1239 if (Flags
& SK_ADDR_SET_LOGICAL
) { /* Activate logical MAC address. */
1240 /* Parameter *pNewAddr is ignored. */
1241 for (i
= 0; i
< (SK_U32
) pAC
->GIni
.GIMacsFound
; i
++) {
1242 if (!pAC
->Addr
.Port
[i
].CurrentMacAddressSet
) {
1243 return (SK_ADDR_TOO_EARLY
);
1247 /* Set PortNumber to number of net's active port. */
1248 PortNumber
= pAC
->Rlmt
.Net
[NetNumber
].
1249 Port
[pAC
->Addr
.Net
[NetNumber
].ActivePort
]->PortNumber
;
1250 #endif /* !SK_NO_RLMT */
1251 pAC
->Addr
.Port
[PortNumber
].Exact
[0] =
1252 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
;
1254 /* Write address to first exact match entry of active port. */
1255 (void) SkAddrMcUpdate(pAC
, IoC
, PortNumber
);
1257 else if (Flags
& SK_ADDR_CLEAR_LOGICAL
) {
1258 /* Deactivate logical MAC address. */
1259 /* Parameter *pNewAddr is ignored. */
1260 for (i
= 0; i
< (SK_U32
) pAC
->GIni
.GIMacsFound
; i
++) {
1261 if (!pAC
->Addr
.Port
[i
].CurrentMacAddressSet
) {
1262 return (SK_ADDR_TOO_EARLY
);
1266 /* Set PortNumber to number of net's active port. */
1267 PortNumber
= pAC
->Rlmt
.Net
[NetNumber
].
1268 Port
[pAC
->Addr
.Net
[NetNumber
].ActivePort
]->PortNumber
;
1269 #endif /* !SK_NO_RLMT */
1270 for (i
= 0; i
< SK_MAC_ADDR_LEN
; i
++ ) {
1271 pAC
->Addr
.Port
[PortNumber
].Exact
[0].a
[i
] = 0;
1274 /* Write address to first exact match entry of active port. */
1275 (void) SkAddrMcUpdate(pAC
, IoC
, PortNumber
);
1277 else if (Flags
& SK_ADDR_PHYSICAL_ADDRESS
) { /* Physical MAC address. */
1278 if (SK_ADDR_EQUAL(pNewAddr
->a
,
1279 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
.a
)) {
1280 return (SK_ADDR_DUPLICATE_ADDRESS
);
1283 for (i
= 0; i
< (SK_U32
) pAC
->GIni
.GIMacsFound
; i
++) {
1284 if (!pAC
->Addr
.Port
[i
].CurrentMacAddressSet
) {
1285 return (SK_ADDR_TOO_EARLY
);
1288 if (SK_ADDR_EQUAL(pNewAddr
->a
,
1289 pAC
->Addr
.Port
[i
].CurrentMacAddress
.a
)) {
1290 if (i
== PortNumber
) {
1291 return (SK_ADDR_SUCCESS
);
1294 return (SK_ADDR_DUPLICATE_ADDRESS
);
1299 pAC
->Addr
.Port
[PortNumber
].PreviousMacAddress
=
1300 pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
;
1301 pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
= *pNewAddr
;
1303 /* Change port's physical MAC address. */
1304 OutAddr
= (SK_U16 SK_FAR
*) pNewAddr
;
1306 if (pAC
->GIni
.GIGenesis
) {
1307 XM_OUTADDR(IoC
, PortNumber
, XM_SA
, OutAddr
);
1309 #endif /* GENESIS */
1311 if (!pAC
->GIni
.GIGenesis
) {
1312 GM_OUTADDR(IoC
, PortNumber
, GM_SRC_ADDR_1L
, OutAddr
);
1317 /* Report address change to RLMT. */
1318 Para
.Para32
[0] = PortNumber
;
1319 Para
.Para32
[0] = -1;
1320 SkEventQueue(pAC
, SKGE_RLMT
, SK_RLMT_PORT_ADDR
, Para
);
1321 #endif /* !SK_NO_RLMT */
1323 else { /* Logical MAC address. */
1324 if (SK_ADDR_EQUAL(pNewAddr
->a
,
1325 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
.a
)) {
1326 return (SK_ADDR_SUCCESS
);
1329 for (i
= 0; i
< (SK_U32
) pAC
->GIni
.GIMacsFound
; i
++) {
1330 if (!pAC
->Addr
.Port
[i
].CurrentMacAddressSet
) {
1331 return (SK_ADDR_TOO_EARLY
);
1334 if (SK_ADDR_EQUAL(pNewAddr
->a
,
1335 pAC
->Addr
.Port
[i
].CurrentMacAddress
.a
)) {
1336 return (SK_ADDR_DUPLICATE_ADDRESS
);
1341 * In case that the physical and the logical MAC addresses are equal
1342 * we must also change the physical MAC address here.
1343 * In this case we have an adapter which initially was programmed with
1344 * two identical MAC addresses.
1346 if (SK_ADDR_EQUAL(pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
.a
,
1347 pAC
->Addr
.Port
[PortNumber
].Exact
[0].a
)) {
1349 pAC
->Addr
.Port
[PortNumber
].PreviousMacAddress
=
1350 pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
;
1351 pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
= *pNewAddr
;
1354 /* Report address change to RLMT. */
1355 Para
.Para32
[0] = PortNumber
;
1356 Para
.Para32
[0] = -1;
1357 SkEventQueue(pAC
, SKGE_RLMT
, SK_RLMT_PORT_ADDR
, Para
);
1358 #endif /* !SK_NO_RLMT */
1362 /* Set PortNumber to number of net's active port. */
1363 PortNumber
= pAC
->Rlmt
.Net
[NetNumber
].
1364 Port
[pAC
->Addr
.Net
[NetNumber
].ActivePort
]->PortNumber
;
1365 #endif /* !SK_NO_RLMT */
1366 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
= *pNewAddr
;
1367 pAC
->Addr
.Port
[PortNumber
].Exact
[0] = *pNewAddr
;
1369 SK_DBG_MSG(pAC
,SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
1370 ("SkAddrOverride: Permanent MAC Address: %02X %02X %02X %02X %02X %02X\n",
1371 pAC
->Addr
.Net
[NetNumber
].PermanentMacAddress
.a
[0],
1372 pAC
->Addr
.Net
[NetNumber
].PermanentMacAddress
.a
[1],
1373 pAC
->Addr
.Net
[NetNumber
].PermanentMacAddress
.a
[2],
1374 pAC
->Addr
.Net
[NetNumber
].PermanentMacAddress
.a
[3],
1375 pAC
->Addr
.Net
[NetNumber
].PermanentMacAddress
.a
[4],
1376 pAC
->Addr
.Net
[NetNumber
].PermanentMacAddress
.a
[5]))
1378 SK_DBG_MSG(pAC
,SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
1379 ("SkAddrOverride: New logical MAC Address: %02X %02X %02X %02X %02X %02X\n",
1380 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
.a
[0],
1381 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
.a
[1],
1382 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
.a
[2],
1383 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
.a
[3],
1384 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
.a
[4],
1385 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
.a
[5]))
1388 /* Write address to first exact match entry of active port. */
1389 (void) SkAddrMcUpdate(pAC
, IoC
, PortNumber
);
1392 return (SK_ADDR_SUCCESS
);
1394 } /* SkAddrOverride */
1397 #endif /* SK_NO_MAO */
1399 /******************************************************************************
1401 * SkAddrPromiscuousChange - set promiscuous mode for given port
1404 * This routine manages promiscuous mode:
1409 * It calls either SkAddrXmacPromiscuousChange or
1410 * SkAddrGmacPromiscuousChange, according to the adapter in use.
1411 * The real work is done there.
1415 * may be called after SK_INIT_IO
1419 * SK_ADDR_ILLEGAL_PORT
1421 int SkAddrPromiscuousChange(
1422 SK_AC
*pAC
, /* adapter context */
1423 SK_IOC IoC
, /* I/O context */
1424 SK_U32 PortNumber
, /* port whose promiscuous mode changes */
1425 int NewPromMode
) /* new promiscuous mode */
1428 #if (!defined(SK_SLIM) || defined(DEBUG))
1429 if (PortNumber
>= (SK_U32
) pAC
->GIni
.GIMacsFound
) {
1430 return (SK_ADDR_ILLEGAL_PORT
);
1432 #endif /* !SK_SLIM || DEBUG */
1435 if (pAC
->GIni
.GIGenesis
) {
1437 SkAddrXmacPromiscuousChange(pAC
, IoC
, PortNumber
, NewPromMode
);
1439 #endif /* GENESIS */
1441 if (!pAC
->GIni
.GIGenesis
) {
1443 SkAddrGmacPromiscuousChange(pAC
, IoC
, PortNumber
, NewPromMode
);
1447 return (ReturnCode
);
1449 } /* SkAddrPromiscuousChange */
1453 /******************************************************************************
1455 * SkAddrXmacPromiscuousChange - set promiscuous mode for given port
1458 * This routine manages promiscuous mode:
1465 * may be called after SK_INIT_IO
1469 * SK_ADDR_ILLEGAL_PORT
1471 int SkAddrXmacPromiscuousChange(
1472 SK_AC
*pAC
, /* adapter context */
1473 SK_IOC IoC
, /* I/O context */
1474 SK_U32 PortNumber
, /* port whose promiscuous mode changes */
1475 int NewPromMode
) /* new promiscuous mode */
1478 SK_BOOL InexactModeBit
;
1481 SK_FILTER64 HwInexactFilter
;
1482 SK_U16 LoMode
; /* Lower 16 bits of XMAC Mode Register. */
1483 int CurPromMode
= SK_PROM_MODE_NONE
;
1485 /* Read CurPromMode from Hardware. */
1486 XM_IN16(IoC
, PortNumber
, XM_MODE
, &LoMode
);
1488 if ((LoMode
& XM_MD_ENA_PROM
) != 0) {
1489 /* Promiscuous mode! */
1490 CurPromMode
|= SK_PROM_MODE_LLC
;
1493 for (Inexact
= 0xFF, i
= 0; i
< 8; i
++) {
1494 Inexact
&= pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
];
1496 if (Inexact
== 0xFF) {
1497 CurPromMode
|= (pAC
->Addr
.Port
[PortNumber
].PromMode
& SK_PROM_MODE_ALL_MC
);
1500 /* Get InexactModeBit (bit XM_MD_ENA_HASH in mode register) */
1501 XM_IN16(IoC
, PortNumber
, XM_MODE
, &LoMode
);
1503 InexactModeBit
= (LoMode
& XM_MD_ENA_HASH
) != 0;
1505 /* Read 64-bit hash register from XMAC */
1506 XM_INHASH(IoC
, PortNumber
, XM_HSM
, &HwInexactFilter
.Bytes
[0]);
1508 for (HwInexact
= 0xFF, i
= 0; i
< 8; i
++) {
1509 HwInexact
&= HwInexactFilter
.Bytes
[i
];
1512 if (InexactModeBit
&& (HwInexact
== 0xFF)) {
1513 CurPromMode
|= SK_PROM_MODE_ALL_MC
;
1517 pAC
->Addr
.Port
[PortNumber
].PromMode
= NewPromMode
;
1519 if (NewPromMode
== CurPromMode
) {
1520 return (SK_ADDR_SUCCESS
);
1523 if ((NewPromMode
& SK_PROM_MODE_ALL_MC
) &&
1524 !(CurPromMode
& SK_PROM_MODE_ALL_MC
)) { /* All MC. */
1526 /* Set all bits in 64-bit hash register. */
1527 XM_OUTHASH(IoC
, PortNumber
, XM_HSM
, &OnesHash
);
1529 /* Enable Hashing */
1530 SkMacHashing(pAC
, IoC
, (int) PortNumber
, SK_TRUE
);
1532 else if ((CurPromMode
& SK_PROM_MODE_ALL_MC
) &&
1533 !(NewPromMode
& SK_PROM_MODE_ALL_MC
)) { /* Norm MC. */
1534 for (Inexact
= 0, i
= 0; i
< 8; i
++) {
1535 Inexact
|= pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
];
1538 /* Disable Hashing */
1539 SkMacHashing(pAC
, IoC
, (int) PortNumber
, SK_FALSE
);
1542 /* Set 64-bit hash register to InexactFilter. */
1543 XM_OUTHASH(IoC
, PortNumber
, XM_HSM
,
1544 &pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[0]);
1546 /* Enable Hashing */
1547 SkMacHashing(pAC
, IoC
, (int) PortNumber
, SK_TRUE
);
1551 if ((NewPromMode
& SK_PROM_MODE_LLC
) &&
1552 !(CurPromMode
& SK_PROM_MODE_LLC
)) { /* Prom. LLC */
1553 /* Set the MAC in Promiscuous Mode */
1554 SkMacPromiscMode(pAC
, IoC
, (int) PortNumber
, SK_TRUE
);
1556 else if ((CurPromMode
& SK_PROM_MODE_LLC
) &&
1557 !(NewPromMode
& SK_PROM_MODE_LLC
)) { /* Norm. LLC. */
1558 /* Clear Promiscuous Mode */
1559 SkMacPromiscMode(pAC
, IoC
, (int) PortNumber
, SK_FALSE
);
1562 return (SK_ADDR_SUCCESS
);
1564 } /* SkAddrXmacPromiscuousChange */
1566 #endif /* GENESIS */
1570 /******************************************************************************
1572 * SkAddrGmacPromiscuousChange - set promiscuous mode for given port
1575 * This routine manages promiscuous mode:
1582 * may be called after SK_INIT_IO
1586 * SK_ADDR_ILLEGAL_PORT
1588 int SkAddrGmacPromiscuousChange(
1589 SK_AC
*pAC
, /* adapter context */
1590 SK_IOC IoC
, /* I/O context */
1591 SK_U32 PortNumber
, /* port whose promiscuous mode changes */
1592 int NewPromMode
) /* new promiscuous mode */
1594 SK_U16 ReceiveControl
; /* GMAC Receive Control Register */
1595 int CurPromMode
= SK_PROM_MODE_NONE
;
1597 /* Read CurPromMode from Hardware. */
1598 GM_IN16(IoC
, PortNumber
, GM_RX_CTRL
, &ReceiveControl
);
1600 if ((ReceiveControl
& (GM_RXCR_UCF_ENA
| GM_RXCR_MCF_ENA
)) == 0) {
1601 /* Promiscuous mode! */
1602 CurPromMode
|= SK_PROM_MODE_LLC
;
1605 if ((ReceiveControl
& GM_RXCR_MCF_ENA
) == 0) {
1606 /* All Multicast mode! */
1607 CurPromMode
|= (pAC
->Addr
.Port
[PortNumber
].PromMode
& SK_PROM_MODE_ALL_MC
);
1610 pAC
->Addr
.Port
[PortNumber
].PromMode
= NewPromMode
;
1612 if (NewPromMode
== CurPromMode
) {
1613 return (SK_ADDR_SUCCESS
);
1616 if ((NewPromMode
& SK_PROM_MODE_ALL_MC
) &&
1617 !(CurPromMode
& SK_PROM_MODE_ALL_MC
)) { /* All MC */
1619 /* Set all bits in 64-bit hash register. */
1620 GM_OUTHASH(IoC
, PortNumber
, GM_MC_ADDR_H1
, &OnesHash
);
1622 /* Enable Hashing */
1623 SkMacHashing(pAC
, IoC
, (int) PortNumber
, SK_TRUE
);
1626 if ((CurPromMode
& SK_PROM_MODE_ALL_MC
) &&
1627 !(NewPromMode
& SK_PROM_MODE_ALL_MC
)) { /* Norm. MC */
1629 /* Set 64-bit hash register to InexactFilter. */
1630 GM_OUTHASH(IoC
, PortNumber
, GM_MC_ADDR_H1
,
1631 &pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[0]);
1633 /* Enable Hashing. */
1634 SkMacHashing(pAC
, IoC
, (int) PortNumber
, SK_TRUE
);
1637 if ((NewPromMode
& SK_PROM_MODE_LLC
) &&
1638 !(CurPromMode
& SK_PROM_MODE_LLC
)) { /* Prom. LLC */
1640 /* Set the MAC to Promiscuous Mode. */
1641 SkMacPromiscMode(pAC
, IoC
, (int) PortNumber
, SK_TRUE
);
1643 else if ((CurPromMode
& SK_PROM_MODE_LLC
) &&
1644 !(NewPromMode
& SK_PROM_MODE_LLC
)) { /* Norm. LLC */
1646 /* Clear Promiscuous Mode. */
1647 SkMacPromiscMode(pAC
, IoC
, (int) PortNumber
, SK_FALSE
);
1650 return (SK_ADDR_SUCCESS
);
1652 } /* SkAddrGmacPromiscuousChange */
1658 /******************************************************************************
1660 * SkAddrSwap - swap address info
1663 * This routine swaps address info of two ports.
1667 * may be called after SK_INIT_IO
1671 * SK_ADDR_ILLEGAL_PORT
1674 SK_AC
*pAC
, /* adapter context */
1675 SK_IOC IoC
, /* I/O context */
1676 SK_U32 FromPortNumber
, /* Port1 Index */
1677 SK_U32 ToPortNumber
) /* Port2 Index */
1681 SK_MAC_ADDR MacAddr
;
1684 if (FromPortNumber
>= (SK_U32
) pAC
->GIni
.GIMacsFound
) {
1685 return (SK_ADDR_ILLEGAL_PORT
);
1688 if (ToPortNumber
>= (SK_U32
) pAC
->GIni
.GIMacsFound
) {
1689 return (SK_ADDR_ILLEGAL_PORT
);
1692 if (pAC
->Rlmt
.Port
[FromPortNumber
].Net
!= pAC
->Rlmt
.Port
[ToPortNumber
].Net
) {
1693 return (SK_ADDR_ILLEGAL_PORT
);
1698 * - Exact Match Entries (GEnesis and Yukon)
1699 * Yukon uses first entry for the logical MAC
1700 * address (stored in the second GMAC register).
1701 * - FirstExactMatchRlmt (GEnesis only)
1702 * - NextExactMatchRlmt (GEnesis only)
1703 * - FirstExactMatchDrv (GEnesis only)
1704 * - NextExactMatchDrv (GEnesis only)
1705 * - 64-bit filter (InexactFilter)
1706 * - Promiscuous Mode
1710 for (i
= 0; i
< SK_ADDR_EXACT_MATCHES
; i
++) {
1711 MacAddr
= pAC
->Addr
.Port
[FromPortNumber
].Exact
[i
];
1712 pAC
->Addr
.Port
[FromPortNumber
].Exact
[i
] =
1713 pAC
->Addr
.Port
[ToPortNumber
].Exact
[i
];
1714 pAC
->Addr
.Port
[ToPortNumber
].Exact
[i
] = MacAddr
;
1717 for (i
= 0; i
< 8; i
++) {
1718 Byte
= pAC
->Addr
.Port
[FromPortNumber
].InexactFilter
.Bytes
[i
];
1719 pAC
->Addr
.Port
[FromPortNumber
].InexactFilter
.Bytes
[i
] =
1720 pAC
->Addr
.Port
[ToPortNumber
].InexactFilter
.Bytes
[i
];
1721 pAC
->Addr
.Port
[ToPortNumber
].InexactFilter
.Bytes
[i
] = Byte
;
1724 i
= pAC
->Addr
.Port
[FromPortNumber
].PromMode
;
1725 pAC
->Addr
.Port
[FromPortNumber
].PromMode
= pAC
->Addr
.Port
[ToPortNumber
].PromMode
;
1726 pAC
->Addr
.Port
[ToPortNumber
].PromMode
= i
;
1728 if (pAC
->GIni
.GIGenesis
) {
1729 DWord
= pAC
->Addr
.Port
[FromPortNumber
].FirstExactMatchRlmt
;
1730 pAC
->Addr
.Port
[FromPortNumber
].FirstExactMatchRlmt
=
1731 pAC
->Addr
.Port
[ToPortNumber
].FirstExactMatchRlmt
;
1732 pAC
->Addr
.Port
[ToPortNumber
].FirstExactMatchRlmt
= DWord
;
1734 DWord
= pAC
->Addr
.Port
[FromPortNumber
].NextExactMatchRlmt
;
1735 pAC
->Addr
.Port
[FromPortNumber
].NextExactMatchRlmt
=
1736 pAC
->Addr
.Port
[ToPortNumber
].NextExactMatchRlmt
;
1737 pAC
->Addr
.Port
[ToPortNumber
].NextExactMatchRlmt
= DWord
;
1739 DWord
= pAC
->Addr
.Port
[FromPortNumber
].FirstExactMatchDrv
;
1740 pAC
->Addr
.Port
[FromPortNumber
].FirstExactMatchDrv
=
1741 pAC
->Addr
.Port
[ToPortNumber
].FirstExactMatchDrv
;
1742 pAC
->Addr
.Port
[ToPortNumber
].FirstExactMatchDrv
= DWord
;
1744 DWord
= pAC
->Addr
.Port
[FromPortNumber
].NextExactMatchDrv
;
1745 pAC
->Addr
.Port
[FromPortNumber
].NextExactMatchDrv
=
1746 pAC
->Addr
.Port
[ToPortNumber
].NextExactMatchDrv
;
1747 pAC
->Addr
.Port
[ToPortNumber
].NextExactMatchDrv
= DWord
;
1750 /* CAUTION: Solution works if only ports of one adapter are in use. */
1751 for (i
= 0; (SK_U32
) i
< pAC
->Rlmt
.Net
[pAC
->Rlmt
.Port
[ToPortNumber
].
1752 Net
->NetNumber
].NumPorts
; i
++) {
1753 if (pAC
->Rlmt
.Net
[pAC
->Rlmt
.Port
[ToPortNumber
].Net
->NetNumber
].
1754 Port
[i
]->PortNumber
== ToPortNumber
) {
1755 pAC
->Addr
.Net
[pAC
->Rlmt
.Port
[ToPortNumber
].Net
->NetNumber
].
1757 /* 20001207 RA: Was "ToPortNumber;". */
1761 (void) SkAddrMcUpdate(pAC
, IoC
, FromPortNumber
);
1762 (void) SkAddrMcUpdate(pAC
, IoC
, ToPortNumber
);
1764 return (SK_ADDR_SUCCESS
);
1768 #endif /* !SK_SLIM */
1772 #endif /* __cplusplus */