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 static int SkAddrGmacMcAdd(SK_AC
*pAC
, SK_IOC IoC
, SK_U32 PortNumber
,
91 SK_MAC_ADDR
*pMc
, int Flags
);
92 static int SkAddrGmacMcClear(SK_AC
*pAC
, SK_IOC IoC
, SK_U32 PortNumber
,
94 static int SkAddrGmacMcUpdate(SK_AC
*pAC
, SK_IOC IoC
, SK_U32 PortNumber
);
95 static int SkAddrGmacPromiscuousChange(SK_AC
*pAC
, SK_IOC IoC
,
96 SK_U32 PortNumber
, int NewPromMode
);
97 static int SkAddrXmacMcAdd(SK_AC
*pAC
, SK_IOC IoC
, SK_U32 PortNumber
,
98 SK_MAC_ADDR
*pMc
, int Flags
);
99 static int SkAddrXmacMcClear(SK_AC
*pAC
, SK_IOC IoC
, SK_U32 PortNumber
,
101 static int SkAddrXmacMcUpdate(SK_AC
*pAC
, SK_IOC IoC
, SK_U32 PortNumber
);
102 static int SkAddrXmacPromiscuousChange(SK_AC
*pAC
, SK_IOC IoC
,
103 SK_U32 PortNumber
, int NewPromMode
);
105 /* functions ******************************************************************/
107 /******************************************************************************
109 * SkAddrInit - initialize data, set state to init
116 * This routine clears the multicast tables and resets promiscuous mode.
117 * Some entries are reserved for the "logical MAC address", the
118 * SK-RLMT multicast address, and the BPDU multicast address.
124 * All permanent MAC addresses are read from EPROM.
125 * If the current MAC addresses are not already set in software,
126 * they are set to the values of the permanent addresses.
127 * The current addresses are written to the corresponding MAC.
142 SK_AC
*pAC
, /* the adapter context */
143 SK_IOC IoC
, /* I/O context */
144 int Level
) /* initialization level */
150 SK_ADDR_PORT
*pAPort
;
154 SK_MEMSET((char *) &pAC
->Addr
, (SK_U8
) 0,
155 (SK_U16
) sizeof(SK_ADDR
));
157 for (i
= 0; i
< SK_MAX_MACS
; i
++) {
158 pAPort
= &pAC
->Addr
.Port
[i
];
159 pAPort
->PromMode
= SK_PROM_MODE_NONE
;
161 pAPort
->FirstExactMatchRlmt
= SK_ADDR_FIRST_MATCH_RLMT
;
162 pAPort
->FirstExactMatchDrv
= SK_ADDR_FIRST_MATCH_DRV
;
163 pAPort
->NextExactMatchRlmt
= SK_ADDR_FIRST_MATCH_RLMT
;
164 pAPort
->NextExactMatchDrv
= SK_ADDR_FIRST_MATCH_DRV
;
167 for (i
= 0; i
< SK_MAX_MACS
; i
++) {
168 if (pAC
->Addr
.Port
[i
].NextExactMatchRlmt
<
169 SK_ADDR_FIRST_MATCH_RLMT
) {
174 /* pAC->Addr.InitDone = SK_INIT_DATA; */
179 for (i
= 0; i
< SK_MAX_NETS
; i
++) {
180 pAC
->Addr
.Net
[i
].ActivePort
= pAC
->Rlmt
.Net
[i
].ActivePort
;
182 #endif /* !SK_NO_RLMT */
184 for (i
= 0; i
< SK_MAX_MACS
; i
++) {
185 if (pAC
->Addr
.Port
[i
].NextExactMatchRlmt
<
186 SK_ADDR_FIRST_MATCH_RLMT
) {
192 /* Read permanent logical MAC address from Control Register File. */
193 for (j
= 0; j
< SK_MAC_ADDR_LEN
; j
++) {
194 InAddr
= (SK_U8
*) &pAC
->Addr
.Net
[0].PermanentMacAddress
.a
[j
];
195 SK_IN8(IoC
, B2_MAC_1
+ j
, InAddr
);
198 if (!pAC
->Addr
.Net
[0].CurrentMacAddressSet
) {
199 /* Set the current logical MAC address to the permanent one. */
200 pAC
->Addr
.Net
[0].CurrentMacAddress
=
201 pAC
->Addr
.Net
[0].PermanentMacAddress
;
202 pAC
->Addr
.Net
[0].CurrentMacAddressSet
= SK_TRUE
;
205 /* Set the current logical MAC address. */
206 pAC
->Addr
.Port
[pAC
->Addr
.Net
[0].ActivePort
].Exact
[0] =
207 pAC
->Addr
.Net
[0].CurrentMacAddress
;
209 /* Set logical MAC address for net 2 to (log | 3). */
210 if (!pAC
->Addr
.Net
[1].CurrentMacAddressSet
) {
211 pAC
->Addr
.Net
[1].PermanentMacAddress
=
212 pAC
->Addr
.Net
[0].PermanentMacAddress
;
213 pAC
->Addr
.Net
[1].PermanentMacAddress
.a
[5] |= 3;
214 /* Set the current logical MAC address to the permanent one. */
215 pAC
->Addr
.Net
[1].CurrentMacAddress
=
216 pAC
->Addr
.Net
[1].PermanentMacAddress
;
217 pAC
->Addr
.Net
[1].CurrentMacAddressSet
= SK_TRUE
;
219 #endif /* SK_MAX_NETS > 1 */
222 for (i
= 0; i
< (SK_U32
) pAC
->GIni
.GIMacsFound
; i
++) {
223 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_INIT
,
224 ("Permanent MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
226 pAC
->Addr
.Net
[i
].PermanentMacAddress
.a
[0],
227 pAC
->Addr
.Net
[i
].PermanentMacAddress
.a
[1],
228 pAC
->Addr
.Net
[i
].PermanentMacAddress
.a
[2],
229 pAC
->Addr
.Net
[i
].PermanentMacAddress
.a
[3],
230 pAC
->Addr
.Net
[i
].PermanentMacAddress
.a
[4],
231 pAC
->Addr
.Net
[i
].PermanentMacAddress
.a
[5]))
233 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_INIT
,
234 ("Logical MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
236 pAC
->Addr
.Net
[i
].CurrentMacAddress
.a
[0],
237 pAC
->Addr
.Net
[i
].CurrentMacAddress
.a
[1],
238 pAC
->Addr
.Net
[i
].CurrentMacAddress
.a
[2],
239 pAC
->Addr
.Net
[i
].CurrentMacAddress
.a
[3],
240 pAC
->Addr
.Net
[i
].CurrentMacAddress
.a
[4],
241 pAC
->Addr
.Net
[i
].CurrentMacAddress
.a
[5]))
245 for (i
= 0; i
< (SK_U32
) pAC
->GIni
.GIMacsFound
; i
++) {
246 pAPort
= &pAC
->Addr
.Port
[i
];
248 /* Read permanent port addresses from Control Register File. */
249 for (j
= 0; j
< SK_MAC_ADDR_LEN
; j
++) {
250 InAddr
= (SK_U8
*) &pAPort
->PermanentMacAddress
.a
[j
];
251 SK_IN8(IoC
, B2_MAC_2
+ 8 * i
+ j
, InAddr
);
254 if (!pAPort
->CurrentMacAddressSet
) {
256 * Set the current and previous physical MAC address
257 * of this port to its permanent MAC address.
259 pAPort
->CurrentMacAddress
= pAPort
->PermanentMacAddress
;
260 pAPort
->PreviousMacAddress
= pAPort
->PermanentMacAddress
;
261 pAPort
->CurrentMacAddressSet
= SK_TRUE
;
264 /* Set port's current physical MAC address. */
265 OutAddr
= (SK_U16
*) &pAPort
->CurrentMacAddress
.a
[0];
267 if (pAC
->GIni
.GIGenesis
) {
268 XM_OUTADDR(IoC
, i
, XM_SA
, OutAddr
);
272 if (!pAC
->GIni
.GIGenesis
) {
273 GM_OUTADDR(IoC
, i
, GM_SRC_ADDR_1L
, OutAddr
);
277 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_INIT
,
278 ("SkAddrInit: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
279 pAPort
->PermanentMacAddress
.a
[0],
280 pAPort
->PermanentMacAddress
.a
[1],
281 pAPort
->PermanentMacAddress
.a
[2],
282 pAPort
->PermanentMacAddress
.a
[3],
283 pAPort
->PermanentMacAddress
.a
[4],
284 pAPort
->PermanentMacAddress
.a
[5]))
286 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_INIT
,
287 ("SkAddrInit: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
288 pAPort
->CurrentMacAddress
.a
[0],
289 pAPort
->CurrentMacAddress
.a
[1],
290 pAPort
->CurrentMacAddress
.a
[2],
291 pAPort
->CurrentMacAddress
.a
[3],
292 pAPort
->CurrentMacAddress
.a
[4],
293 pAPort
->CurrentMacAddress
.a
[5]))
296 /* pAC->Addr.InitDone = SK_INIT_IO; */
301 for (i
= 0; i
< SK_MAX_MACS
; i
++) {
302 if (pAC
->Addr
.Port
[i
].NextExactMatchRlmt
<
303 SK_ADDR_FIRST_MATCH_RLMT
) {
309 /* pAC->Addr.InitDone = SK_INIT_RUN; */
316 return (SK_ADDR_SUCCESS
);
322 /******************************************************************************
324 * SkAddrMcClear - clear the multicast table
327 * This routine clears the multicast table.
329 * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
332 * It calls either SkAddrXmacMcClear or SkAddrGmacMcClear, according
333 * to the adapter in use. The real work is done there.
337 * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
338 * may be called after SK_INIT_IO without limitation
342 * SK_ADDR_ILLEGAL_PORT
345 SK_AC
*pAC
, /* adapter context */
346 SK_IOC IoC
, /* I/O context */
347 SK_U32 PortNumber
, /* Index of affected port */
348 int Flags
) /* permanent/non-perm, sw-only */
352 if (PortNumber
>= (SK_U32
) pAC
->GIni
.GIMacsFound
) {
353 return (SK_ADDR_ILLEGAL_PORT
);
356 if (pAC
->GIni
.GIGenesis
) {
357 ReturnCode
= SkAddrXmacMcClear(pAC
, IoC
, PortNumber
, Flags
);
360 ReturnCode
= SkAddrGmacMcClear(pAC
, IoC
, PortNumber
, Flags
);
365 } /* SkAddrMcClear */
367 #endif /* !SK_SLIM */
371 /******************************************************************************
373 * SkAddrXmacMcClear - clear the multicast table
376 * This routine clears the multicast table
377 * (either entry 2 or entries 3-16 and InexactFilter) of the given port.
378 * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
383 * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
384 * may be called after SK_INIT_IO without limitation
388 * SK_ADDR_ILLEGAL_PORT
390 static int SkAddrXmacMcClear(
391 SK_AC
*pAC
, /* adapter context */
392 SK_IOC IoC
, /* I/O context */
393 SK_U32 PortNumber
, /* Index of affected port */
394 int Flags
) /* permanent/non-perm, sw-only */
398 if (Flags
& SK_ADDR_PERMANENT
) { /* permanent => RLMT */
400 /* Clear RLMT multicast addresses. */
401 pAC
->Addr
.Port
[PortNumber
].NextExactMatchRlmt
= SK_ADDR_FIRST_MATCH_RLMT
;
403 else { /* not permanent => DRV */
405 /* Clear InexactFilter */
406 for (i
= 0; i
< 8; i
++) {
407 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] = 0;
410 /* Clear DRV multicast addresses. */
412 pAC
->Addr
.Port
[PortNumber
].NextExactMatchDrv
= SK_ADDR_FIRST_MATCH_DRV
;
415 if (!(Flags
& SK_MC_SW_ONLY
)) {
416 (void) SkAddrXmacMcUpdate(pAC
, IoC
, PortNumber
);
419 return (SK_ADDR_SUCCESS
);
421 } /* SkAddrXmacMcClear */
423 #endif /* !SK_SLIM */
427 /******************************************************************************
429 * SkAddrGmacMcClear - clear the multicast table
432 * This routine clears the multicast hashing table (InexactFilter)
433 * (either the RLMT or the driver bits) of the given port.
435 * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
440 * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
441 * may be called after SK_INIT_IO without limitation
445 * SK_ADDR_ILLEGAL_PORT
447 static int SkAddrGmacMcClear(
448 SK_AC
*pAC
, /* adapter context */
449 SK_IOC IoC
, /* I/O context */
450 SK_U32 PortNumber
, /* Index of affected port */
451 int Flags
) /* permanent/non-perm, sw-only */
456 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
457 ("GMAC InexactFilter (not cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
458 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[0],
459 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[1],
460 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[2],
461 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[3],
462 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[4],
463 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[5],
464 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[6],
465 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[7]))
468 /* Clear InexactFilter */
469 for (i
= 0; i
< 8; i
++) {
470 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] = 0;
473 if (Flags
& SK_ADDR_PERMANENT
) { /* permanent => RLMT */
475 /* Copy DRV bits to InexactFilter. */
476 for (i
= 0; i
< 8; i
++) {
477 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] |=
478 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[i
];
480 /* Clear InexactRlmtFilter. */
481 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[i
] = 0;
485 else { /* not permanent => DRV */
487 /* Copy RLMT bits to InexactFilter. */
488 for (i
= 0; i
< 8; i
++) {
489 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] |=
490 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[i
];
492 /* Clear InexactDrvFilter. */
493 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[i
] = 0;
498 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
499 ("GMAC InexactFilter (cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
500 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[0],
501 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[1],
502 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[2],
503 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[3],
504 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[4],
505 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[5],
506 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[6],
507 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[7]))
510 if (!(Flags
& SK_MC_SW_ONLY
)) {
511 (void) SkAddrGmacMcUpdate(pAC
, IoC
, PortNumber
);
514 return (SK_ADDR_SUCCESS
);
516 } /* SkAddrGmacMcClear */
518 #ifndef SK_ADDR_CHEAT
520 /******************************************************************************
522 * SkXmacMcHash - hash multicast address
525 * This routine computes the hash value for a multicast address.
526 * A CRC32 algorithm is used.
529 * The code was adapted from the XaQti data sheet.
535 * Hash value of multicast address.
537 static SK_U32
SkXmacMcHash(
538 unsigned char *pMc
) /* Multicast address */
546 for (Idx
= 0; Idx
< SK_MAC_ADDR_LEN
; Idx
++) {
548 for (Bit
= 0; Bit
< 8; Bit
++, Data
>>= 1) {
549 Crc
= (Crc
>> 1) ^ (((Crc
^ Data
) & 1) ? XMAC_POLY
: 0);
553 return (Crc
& ((1 << HASH_BITS
) - 1));
558 /******************************************************************************
560 * SkGmacMcHash - hash multicast address
563 * This routine computes the hash value for a multicast address.
564 * A CRC16 algorithm is used.
573 * Hash value of multicast address.
575 static SK_U32
SkGmacMcHash(
576 unsigned char *pMc
) /* Multicast address */
585 for (Byte
= 0; Byte
< 6; Byte
++) {
587 Data
= (SK_U32
) pMc
[Byte
];
589 /* Change bit order in byte. */
591 for (Bit
= 0; Bit
< 8; Bit
++) {
593 Data
|= 1L << (7 - Bit
);
596 Data
&= ~(1L << (7 - Bit
));
602 for (Bit
= 0; Bit
< 8; Bit
++) {
603 if (Crc
& 0x80000000) {
604 Crc
= (Crc
<< 1) ^ GMAC_POLY
;
612 return (Crc
& ((1 << HASH_BITS
) - 1));
616 #endif /* !SK_ADDR_CHEAT */
618 /******************************************************************************
620 * SkAddrMcAdd - add a multicast address to a port
623 * This routine enables reception for a given address on the given port.
625 * It calls either SkAddrXmacMcAdd or SkAddrGmacMcAdd, according to the
626 * adapter in use. The real work is done there.
629 * The return code is only valid for SK_PROM_MODE_NONE.
633 * may be called after SK_INIT_DATA
636 * SK_MC_FILTERING_EXACT
637 * SK_MC_FILTERING_INEXACT
638 * SK_MC_ILLEGAL_ADDRESS
640 * SK_MC_RLMT_OVERFLOW
643 SK_AC
*pAC
, /* adapter context */
644 SK_IOC IoC
, /* I/O context */
645 SK_U32 PortNumber
, /* Port Number */
646 SK_MAC_ADDR
*pMc
, /* multicast address to be added */
647 int Flags
) /* permanent/non-permanent */
651 if (PortNumber
>= (SK_U32
) pAC
->GIni
.GIMacsFound
) {
652 return (SK_ADDR_ILLEGAL_PORT
);
655 if (pAC
->GIni
.GIGenesis
) {
656 ReturnCode
= SkAddrXmacMcAdd(pAC
, IoC
, PortNumber
, pMc
, Flags
);
659 ReturnCode
= SkAddrGmacMcAdd(pAC
, IoC
, PortNumber
, pMc
, Flags
);
667 /******************************************************************************
669 * SkAddrXmacMcAdd - add a multicast address to a port
672 * This routine enables reception for a given address on the given port.
675 * The return code is only valid for SK_PROM_MODE_NONE.
677 * The multicast bit is only checked if there are no free exact match
682 * may be called after SK_INIT_DATA
685 * SK_MC_FILTERING_EXACT
686 * SK_MC_FILTERING_INEXACT
687 * SK_MC_ILLEGAL_ADDRESS
688 * SK_MC_RLMT_OVERFLOW
690 static int SkAddrXmacMcAdd(
691 SK_AC
*pAC
, /* adapter context */
692 SK_IOC IoC
, /* I/O context */
693 SK_U32 PortNumber
, /* Port Number */
694 SK_MAC_ADDR
*pMc
, /* multicast address to be added */
695 int Flags
) /* permanent/non-permanent */
699 #ifndef SK_ADDR_CHEAT
701 #endif /* !defined(SK_ADDR_CHEAT) */
703 if (Flags
& SK_ADDR_PERMANENT
) { /* permanent => RLMT */
705 if (pAC
->Addr
.Port
[PortNumber
].NextExactMatchRlmt
<
706 SK_ADDR_FIRST_MATCH_RLMT
) {
707 Next0
[PortNumber
] |= 1;
708 return (SK_MC_RLMT_OVERFLOW
);
712 if (pAC
->Addr
.Port
[PortNumber
].NextExactMatchRlmt
>
713 SK_ADDR_LAST_MATCH_RLMT
) {
714 return (SK_MC_RLMT_OVERFLOW
);
717 /* Set a RLMT multicast address. */
719 pAC
->Addr
.Port
[PortNumber
].Exact
[
720 pAC
->Addr
.Port
[PortNumber
].NextExactMatchRlmt
++] = *pMc
;
722 return (SK_MC_FILTERING_EXACT
);
726 if (pAC
->Addr
.Port
[PortNumber
].NextExactMatchDrv
<
727 SK_ADDR_FIRST_MATCH_DRV
) {
728 Next0
[PortNumber
] |= 2;
729 return (SK_MC_RLMT_OVERFLOW
);
733 if (pAC
->Addr
.Port
[PortNumber
].NextExactMatchDrv
<= SK_ADDR_LAST_MATCH_DRV
) {
735 /* Set exact match entry. */
736 pAC
->Addr
.Port
[PortNumber
].Exact
[
737 pAC
->Addr
.Port
[PortNumber
].NextExactMatchDrv
++] = *pMc
;
739 /* Clear InexactFilter */
740 for (i
= 0; i
< 8; i
++) {
741 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] = 0;
745 if (!(pMc
->a
[0] & SK_MC_BIT
)) {
746 /* Hashing only possible with multicast addresses */
747 return (SK_MC_ILLEGAL_ADDRESS
);
749 #ifndef SK_ADDR_CHEAT
750 /* Compute hash value of address. */
751 HashBit
= 63 - SkXmacMcHash(&pMc
->a
[0]);
753 /* Add bit to InexactFilter. */
754 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[HashBit
/ 8] |=
756 #else /* SK_ADDR_CHEAT */
757 /* Set all bits in InexactFilter. */
758 for (i
= 0; i
< 8; i
++) {
759 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] = 0xFF;
761 #endif /* SK_ADDR_CHEAT */
764 for (Inexact
= 0, i
= 0; i
< 8; i
++) {
765 Inexact
|= pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
];
768 if (Inexact
== 0 && pAC
->Addr
.Port
[PortNumber
].PromMode
== 0) {
769 return (SK_MC_FILTERING_EXACT
);
772 return (SK_MC_FILTERING_INEXACT
);
775 } /* SkAddrXmacMcAdd */
778 /******************************************************************************
780 * SkAddrGmacMcAdd - add a multicast address to a port
783 * This routine enables reception for a given address on the given port.
786 * The return code is only valid for SK_PROM_MODE_NONE.
790 * may be called after SK_INIT_DATA
793 * SK_MC_FILTERING_INEXACT
794 * SK_MC_ILLEGAL_ADDRESS
796 static int SkAddrGmacMcAdd(
797 SK_AC
*pAC
, /* adapter context */
798 SK_IOC IoC
, /* I/O context */
799 SK_U32 PortNumber
, /* Port Number */
800 SK_MAC_ADDR
*pMc
, /* multicast address to be added */
801 int Flags
) /* permanent/non-permanent */
804 #ifndef SK_ADDR_CHEAT
806 #endif /* !defined(SK_ADDR_CHEAT) */
808 if (!(pMc
->a
[0] & SK_MC_BIT
)) {
809 /* Hashing only possible with multicast addresses */
810 return (SK_MC_ILLEGAL_ADDRESS
);
813 #ifndef SK_ADDR_CHEAT
815 /* Compute hash value of address. */
816 HashBit
= SkGmacMcHash(&pMc
->a
[0]);
818 if (Flags
& SK_ADDR_PERMANENT
) { /* permanent => RLMT */
820 /* Add bit to InexactRlmtFilter. */
821 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[HashBit
/ 8] |=
824 /* Copy bit to InexactFilter. */
825 for (i
= 0; i
< 8; i
++) {
826 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] |=
827 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[i
];
830 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
831 ("GMAC InexactRlmtFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
832 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[0],
833 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[1],
834 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[2],
835 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[3],
836 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[4],
837 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[5],
838 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[6],
839 pAC
->Addr
.Port
[PortNumber
].InexactRlmtFilter
.Bytes
[7]))
842 else { /* not permanent => DRV */
844 /* Add bit to InexactDrvFilter. */
845 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[HashBit
/ 8] |=
848 /* Copy bit to InexactFilter. */
849 for (i
= 0; i
< 8; i
++) {
850 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] |=
851 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[i
];
854 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
855 ("GMAC InexactDrvFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
856 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[0],
857 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[1],
858 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[2],
859 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[3],
860 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[4],
861 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[5],
862 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[6],
863 pAC
->Addr
.Port
[PortNumber
].InexactDrvFilter
.Bytes
[7]))
867 #else /* SK_ADDR_CHEAT */
869 /* Set all bits in InexactFilter. */
870 for (i
= 0; i
< 8; i
++) {
871 pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
] = 0xFF;
873 #endif /* SK_ADDR_CHEAT */
875 return (SK_MC_FILTERING_INEXACT
);
877 } /* SkAddrGmacMcAdd */
879 #endif /* !SK_SLIM */
881 /******************************************************************************
883 * SkAddrMcUpdate - update the HW MC address table and set the MAC address
886 * This routine enables reception of the addresses contained in a local
887 * table for a given port.
888 * It also programs the port's current physical MAC address.
890 * It calls either SkAddrXmacMcUpdate or SkAddrGmacMcUpdate, according
891 * to the adapter in use. The real work is done there.
894 * The return code is only valid for SK_PROM_MODE_NONE.
898 * may be called after SK_INIT_IO
901 * SK_MC_FILTERING_EXACT
902 * SK_MC_FILTERING_INEXACT
903 * SK_ADDR_ILLEGAL_PORT
906 SK_AC
*pAC
, /* adapter context */
907 SK_IOC IoC
, /* I/O context */
908 SK_U32 PortNumber
) /* Port Number */
911 #if (!defined(SK_SLIM) || defined(DEBUG))
912 if (PortNumber
>= (SK_U32
) pAC
->GIni
.GIMacsFound
) {
913 return (SK_ADDR_ILLEGAL_PORT
);
915 #endif /* !SK_SLIM || DEBUG */
918 if (pAC
->GIni
.GIGenesis
) {
919 ReturnCode
= SkAddrXmacMcUpdate(pAC
, IoC
, PortNumber
);
923 if (!pAC
->GIni
.GIGenesis
) {
924 ReturnCode
= SkAddrGmacMcUpdate(pAC
, IoC
, PortNumber
);
929 } /* SkAddrMcUpdate */
934 /******************************************************************************
936 * SkAddrXmacMcUpdate - update the HW MC address table and set the MAC address
939 * This routine enables reception of the addresses contained in a local
940 * table for a given port.
941 * It also programs the port's current physical MAC address.
944 * The return code is only valid for SK_PROM_MODE_NONE.
948 * may be called after SK_INIT_IO
951 * SK_MC_FILTERING_EXACT
952 * SK_MC_FILTERING_INEXACT
953 * SK_ADDR_ILLEGAL_PORT
955 static int SkAddrXmacMcUpdate(
956 SK_AC
*pAC
, /* adapter context */
957 SK_IOC IoC
, /* I/O context */
958 SK_U32 PortNumber
) /* Port Number */
963 SK_ADDR_PORT
*pAPort
;
965 SK_DBG_MSG(pAC
,SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
966 ("SkAddrXmacMcUpdate on Port %u.\n", PortNumber
))
968 pAPort
= &pAC
->Addr
.Port
[PortNumber
];
971 SK_DBG_MSG(pAC
,SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
972 ("Next0 on Port %d: %d\n", PortNumber
, Next0
[PortNumber
]))
975 /* Start with 0 to also program the logical MAC address. */
976 for (i
= 0; i
< pAPort
->NextExactMatchRlmt
; i
++) {
977 /* Set exact match address i on XMAC */
978 OutAddr
= (SK_U16
*) &pAPort
->Exact
[i
].a
[0];
979 XM_OUTADDR(IoC
, PortNumber
, XM_EXM(i
), OutAddr
);
982 /* Clear other permanent exact match addresses on XMAC */
983 if (pAPort
->NextExactMatchRlmt
<= SK_ADDR_LAST_MATCH_RLMT
) {
985 SkXmClrExactAddr(pAC
, IoC
, PortNumber
, pAPort
->NextExactMatchRlmt
,
986 SK_ADDR_LAST_MATCH_RLMT
);
989 for (i
= pAPort
->FirstExactMatchDrv
; i
< pAPort
->NextExactMatchDrv
; i
++) {
990 OutAddr
= (SK_U16
*) &pAPort
->Exact
[i
].a
[0];
991 XM_OUTADDR(IoC
, PortNumber
, XM_EXM(i
), OutAddr
);
994 /* Clear other non-permanent exact match addresses on XMAC */
995 if (pAPort
->NextExactMatchDrv
<= SK_ADDR_LAST_MATCH_DRV
) {
997 SkXmClrExactAddr(pAC
, IoC
, PortNumber
, pAPort
->NextExactMatchDrv
,
998 SK_ADDR_LAST_MATCH_DRV
);
1001 for (Inexact
= 0, i
= 0; i
< 8; i
++) {
1002 Inexact
|= pAPort
->InexactFilter
.Bytes
[i
];
1005 if (pAPort
->PromMode
& SK_PROM_MODE_ALL_MC
) {
1007 /* Set all bits in 64-bit hash register. */
1008 XM_OUTHASH(IoC
, PortNumber
, XM_HSM
, &OnesHash
);
1010 /* Enable Hashing */
1011 SkMacHashing(pAC
, IoC
, (int) PortNumber
, SK_TRUE
);
1013 else if (Inexact
!= 0) {
1015 /* Set 64-bit hash register to InexactFilter. */
1016 XM_OUTHASH(IoC
, PortNumber
, XM_HSM
, &pAPort
->InexactFilter
.Bytes
[0]);
1018 /* Enable Hashing */
1019 SkMacHashing(pAC
, IoC
, (int) PortNumber
, SK_TRUE
);
1022 /* Disable Hashing */
1023 SkMacHashing(pAC
, IoC
, (int) PortNumber
, SK_FALSE
);
1026 if (pAPort
->PromMode
!= SK_PROM_MODE_NONE
) {
1027 (void) SkAddrXmacPromiscuousChange(pAC
, IoC
, PortNumber
, pAPort
->PromMode
);
1030 /* Set port's current physical MAC address. */
1031 OutAddr
= (SK_U16
*) &pAPort
->CurrentMacAddress
.a
[0];
1033 XM_OUTADDR(IoC
, PortNumber
, XM_SA
, OutAddr
);
1036 for (i
= 0; i
< pAPort
->NextExactMatchRlmt
; i
++) {
1040 /* Get exact match address i from port PortNumber. */
1041 InAddr
= (SK_U16
*) &InAddr8
[0];
1043 XM_INADDR(IoC
, PortNumber
, XM_EXM(i
), InAddr
);
1045 SK_DBG_MSG(pAC
,SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
1046 ("SkAddrXmacMcUpdate: MC address %d on Port %u: ",
1047 "%02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x\n",
1056 pAPort
->Exact
[i
].a
[0],
1057 pAPort
->Exact
[i
].a
[1],
1058 pAPort
->Exact
[i
].a
[2],
1059 pAPort
->Exact
[i
].a
[3],
1060 pAPort
->Exact
[i
].a
[4],
1061 pAPort
->Exact
[i
].a
[5]))
1065 /* Determine return value. */
1066 if (Inexact
== 0 && pAPort
->PromMode
== 0) {
1067 return (SK_MC_FILTERING_EXACT
);
1070 return (SK_MC_FILTERING_INEXACT
);
1073 } /* SkAddrXmacMcUpdate */
1075 #endif /* GENESIS */
1079 /******************************************************************************
1081 * SkAddrGmacMcUpdate - update the HW MC address table and set the MAC address
1084 * This routine enables reception of the addresses contained in a local
1085 * table for a given port.
1086 * It also programs the port's current physical MAC address.
1089 * The return code is only valid for SK_PROM_MODE_NONE.
1093 * may be called after SK_INIT_IO
1096 * SK_MC_FILTERING_EXACT
1097 * SK_MC_FILTERING_INEXACT
1098 * SK_ADDR_ILLEGAL_PORT
1100 static int SkAddrGmacMcUpdate(
1101 SK_AC
*pAC
, /* adapter context */
1102 SK_IOC IoC
, /* I/O context */
1103 SK_U32 PortNumber
) /* Port Number */
1108 #endif /* not SK_SLIM */
1110 SK_ADDR_PORT
*pAPort
;
1112 SK_DBG_MSG(pAC
,SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
1113 ("SkAddrGmacMcUpdate on Port %u.\n", PortNumber
))
1115 pAPort
= &pAC
->Addr
.Port
[PortNumber
];
1118 SK_DBG_MSG(pAC
,SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
1119 ("Next0 on Port %d: %d\n", PortNumber
, Next0
[PortNumber
]))
1123 for (Inexact
= 0, i
= 0; i
< 8; i
++) {
1124 Inexact
|= pAPort
->InexactFilter
.Bytes
[i
];
1127 /* Set 64-bit hash register to InexactFilter. */
1128 GM_OUTHASH(IoC
, PortNumber
, GM_MC_ADDR_H1
,
1129 &pAPort
->InexactFilter
.Bytes
[0]);
1131 if (pAPort
->PromMode
& SK_PROM_MODE_ALL_MC
) {
1133 /* Set all bits in 64-bit hash register. */
1134 GM_OUTHASH(IoC
, PortNumber
, GM_MC_ADDR_H1
, &OnesHash
);
1136 /* Enable Hashing */
1137 SkMacHashing(pAC
, IoC
, (int) PortNumber
, SK_TRUE
);
1140 /* Enable Hashing. */
1141 SkMacHashing(pAC
, IoC
, (int) PortNumber
, SK_TRUE
);
1144 if (pAPort
->PromMode
!= SK_PROM_MODE_NONE
) {
1145 (void) SkAddrGmacPromiscuousChange(pAC
, IoC
, PortNumber
, pAPort
->PromMode
);
1149 /* Set all bits in 64-bit hash register. */
1150 GM_OUTHASH(IoC
, PortNumber
, GM_MC_ADDR_H1
, &OnesHash
);
1152 /* Enable Hashing */
1153 SkMacHashing(pAC
, IoC
, (int) PortNumber
, SK_TRUE
);
1155 (void) SkAddrGmacPromiscuousChange(pAC
, IoC
, PortNumber
, pAPort
->PromMode
);
1157 #endif /* SK_SLIM */
1159 /* Set port's current physical MAC address. */
1160 OutAddr
= (SK_U16
*) &pAPort
->CurrentMacAddress
.a
[0];
1161 GM_OUTADDR(IoC
, PortNumber
, GM_SRC_ADDR_1L
, OutAddr
);
1163 /* Set port's current logical MAC address. */
1164 OutAddr
= (SK_U16
*) &pAPort
->Exact
[0].a
[0];
1165 GM_OUTADDR(IoC
, PortNumber
, GM_SRC_ADDR_2L
, OutAddr
);
1168 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
1169 ("SkAddrGmacMcUpdate: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
1170 pAPort
->Exact
[0].a
[0],
1171 pAPort
->Exact
[0].a
[1],
1172 pAPort
->Exact
[0].a
[2],
1173 pAPort
->Exact
[0].a
[3],
1174 pAPort
->Exact
[0].a
[4],
1175 pAPort
->Exact
[0].a
[5]))
1177 SK_DBG_MSG(pAC
, SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
1178 ("SkAddrGmacMcUpdate: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
1179 pAPort
->CurrentMacAddress
.a
[0],
1180 pAPort
->CurrentMacAddress
.a
[1],
1181 pAPort
->CurrentMacAddress
.a
[2],
1182 pAPort
->CurrentMacAddress
.a
[3],
1183 pAPort
->CurrentMacAddress
.a
[4],
1184 pAPort
->CurrentMacAddress
.a
[5]))
1188 /* Determine return value. */
1189 if (Inexact
== 0 && pAPort
->PromMode
== 0) {
1190 return (SK_MC_FILTERING_EXACT
);
1193 return (SK_MC_FILTERING_INEXACT
);
1196 return (SK_MC_FILTERING_INEXACT
);
1197 #endif /* SK_SLIM */
1199 } /* SkAddrGmacMcUpdate */
1205 /******************************************************************************
1207 * SkAddrOverride - override a port's MAC address
1210 * This routine overrides the MAC address of one port.
1214 * may be called after SK_INIT_IO
1217 * SK_ADDR_SUCCESS if successful.
1218 * SK_ADDR_DUPLICATE_ADDRESS if duplicate MAC address.
1219 * SK_ADDR_MULTICAST_ADDRESS if multicast or broadcast address.
1220 * SK_ADDR_TOO_EARLY if SK_INIT_IO was not executed before.
1223 SK_AC
*pAC
, /* adapter context */
1224 SK_IOC IoC
, /* I/O context */
1225 SK_U32 PortNumber
, /* Port Number */
1226 SK_MAC_ADDR SK_FAR
*pNewAddr
, /* new MAC address */
1227 int Flags
) /* logical/physical MAC address */
1231 #endif /* !SK_NO_RLMT */
1234 SK_U16 SK_FAR
*OutAddr
;
1237 NetNumber
= pAC
->Rlmt
.Port
[PortNumber
].Net
->NetNumber
;
1240 #endif /* SK_NO_RLMT */
1241 #if (!defined(SK_SLIM) || defined(DEBUG))
1242 if (PortNumber
>= (SK_U32
) pAC
->GIni
.GIMacsFound
) {
1243 return (SK_ADDR_ILLEGAL_PORT
);
1245 #endif /* !SK_SLIM || DEBUG */
1246 if (pNewAddr
!= NULL
&& (pNewAddr
->a
[0] & SK_MC_BIT
) != 0) {
1247 return (SK_ADDR_MULTICAST_ADDRESS
);
1250 if (!pAC
->Addr
.Net
[NetNumber
].CurrentMacAddressSet
) {
1251 return (SK_ADDR_TOO_EARLY
);
1254 if (Flags
& SK_ADDR_SET_LOGICAL
) { /* Activate logical MAC address. */
1255 /* Parameter *pNewAddr is ignored. */
1256 for (i
= 0; i
< (SK_U32
) pAC
->GIni
.GIMacsFound
; i
++) {
1257 if (!pAC
->Addr
.Port
[i
].CurrentMacAddressSet
) {
1258 return (SK_ADDR_TOO_EARLY
);
1262 /* Set PortNumber to number of net's active port. */
1263 PortNumber
= pAC
->Rlmt
.Net
[NetNumber
].
1264 Port
[pAC
->Addr
.Net
[NetNumber
].ActivePort
]->PortNumber
;
1265 #endif /* !SK_NO_RLMT */
1266 pAC
->Addr
.Port
[PortNumber
].Exact
[0] =
1267 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
;
1269 /* Write address to first exact match entry of active port. */
1270 (void) SkAddrMcUpdate(pAC
, IoC
, PortNumber
);
1272 else if (Flags
& SK_ADDR_CLEAR_LOGICAL
) {
1273 /* Deactivate logical MAC address. */
1274 /* Parameter *pNewAddr is ignored. */
1275 for (i
= 0; i
< (SK_U32
) pAC
->GIni
.GIMacsFound
; i
++) {
1276 if (!pAC
->Addr
.Port
[i
].CurrentMacAddressSet
) {
1277 return (SK_ADDR_TOO_EARLY
);
1281 /* Set PortNumber to number of net's active port. */
1282 PortNumber
= pAC
->Rlmt
.Net
[NetNumber
].
1283 Port
[pAC
->Addr
.Net
[NetNumber
].ActivePort
]->PortNumber
;
1284 #endif /* !SK_NO_RLMT */
1285 for (i
= 0; i
< SK_MAC_ADDR_LEN
; i
++ ) {
1286 pAC
->Addr
.Port
[PortNumber
].Exact
[0].a
[i
] = 0;
1289 /* Write address to first exact match entry of active port. */
1290 (void) SkAddrMcUpdate(pAC
, IoC
, PortNumber
);
1292 else if (Flags
& SK_ADDR_PHYSICAL_ADDRESS
) { /* Physical MAC address. */
1293 if (SK_ADDR_EQUAL(pNewAddr
->a
,
1294 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
.a
)) {
1295 return (SK_ADDR_DUPLICATE_ADDRESS
);
1298 for (i
= 0; i
< (SK_U32
) pAC
->GIni
.GIMacsFound
; i
++) {
1299 if (!pAC
->Addr
.Port
[i
].CurrentMacAddressSet
) {
1300 return (SK_ADDR_TOO_EARLY
);
1303 if (SK_ADDR_EQUAL(pNewAddr
->a
,
1304 pAC
->Addr
.Port
[i
].CurrentMacAddress
.a
)) {
1305 if (i
== PortNumber
) {
1306 return (SK_ADDR_SUCCESS
);
1309 return (SK_ADDR_DUPLICATE_ADDRESS
);
1314 pAC
->Addr
.Port
[PortNumber
].PreviousMacAddress
=
1315 pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
;
1316 pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
= *pNewAddr
;
1318 /* Change port's physical MAC address. */
1319 OutAddr
= (SK_U16 SK_FAR
*) pNewAddr
;
1321 if (pAC
->GIni
.GIGenesis
) {
1322 XM_OUTADDR(IoC
, PortNumber
, XM_SA
, OutAddr
);
1324 #endif /* GENESIS */
1326 if (!pAC
->GIni
.GIGenesis
) {
1327 GM_OUTADDR(IoC
, PortNumber
, GM_SRC_ADDR_1L
, OutAddr
);
1332 /* Report address change to RLMT. */
1333 Para
.Para32
[0] = PortNumber
;
1334 Para
.Para32
[0] = -1;
1335 SkEventQueue(pAC
, SKGE_RLMT
, SK_RLMT_PORT_ADDR
, Para
);
1336 #endif /* !SK_NO_RLMT */
1338 else { /* Logical MAC address. */
1339 if (SK_ADDR_EQUAL(pNewAddr
->a
,
1340 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
.a
)) {
1341 return (SK_ADDR_SUCCESS
);
1344 for (i
= 0; i
< (SK_U32
) pAC
->GIni
.GIMacsFound
; i
++) {
1345 if (!pAC
->Addr
.Port
[i
].CurrentMacAddressSet
) {
1346 return (SK_ADDR_TOO_EARLY
);
1349 if (SK_ADDR_EQUAL(pNewAddr
->a
,
1350 pAC
->Addr
.Port
[i
].CurrentMacAddress
.a
)) {
1351 return (SK_ADDR_DUPLICATE_ADDRESS
);
1356 * In case that the physical and the logical MAC addresses are equal
1357 * we must also change the physical MAC address here.
1358 * In this case we have an adapter which initially was programmed with
1359 * two identical MAC addresses.
1361 if (SK_ADDR_EQUAL(pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
.a
,
1362 pAC
->Addr
.Port
[PortNumber
].Exact
[0].a
)) {
1364 pAC
->Addr
.Port
[PortNumber
].PreviousMacAddress
=
1365 pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
;
1366 pAC
->Addr
.Port
[PortNumber
].CurrentMacAddress
= *pNewAddr
;
1369 /* Report address change to RLMT. */
1370 Para
.Para32
[0] = PortNumber
;
1371 Para
.Para32
[0] = -1;
1372 SkEventQueue(pAC
, SKGE_RLMT
, SK_RLMT_PORT_ADDR
, Para
);
1373 #endif /* !SK_NO_RLMT */
1377 /* Set PortNumber to number of net's active port. */
1378 PortNumber
= pAC
->Rlmt
.Net
[NetNumber
].
1379 Port
[pAC
->Addr
.Net
[NetNumber
].ActivePort
]->PortNumber
;
1380 #endif /* !SK_NO_RLMT */
1381 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
= *pNewAddr
;
1382 pAC
->Addr
.Port
[PortNumber
].Exact
[0] = *pNewAddr
;
1384 SK_DBG_MSG(pAC
,SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
1385 ("SkAddrOverride: Permanent MAC Address: %02X %02X %02X %02X %02X %02X\n",
1386 pAC
->Addr
.Net
[NetNumber
].PermanentMacAddress
.a
[0],
1387 pAC
->Addr
.Net
[NetNumber
].PermanentMacAddress
.a
[1],
1388 pAC
->Addr
.Net
[NetNumber
].PermanentMacAddress
.a
[2],
1389 pAC
->Addr
.Net
[NetNumber
].PermanentMacAddress
.a
[3],
1390 pAC
->Addr
.Net
[NetNumber
].PermanentMacAddress
.a
[4],
1391 pAC
->Addr
.Net
[NetNumber
].PermanentMacAddress
.a
[5]))
1393 SK_DBG_MSG(pAC
,SK_DBGMOD_ADDR
, SK_DBGCAT_CTRL
,
1394 ("SkAddrOverride: New logical MAC Address: %02X %02X %02X %02X %02X %02X\n",
1395 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
.a
[0],
1396 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
.a
[1],
1397 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
.a
[2],
1398 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
.a
[3],
1399 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
.a
[4],
1400 pAC
->Addr
.Net
[NetNumber
].CurrentMacAddress
.a
[5]))
1403 /* Write address to first exact match entry of active port. */
1404 (void) SkAddrMcUpdate(pAC
, IoC
, PortNumber
);
1407 return (SK_ADDR_SUCCESS
);
1409 } /* SkAddrOverride */
1412 #endif /* SK_NO_MAO */
1414 /******************************************************************************
1416 * SkAddrPromiscuousChange - set promiscuous mode for given port
1419 * This routine manages promiscuous mode:
1424 * It calls either SkAddrXmacPromiscuousChange or
1425 * SkAddrGmacPromiscuousChange, according to the adapter in use.
1426 * The real work is done there.
1430 * may be called after SK_INIT_IO
1434 * SK_ADDR_ILLEGAL_PORT
1436 int SkAddrPromiscuousChange(
1437 SK_AC
*pAC
, /* adapter context */
1438 SK_IOC IoC
, /* I/O context */
1439 SK_U32 PortNumber
, /* port whose promiscuous mode changes */
1440 int NewPromMode
) /* new promiscuous mode */
1443 #if (!defined(SK_SLIM) || defined(DEBUG))
1444 if (PortNumber
>= (SK_U32
) pAC
->GIni
.GIMacsFound
) {
1445 return (SK_ADDR_ILLEGAL_PORT
);
1447 #endif /* !SK_SLIM || DEBUG */
1450 if (pAC
->GIni
.GIGenesis
) {
1452 SkAddrXmacPromiscuousChange(pAC
, IoC
, PortNumber
, NewPromMode
);
1454 #endif /* GENESIS */
1456 if (!pAC
->GIni
.GIGenesis
) {
1458 SkAddrGmacPromiscuousChange(pAC
, IoC
, PortNumber
, NewPromMode
);
1462 return (ReturnCode
);
1464 } /* SkAddrPromiscuousChange */
1468 /******************************************************************************
1470 * SkAddrXmacPromiscuousChange - set promiscuous mode for given port
1473 * This routine manages promiscuous mode:
1480 * may be called after SK_INIT_IO
1484 * SK_ADDR_ILLEGAL_PORT
1486 static int SkAddrXmacPromiscuousChange(
1487 SK_AC
*pAC
, /* adapter context */
1488 SK_IOC IoC
, /* I/O context */
1489 SK_U32 PortNumber
, /* port whose promiscuous mode changes */
1490 int NewPromMode
) /* new promiscuous mode */
1493 SK_BOOL InexactModeBit
;
1496 SK_FILTER64 HwInexactFilter
;
1497 SK_U16 LoMode
; /* Lower 16 bits of XMAC Mode Register. */
1498 int CurPromMode
= SK_PROM_MODE_NONE
;
1500 /* Read CurPromMode from Hardware. */
1501 XM_IN16(IoC
, PortNumber
, XM_MODE
, &LoMode
);
1503 if ((LoMode
& XM_MD_ENA_PROM
) != 0) {
1504 /* Promiscuous mode! */
1505 CurPromMode
|= SK_PROM_MODE_LLC
;
1508 for (Inexact
= 0xFF, i
= 0; i
< 8; i
++) {
1509 Inexact
&= pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
];
1511 if (Inexact
== 0xFF) {
1512 CurPromMode
|= (pAC
->Addr
.Port
[PortNumber
].PromMode
& SK_PROM_MODE_ALL_MC
);
1515 /* Get InexactModeBit (bit XM_MD_ENA_HASH in mode register) */
1516 XM_IN16(IoC
, PortNumber
, XM_MODE
, &LoMode
);
1518 InexactModeBit
= (LoMode
& XM_MD_ENA_HASH
) != 0;
1520 /* Read 64-bit hash register from XMAC */
1521 XM_INHASH(IoC
, PortNumber
, XM_HSM
, &HwInexactFilter
.Bytes
[0]);
1523 for (HwInexact
= 0xFF, i
= 0; i
< 8; i
++) {
1524 HwInexact
&= HwInexactFilter
.Bytes
[i
];
1527 if (InexactModeBit
&& (HwInexact
== 0xFF)) {
1528 CurPromMode
|= SK_PROM_MODE_ALL_MC
;
1532 pAC
->Addr
.Port
[PortNumber
].PromMode
= NewPromMode
;
1534 if (NewPromMode
== CurPromMode
) {
1535 return (SK_ADDR_SUCCESS
);
1538 if ((NewPromMode
& SK_PROM_MODE_ALL_MC
) &&
1539 !(CurPromMode
& SK_PROM_MODE_ALL_MC
)) { /* All MC. */
1541 /* Set all bits in 64-bit hash register. */
1542 XM_OUTHASH(IoC
, PortNumber
, XM_HSM
, &OnesHash
);
1544 /* Enable Hashing */
1545 SkMacHashing(pAC
, IoC
, (int) PortNumber
, SK_TRUE
);
1547 else if ((CurPromMode
& SK_PROM_MODE_ALL_MC
) &&
1548 !(NewPromMode
& SK_PROM_MODE_ALL_MC
)) { /* Norm MC. */
1549 for (Inexact
= 0, i
= 0; i
< 8; i
++) {
1550 Inexact
|= pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[i
];
1553 /* Disable Hashing */
1554 SkMacHashing(pAC
, IoC
, (int) PortNumber
, SK_FALSE
);
1557 /* Set 64-bit hash register to InexactFilter. */
1558 XM_OUTHASH(IoC
, PortNumber
, XM_HSM
,
1559 &pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[0]);
1561 /* Enable Hashing */
1562 SkMacHashing(pAC
, IoC
, (int) PortNumber
, SK_TRUE
);
1566 if ((NewPromMode
& SK_PROM_MODE_LLC
) &&
1567 !(CurPromMode
& SK_PROM_MODE_LLC
)) { /* Prom. LLC */
1568 /* Set the MAC in Promiscuous Mode */
1569 SkMacPromiscMode(pAC
, IoC
, (int) PortNumber
, SK_TRUE
);
1571 else if ((CurPromMode
& SK_PROM_MODE_LLC
) &&
1572 !(NewPromMode
& SK_PROM_MODE_LLC
)) { /* Norm. LLC. */
1573 /* Clear Promiscuous Mode */
1574 SkMacPromiscMode(pAC
, IoC
, (int) PortNumber
, SK_FALSE
);
1577 return (SK_ADDR_SUCCESS
);
1579 } /* SkAddrXmacPromiscuousChange */
1581 #endif /* GENESIS */
1585 /******************************************************************************
1587 * SkAddrGmacPromiscuousChange - set promiscuous mode for given port
1590 * This routine manages promiscuous mode:
1597 * may be called after SK_INIT_IO
1601 * SK_ADDR_ILLEGAL_PORT
1603 static int SkAddrGmacPromiscuousChange(
1604 SK_AC
*pAC
, /* adapter context */
1605 SK_IOC IoC
, /* I/O context */
1606 SK_U32 PortNumber
, /* port whose promiscuous mode changes */
1607 int NewPromMode
) /* new promiscuous mode */
1609 SK_U16 ReceiveControl
; /* GMAC Receive Control Register */
1610 int CurPromMode
= SK_PROM_MODE_NONE
;
1612 /* Read CurPromMode from Hardware. */
1613 GM_IN16(IoC
, PortNumber
, GM_RX_CTRL
, &ReceiveControl
);
1615 if ((ReceiveControl
& (GM_RXCR_UCF_ENA
| GM_RXCR_MCF_ENA
)) == 0) {
1616 /* Promiscuous mode! */
1617 CurPromMode
|= SK_PROM_MODE_LLC
;
1620 if ((ReceiveControl
& GM_RXCR_MCF_ENA
) == 0) {
1621 /* All Multicast mode! */
1622 CurPromMode
|= (pAC
->Addr
.Port
[PortNumber
].PromMode
& SK_PROM_MODE_ALL_MC
);
1625 pAC
->Addr
.Port
[PortNumber
].PromMode
= NewPromMode
;
1627 if (NewPromMode
== CurPromMode
) {
1628 return (SK_ADDR_SUCCESS
);
1631 if ((NewPromMode
& SK_PROM_MODE_ALL_MC
) &&
1632 !(CurPromMode
& SK_PROM_MODE_ALL_MC
)) { /* All MC */
1634 /* Set all bits in 64-bit hash register. */
1635 GM_OUTHASH(IoC
, PortNumber
, GM_MC_ADDR_H1
, &OnesHash
);
1637 /* Enable Hashing */
1638 SkMacHashing(pAC
, IoC
, (int) PortNumber
, SK_TRUE
);
1641 if ((CurPromMode
& SK_PROM_MODE_ALL_MC
) &&
1642 !(NewPromMode
& SK_PROM_MODE_ALL_MC
)) { /* Norm. MC */
1644 /* Set 64-bit hash register to InexactFilter. */
1645 GM_OUTHASH(IoC
, PortNumber
, GM_MC_ADDR_H1
,
1646 &pAC
->Addr
.Port
[PortNumber
].InexactFilter
.Bytes
[0]);
1648 /* Enable Hashing. */
1649 SkMacHashing(pAC
, IoC
, (int) PortNumber
, SK_TRUE
);
1652 if ((NewPromMode
& SK_PROM_MODE_LLC
) &&
1653 !(CurPromMode
& SK_PROM_MODE_LLC
)) { /* Prom. LLC */
1655 /* Set the MAC to Promiscuous Mode. */
1656 SkMacPromiscMode(pAC
, IoC
, (int) PortNumber
, SK_TRUE
);
1658 else if ((CurPromMode
& SK_PROM_MODE_LLC
) &&
1659 !(NewPromMode
& SK_PROM_MODE_LLC
)) { /* Norm. LLC */
1661 /* Clear Promiscuous Mode. */
1662 SkMacPromiscMode(pAC
, IoC
, (int) PortNumber
, SK_FALSE
);
1665 return (SK_ADDR_SUCCESS
);
1667 } /* SkAddrGmacPromiscuousChange */
1673 /******************************************************************************
1675 * SkAddrSwap - swap address info
1678 * This routine swaps address info of two ports.
1682 * may be called after SK_INIT_IO
1686 * SK_ADDR_ILLEGAL_PORT
1689 SK_AC
*pAC
, /* adapter context */
1690 SK_IOC IoC
, /* I/O context */
1691 SK_U32 FromPortNumber
, /* Port1 Index */
1692 SK_U32 ToPortNumber
) /* Port2 Index */
1696 SK_MAC_ADDR MacAddr
;
1699 if (FromPortNumber
>= (SK_U32
) pAC
->GIni
.GIMacsFound
) {
1700 return (SK_ADDR_ILLEGAL_PORT
);
1703 if (ToPortNumber
>= (SK_U32
) pAC
->GIni
.GIMacsFound
) {
1704 return (SK_ADDR_ILLEGAL_PORT
);
1707 if (pAC
->Rlmt
.Port
[FromPortNumber
].Net
!= pAC
->Rlmt
.Port
[ToPortNumber
].Net
) {
1708 return (SK_ADDR_ILLEGAL_PORT
);
1713 * - Exact Match Entries (GEnesis and Yukon)
1714 * Yukon uses first entry for the logical MAC
1715 * address (stored in the second GMAC register).
1716 * - FirstExactMatchRlmt (GEnesis only)
1717 * - NextExactMatchRlmt (GEnesis only)
1718 * - FirstExactMatchDrv (GEnesis only)
1719 * - NextExactMatchDrv (GEnesis only)
1720 * - 64-bit filter (InexactFilter)
1721 * - Promiscuous Mode
1725 for (i
= 0; i
< SK_ADDR_EXACT_MATCHES
; i
++) {
1726 MacAddr
= pAC
->Addr
.Port
[FromPortNumber
].Exact
[i
];
1727 pAC
->Addr
.Port
[FromPortNumber
].Exact
[i
] =
1728 pAC
->Addr
.Port
[ToPortNumber
].Exact
[i
];
1729 pAC
->Addr
.Port
[ToPortNumber
].Exact
[i
] = MacAddr
;
1732 for (i
= 0; i
< 8; i
++) {
1733 Byte
= pAC
->Addr
.Port
[FromPortNumber
].InexactFilter
.Bytes
[i
];
1734 pAC
->Addr
.Port
[FromPortNumber
].InexactFilter
.Bytes
[i
] =
1735 pAC
->Addr
.Port
[ToPortNumber
].InexactFilter
.Bytes
[i
];
1736 pAC
->Addr
.Port
[ToPortNumber
].InexactFilter
.Bytes
[i
] = Byte
;
1739 i
= pAC
->Addr
.Port
[FromPortNumber
].PromMode
;
1740 pAC
->Addr
.Port
[FromPortNumber
].PromMode
= pAC
->Addr
.Port
[ToPortNumber
].PromMode
;
1741 pAC
->Addr
.Port
[ToPortNumber
].PromMode
= i
;
1743 if (pAC
->GIni
.GIGenesis
) {
1744 DWord
= pAC
->Addr
.Port
[FromPortNumber
].FirstExactMatchRlmt
;
1745 pAC
->Addr
.Port
[FromPortNumber
].FirstExactMatchRlmt
=
1746 pAC
->Addr
.Port
[ToPortNumber
].FirstExactMatchRlmt
;
1747 pAC
->Addr
.Port
[ToPortNumber
].FirstExactMatchRlmt
= DWord
;
1749 DWord
= pAC
->Addr
.Port
[FromPortNumber
].NextExactMatchRlmt
;
1750 pAC
->Addr
.Port
[FromPortNumber
].NextExactMatchRlmt
=
1751 pAC
->Addr
.Port
[ToPortNumber
].NextExactMatchRlmt
;
1752 pAC
->Addr
.Port
[ToPortNumber
].NextExactMatchRlmt
= DWord
;
1754 DWord
= pAC
->Addr
.Port
[FromPortNumber
].FirstExactMatchDrv
;
1755 pAC
->Addr
.Port
[FromPortNumber
].FirstExactMatchDrv
=
1756 pAC
->Addr
.Port
[ToPortNumber
].FirstExactMatchDrv
;
1757 pAC
->Addr
.Port
[ToPortNumber
].FirstExactMatchDrv
= DWord
;
1759 DWord
= pAC
->Addr
.Port
[FromPortNumber
].NextExactMatchDrv
;
1760 pAC
->Addr
.Port
[FromPortNumber
].NextExactMatchDrv
=
1761 pAC
->Addr
.Port
[ToPortNumber
].NextExactMatchDrv
;
1762 pAC
->Addr
.Port
[ToPortNumber
].NextExactMatchDrv
= DWord
;
1765 /* CAUTION: Solution works if only ports of one adapter are in use. */
1766 for (i
= 0; (SK_U32
) i
< pAC
->Rlmt
.Net
[pAC
->Rlmt
.Port
[ToPortNumber
].
1767 Net
->NetNumber
].NumPorts
; i
++) {
1768 if (pAC
->Rlmt
.Net
[pAC
->Rlmt
.Port
[ToPortNumber
].Net
->NetNumber
].
1769 Port
[i
]->PortNumber
== ToPortNumber
) {
1770 pAC
->Addr
.Net
[pAC
->Rlmt
.Port
[ToPortNumber
].Net
->NetNumber
].
1772 /* 20001207 RA: Was "ToPortNumber;". */
1776 (void) SkAddrMcUpdate(pAC
, IoC
, FromPortNumber
);
1777 (void) SkAddrMcUpdate(pAC
, IoC
, ToPortNumber
);
1779 return (SK_ADDR_SUCCESS
);
1783 #endif /* !SK_SLIM */
1787 #endif /* __cplusplus */