[TG3]: Add tagged status support.
[linux-2.6/verdex.git] / drivers / net / sk98lin / skaddr.c
bloba7e25edc7fc44c973631781dc8e623c8a44ec688
1 /******************************************************************************
3 * Name: skaddr.c
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 /******************************************************************************
27 * Description:
29 * This module is intended to manage multicast addresses, address override,
30 * and promiscuous mode on GEnesis and Yukon adapters.
32 * Address Layout:
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:
40 * "skdrv1st.h"
41 * "skdrv2nd.h"
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 */
50 #define __SKADDR_C
52 #ifdef __cplusplus
53 extern "C" {
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 *******************************************************************/
76 /* None. */
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 ************************************************************/
86 #ifdef DEBUG
87 static int Next0[SK_MAX_MACS] = {0};
88 #endif /* DEBUG */
90 /* functions ******************************************************************/
92 /******************************************************************************
94 * SkAddrInit - initialize data, set state to init
96 * Description:
98 * SK_INIT_DATA
99 * ============
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.
106 * SK_INIT_IO
107 * ==========
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.
115 * SK_INIT_RUN
116 * ===========
118 * Nothing.
120 * Context:
121 * init, pageable
123 * Returns:
124 * SK_ADDR_SUCCESS
126 int SkAddrInit(
127 SK_AC *pAC, /* the adapter context */
128 SK_IOC IoC, /* I/O context */
129 int Level) /* initialization level */
131 int j;
132 SK_U32 i;
133 SK_U8 *InAddr;
134 SK_U16 *OutAddr;
135 SK_ADDR_PORT *pAPort;
137 switch (Level) {
138 case SK_INIT_DATA:
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;
151 #ifdef xDEBUG
152 for (i = 0; i < SK_MAX_MACS; i++) {
153 if (pAC->Addr.Port[i].NextExactMatchRlmt <
154 SK_ADDR_FIRST_MATCH_RLMT) {
155 Next0[i] |= 4;
158 #endif /* DEBUG */
159 /* pAC->Addr.InitDone = SK_INIT_DATA; */
160 break;
162 case SK_INIT_IO:
163 #ifndef SK_NO_RLMT
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 */
168 #ifdef xDEBUG
169 for (i = 0; i < SK_MAX_MACS; i++) {
170 if (pAC->Addr.Port[i].NextExactMatchRlmt <
171 SK_ADDR_FIRST_MATCH_RLMT) {
172 Next0[i] |= 8;
175 #endif /* DEBUG */
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;
193 #if SK_MAX_NETS > 1
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 */
206 #ifdef DEBUG
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]))
228 #endif /* DEBUG */
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];
251 #ifdef GENESIS
252 if (pAC->GIni.GIGenesis) {
253 XM_OUTADDR(IoC, i, XM_SA, OutAddr);
255 #endif /* GENESIS */
256 #ifdef YUKON
257 if (!pAC->GIni.GIGenesis) {
258 GM_OUTADDR(IoC, i, GM_SRC_ADDR_1L, OutAddr);
260 #endif /* YUKON */
261 #ifdef DEBUG
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]))
279 #endif /* DEBUG */
281 /* pAC->Addr.InitDone = SK_INIT_IO; */
282 break;
284 case SK_INIT_RUN:
285 #ifdef xDEBUG
286 for (i = 0; i < SK_MAX_MACS; i++) {
287 if (pAC->Addr.Port[i].NextExactMatchRlmt <
288 SK_ADDR_FIRST_MATCH_RLMT) {
289 Next0[i] |= 16;
292 #endif /* DEBUG */
294 /* pAC->Addr.InitDone = SK_INIT_RUN; */
295 break;
297 default: /* error */
298 break;
301 return (SK_ADDR_SUCCESS);
303 } /* SkAddrInit */
305 #ifndef SK_SLIM
307 /******************************************************************************
309 * SkAddrMcClear - clear the multicast table
311 * Description:
312 * This routine clears the multicast table.
314 * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
315 * immediately.
317 * It calls either SkAddrXmacMcClear or SkAddrGmacMcClear, according
318 * to the adapter in use. The real work is done there.
320 * Context:
321 * runtime, pageable
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
325 * Returns:
326 * SK_ADDR_SUCCESS
327 * SK_ADDR_ILLEGAL_PORT
329 int SkAddrMcClear(
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 */
335 int ReturnCode;
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);
344 else {
345 ReturnCode = SkAddrGmacMcClear(pAC, IoC, PortNumber, Flags);
348 return (ReturnCode);
350 } /* SkAddrMcClear */
352 #endif /* !SK_SLIM */
354 #ifndef SK_SLIM
356 /******************************************************************************
358 * SkAddrXmacMcClear - clear the multicast table
360 * Description:
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
364 * immediately.
366 * Context:
367 * runtime, pageable
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
371 * Returns:
372 * SK_ADDR_SUCCESS
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 */
381 int i;
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 */
410 #ifndef SK_SLIM
412 /******************************************************************************
414 * SkAddrGmacMcClear - clear the multicast table
416 * Description:
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
421 * immediately.
423 * Context:
424 * runtime, pageable
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
428 * Returns:
429 * SK_ADDR_SUCCESS
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 */
438 int i;
440 #ifdef DEBUG
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]))
451 #endif /* DEBUG */
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;
482 #ifdef DEBUG
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]))
493 #endif /* DEBUG */
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
509 * Description:
510 * This routine computes the hash value for a multicast address.
511 * A CRC32 algorithm is used.
513 * Notes:
514 * The code was adapted from the XaQti data sheet.
516 * Context:
517 * runtime, pageable
519 * Returns:
520 * Hash value of multicast address.
522 SK_U32 SkXmacMcHash(
523 unsigned char *pMc) /* Multicast address */
525 SK_U32 Idx;
526 SK_U32 Bit;
527 SK_U32 Data;
528 SK_U32 Crc;
530 Crc = 0xFFFFFFFFUL;
531 for (Idx = 0; Idx < SK_MAC_ADDR_LEN; Idx++) {
532 Data = *pMc++;
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));
540 } /* SkXmacMcHash */
543 /******************************************************************************
545 * SkGmacMcHash - hash multicast address
547 * Description:
548 * This routine computes the hash value for a multicast address.
549 * A CRC16 algorithm is used.
551 * Notes:
554 * Context:
555 * runtime, pageable
557 * Returns:
558 * Hash value of multicast address.
560 SK_U32 SkGmacMcHash(
561 unsigned char *pMc) /* Multicast address */
563 SK_U32 Data;
564 SK_U32 TmpData;
565 SK_U32 Crc;
566 int Byte;
567 int Bit;
569 Crc = 0xFFFFFFFFUL;
570 for (Byte = 0; Byte < 6; Byte++) {
571 /* Get next byte. */
572 Data = (SK_U32) pMc[Byte];
574 /* Change bit order in byte. */
575 TmpData = Data;
576 for (Bit = 0; Bit < 8; Bit++) {
577 if (TmpData & 1L) {
578 Data |= 1L << (7 - Bit);
580 else {
581 Data &= ~(1L << (7 - Bit));
583 TmpData >>= 1;
586 Crc ^= (Data << 24);
587 for (Bit = 0; Bit < 8; Bit++) {
588 if (Crc & 0x80000000) {
589 Crc = (Crc << 1) ^ GMAC_POLY;
591 else {
592 Crc <<= 1;
597 return (Crc & ((1 << HASH_BITS) - 1));
599 } /* SkGmacMcHash */
601 #endif /* !SK_ADDR_CHEAT */
603 /******************************************************************************
605 * SkAddrMcAdd - add a multicast address to a port
607 * Description:
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.
613 * Notes:
614 * The return code is only valid for SK_PROM_MODE_NONE.
616 * Context:
617 * runtime, pageable
618 * may be called after SK_INIT_DATA
620 * Returns:
621 * SK_MC_FILTERING_EXACT
622 * SK_MC_FILTERING_INEXACT
623 * SK_MC_ILLEGAL_ADDRESS
624 * SK_MC_ILLEGAL_PORT
625 * SK_MC_RLMT_OVERFLOW
627 int SkAddrMcAdd(
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 */
634 int ReturnCode;
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);
643 else {
644 ReturnCode = SkAddrGmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
647 return (ReturnCode);
649 } /* SkAddrMcAdd */
652 /******************************************************************************
654 * SkAddrXmacMcAdd - add a multicast address to a port
656 * Description:
657 * This routine enables reception for a given address on the given port.
659 * Notes:
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
663 * entries.
665 * Context:
666 * runtime, pageable
667 * may be called after SK_INIT_DATA
669 * Returns:
670 * SK_MC_FILTERING_EXACT
671 * SK_MC_FILTERING_INEXACT
672 * SK_MC_ILLEGAL_ADDRESS
673 * SK_MC_RLMT_OVERFLOW
675 int SkAddrXmacMcAdd(
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 */
682 int i;
683 SK_U8 Inexact;
684 #ifndef SK_ADDR_CHEAT
685 SK_U32 HashBit;
686 #endif /* !defined(SK_ADDR_CHEAT) */
688 if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
689 #ifdef xDEBUG
690 if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt <
691 SK_ADDR_FIRST_MATCH_RLMT) {
692 Next0[PortNumber] |= 1;
693 return (SK_MC_RLMT_OVERFLOW);
695 #endif /* DEBUG */
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);
710 #ifdef xDEBUG
711 if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <
712 SK_ADDR_FIRST_MATCH_DRV) {
713 Next0[PortNumber] |= 2;
714 return (SK_MC_RLMT_OVERFLOW);
716 #endif /* DEBUG */
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;
729 else {
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] |=
740 1 << (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);
756 else {
757 return (SK_MC_FILTERING_INEXACT);
760 } /* SkAddrXmacMcAdd */
763 /******************************************************************************
765 * SkAddrGmacMcAdd - add a multicast address to a port
767 * Description:
768 * This routine enables reception for a given address on the given port.
770 * Notes:
771 * The return code is only valid for SK_PROM_MODE_NONE.
773 * Context:
774 * runtime, pageable
775 * may be called after SK_INIT_DATA
777 * Returns:
778 * SK_MC_FILTERING_INEXACT
779 * SK_MC_ILLEGAL_ADDRESS
781 int SkAddrGmacMcAdd(
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 */
788 int i;
789 #ifndef SK_ADDR_CHEAT
790 SK_U32 HashBit;
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] |=
807 1 << (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];
814 #ifdef DEBUG
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]))
825 #endif /* DEBUG */
827 else { /* not permanent => DRV */
829 /* Add bit to InexactDrvFilter. */
830 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[HashBit / 8] |=
831 1 << (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];
838 #ifdef DEBUG
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]))
849 #endif /* DEBUG */
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
870 * Description:
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.
878 * Notes:
879 * The return code is only valid for SK_PROM_MODE_NONE.
881 * Context:
882 * runtime, pageable
883 * may be called after SK_INIT_IO
885 * Returns:
886 * SK_MC_FILTERING_EXACT
887 * SK_MC_FILTERING_INEXACT
888 * SK_ADDR_ILLEGAL_PORT
890 int SkAddrMcUpdate(
891 SK_AC *pAC, /* adapter context */
892 SK_IOC IoC, /* I/O context */
893 SK_U32 PortNumber) /* Port Number */
895 int ReturnCode = 0;
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 */
902 #ifdef GENESIS
903 if (pAC->GIni.GIGenesis) {
904 ReturnCode = SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
906 #endif /* GENESIS */
907 #ifdef YUKON
908 if (!pAC->GIni.GIGenesis) {
909 ReturnCode = SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
911 #endif /* YUKON */
912 return (ReturnCode);
914 } /* SkAddrMcUpdate */
917 #ifdef GENESIS
919 /******************************************************************************
921 * SkAddrXmacMcUpdate - update the HW MC address table and set the MAC address
923 * Description:
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.
928 * Notes:
929 * The return code is only valid for SK_PROM_MODE_NONE.
931 * Context:
932 * runtime, pageable
933 * may be called after SK_INIT_IO
935 * Returns:
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 */
945 SK_U32 i;
946 SK_U8 Inexact;
947 SK_U16 *OutAddr;
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];
955 #ifdef DEBUG
956 SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
957 ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
958 #endif /* DEBUG */
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);
995 /* Enable Hashing */
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);
1006 else {
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);
1020 #ifdef xDEBUG
1021 for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
1022 SK_U8 InAddr8[6];
1023 SK_U16 *InAddr;
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",
1034 PortNumber,
1035 InAddr8[0],
1036 InAddr8[1],
1037 InAddr8[2],
1038 InAddr8[3],
1039 InAddr8[4],
1040 InAddr8[5],
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]))
1048 #endif /* DEBUG */
1050 /* Determine return value. */
1051 if (Inexact == 0 && pAPort->PromMode == 0) {
1052 return (SK_MC_FILTERING_EXACT);
1054 else {
1055 return (SK_MC_FILTERING_INEXACT);
1058 } /* SkAddrXmacMcUpdate */
1060 #endif /* GENESIS */
1062 #ifdef YUKON
1064 /******************************************************************************
1066 * SkAddrGmacMcUpdate - update the HW MC address table and set the MAC address
1068 * Description:
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.
1073 * Notes:
1074 * The return code is only valid for SK_PROM_MODE_NONE.
1076 * Context:
1077 * runtime, pageable
1078 * may be called after SK_INIT_IO
1080 * Returns:
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 */
1090 #ifndef SK_SLIM
1091 SK_U32 i;
1092 SK_U8 Inexact;
1093 #endif /* not SK_SLIM */
1094 SK_U16 *OutAddr;
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];
1102 #ifdef DEBUG
1103 SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1104 ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
1105 #endif /* DEBUG */
1107 #ifndef SK_SLIM
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);
1124 else {
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);
1132 #else /* SK_SLIM */
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);
1152 #ifdef DEBUG
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]))
1170 #endif /* DEBUG */
1172 #ifndef SK_SLIM
1173 /* Determine return value. */
1174 if (Inexact == 0 && pAPort->PromMode == 0) {
1175 return (SK_MC_FILTERING_EXACT);
1177 else {
1178 return (SK_MC_FILTERING_INEXACT);
1180 #else /* SK_SLIM */
1181 return (SK_MC_FILTERING_INEXACT);
1182 #endif /* SK_SLIM */
1184 } /* SkAddrGmacMcUpdate */
1186 #endif /* YUKON */
1188 #ifndef SK_NO_MAO
1190 /******************************************************************************
1192 * SkAddrOverride - override a port's MAC address
1194 * Description:
1195 * This routine overrides the MAC address of one port.
1197 * Context:
1198 * runtime, pageable
1199 * may be called after SK_INIT_IO
1201 * Returns:
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.
1207 int SkAddrOverride(
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 */
1214 #ifndef SK_NO_RLMT
1215 SK_EVPARA Para;
1216 #endif /* !SK_NO_RLMT */
1217 SK_U32 NetNumber;
1218 SK_U32 i;
1219 SK_U16 SK_FAR *OutAddr;
1221 #ifndef SK_NO_RLMT
1222 NetNumber = pAC->Rlmt.Port[PortNumber].Net->NetNumber;
1223 #else
1224 NetNumber = 0;
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);
1246 #ifndef SK_NO_RLMT
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);
1265 #ifndef SK_NO_RLMT
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);
1293 else {
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;
1305 #ifdef GENESIS
1306 if (pAC->GIni.GIGenesis) {
1307 XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
1309 #endif /* GENESIS */
1310 #ifdef YUKON
1311 if (!pAC->GIni.GIGenesis) {
1312 GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
1314 #endif /* YUKON */
1316 #ifndef SK_NO_RLMT
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;
1353 #ifndef SK_NO_RLMT
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 */
1361 #ifndef 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;
1368 #ifdef DEBUG
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]))
1386 #endif /* DEBUG */
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
1403 * Description:
1404 * This routine manages promiscuous mode:
1405 * - none
1406 * - all LLC frames
1407 * - all MC frames
1409 * It calls either SkAddrXmacPromiscuousChange or
1410 * SkAddrGmacPromiscuousChange, according to the adapter in use.
1411 * The real work is done there.
1413 * Context:
1414 * runtime, pageable
1415 * may be called after SK_INIT_IO
1417 * Returns:
1418 * SK_ADDR_SUCCESS
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 */
1427 int ReturnCode = 0;
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 */
1434 #ifdef GENESIS
1435 if (pAC->GIni.GIGenesis) {
1436 ReturnCode =
1437 SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
1439 #endif /* GENESIS */
1440 #ifdef YUKON
1441 if (!pAC->GIni.GIGenesis) {
1442 ReturnCode =
1443 SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
1445 #endif /* YUKON */
1447 return (ReturnCode);
1449 } /* SkAddrPromiscuousChange */
1451 #ifdef GENESIS
1453 /******************************************************************************
1455 * SkAddrXmacPromiscuousChange - set promiscuous mode for given port
1457 * Description:
1458 * This routine manages promiscuous mode:
1459 * - none
1460 * - all LLC frames
1461 * - all MC frames
1463 * Context:
1464 * runtime, pageable
1465 * may be called after SK_INIT_IO
1467 * Returns:
1468 * SK_ADDR_SUCCESS
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 */
1477 int i;
1478 SK_BOOL InexactModeBit;
1479 SK_U8 Inexact;
1480 SK_U8 HwInexact;
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);
1499 else {
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];
1537 if (Inexact == 0) {
1538 /* Disable Hashing */
1539 SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE);
1541 else {
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 */
1568 #ifdef YUKON
1570 /******************************************************************************
1572 * SkAddrGmacPromiscuousChange - set promiscuous mode for given port
1574 * Description:
1575 * This routine manages promiscuous mode:
1576 * - none
1577 * - all LLC frames
1578 * - all MC frames
1580 * Context:
1581 * runtime, pageable
1582 * may be called after SK_INIT_IO
1584 * Returns:
1585 * SK_ADDR_SUCCESS
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 */
1654 #endif /* YUKON */
1656 #ifndef SK_SLIM
1658 /******************************************************************************
1660 * SkAddrSwap - swap address info
1662 * Description:
1663 * This routine swaps address info of two ports.
1665 * Context:
1666 * runtime, pageable
1667 * may be called after SK_INIT_IO
1669 * Returns:
1670 * SK_ADDR_SUCCESS
1671 * SK_ADDR_ILLEGAL_PORT
1673 int SkAddrSwap(
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 */
1679 int i;
1680 SK_U8 Byte;
1681 SK_MAC_ADDR MacAddr;
1682 SK_U32 DWord;
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);
1697 * Swap:
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
1707 * of ports.
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].
1756 ActivePort = i;
1757 /* 20001207 RA: Was "ToPortNumber;". */
1761 (void) SkAddrMcUpdate(pAC, IoC, FromPortNumber);
1762 (void) SkAddrMcUpdate(pAC, IoC, ToPortNumber);
1764 return (SK_ADDR_SUCCESS);
1766 } /* SkAddrSwap */
1768 #endif /* !SK_SLIM */
1770 #ifdef __cplusplus
1772 #endif /* __cplusplus */