fs: use kmem_cache_zalloc instead
[pv_ops_mirror.git] / drivers / net / sk98lin / skaddr.c
blob6e6c56aa6d6f294b19c7b332ecfe4ff5fceff60f
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 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,
93 int Flags);
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,
100 int Flags);
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
111 * Description:
113 * SK_INIT_DATA
114 * ============
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.
121 * SK_INIT_IO
122 * ==========
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.
130 * SK_INIT_RUN
131 * ===========
133 * Nothing.
135 * Context:
136 * init, pageable
138 * Returns:
139 * SK_ADDR_SUCCESS
141 int SkAddrInit(
142 SK_AC *pAC, /* the adapter context */
143 SK_IOC IoC, /* I/O context */
144 int Level) /* initialization level */
146 int j;
147 SK_U32 i;
148 SK_U8 *InAddr;
149 SK_U16 *OutAddr;
150 SK_ADDR_PORT *pAPort;
152 switch (Level) {
153 case SK_INIT_DATA:
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;
166 #ifdef xDEBUG
167 for (i = 0; i < SK_MAX_MACS; i++) {
168 if (pAC->Addr.Port[i].NextExactMatchRlmt <
169 SK_ADDR_FIRST_MATCH_RLMT) {
170 Next0[i] |= 4;
173 #endif /* DEBUG */
174 /* pAC->Addr.InitDone = SK_INIT_DATA; */
175 break;
177 case SK_INIT_IO:
178 #ifndef SK_NO_RLMT
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 */
183 #ifdef xDEBUG
184 for (i = 0; i < SK_MAX_MACS; i++) {
185 if (pAC->Addr.Port[i].NextExactMatchRlmt <
186 SK_ADDR_FIRST_MATCH_RLMT) {
187 Next0[i] |= 8;
190 #endif /* DEBUG */
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;
208 #if SK_MAX_NETS > 1
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 */
221 #ifdef DEBUG
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]))
243 #endif /* DEBUG */
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];
266 #ifdef GENESIS
267 if (pAC->GIni.GIGenesis) {
268 XM_OUTADDR(IoC, i, XM_SA, OutAddr);
270 #endif /* GENESIS */
271 #ifdef YUKON
272 if (!pAC->GIni.GIGenesis) {
273 GM_OUTADDR(IoC, i, GM_SRC_ADDR_1L, OutAddr);
275 #endif /* YUKON */
276 #ifdef DEBUG
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]))
294 #endif /* DEBUG */
296 /* pAC->Addr.InitDone = SK_INIT_IO; */
297 break;
299 case SK_INIT_RUN:
300 #ifdef xDEBUG
301 for (i = 0; i < SK_MAX_MACS; i++) {
302 if (pAC->Addr.Port[i].NextExactMatchRlmt <
303 SK_ADDR_FIRST_MATCH_RLMT) {
304 Next0[i] |= 16;
307 #endif /* DEBUG */
309 /* pAC->Addr.InitDone = SK_INIT_RUN; */
310 break;
312 default: /* error */
313 break;
316 return (SK_ADDR_SUCCESS);
318 } /* SkAddrInit */
320 #ifndef SK_SLIM
322 /******************************************************************************
324 * SkAddrMcClear - clear the multicast table
326 * Description:
327 * This routine clears the multicast table.
329 * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
330 * immediately.
332 * It calls either SkAddrXmacMcClear or SkAddrGmacMcClear, according
333 * to the adapter in use. The real work is done there.
335 * Context:
336 * runtime, pageable
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
340 * Returns:
341 * SK_ADDR_SUCCESS
342 * SK_ADDR_ILLEGAL_PORT
344 int SkAddrMcClear(
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 */
350 int ReturnCode;
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);
359 else {
360 ReturnCode = SkAddrGmacMcClear(pAC, IoC, PortNumber, Flags);
363 return (ReturnCode);
365 } /* SkAddrMcClear */
367 #endif /* !SK_SLIM */
369 #ifndef SK_SLIM
371 /******************************************************************************
373 * SkAddrXmacMcClear - clear the multicast table
375 * Description:
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
379 * immediately.
381 * Context:
382 * runtime, pageable
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
386 * Returns:
387 * SK_ADDR_SUCCESS
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 */
396 int i;
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 */
425 #ifndef SK_SLIM
427 /******************************************************************************
429 * SkAddrGmacMcClear - clear the multicast table
431 * Description:
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
436 * immediately.
438 * Context:
439 * runtime, pageable
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
443 * Returns:
444 * SK_ADDR_SUCCESS
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 */
453 int i;
455 #ifdef DEBUG
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]))
466 #endif /* DEBUG */
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;
497 #ifdef DEBUG
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]))
508 #endif /* DEBUG */
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
524 * Description:
525 * This routine computes the hash value for a multicast address.
526 * A CRC32 algorithm is used.
528 * Notes:
529 * The code was adapted from the XaQti data sheet.
531 * Context:
532 * runtime, pageable
534 * Returns:
535 * Hash value of multicast address.
537 static SK_U32 SkXmacMcHash(
538 unsigned char *pMc) /* Multicast address */
540 SK_U32 Idx;
541 SK_U32 Bit;
542 SK_U32 Data;
543 SK_U32 Crc;
545 Crc = 0xFFFFFFFFUL;
546 for (Idx = 0; Idx < SK_MAC_ADDR_LEN; Idx++) {
547 Data = *pMc++;
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));
555 } /* SkXmacMcHash */
558 /******************************************************************************
560 * SkGmacMcHash - hash multicast address
562 * Description:
563 * This routine computes the hash value for a multicast address.
564 * A CRC16 algorithm is used.
566 * Notes:
569 * Context:
570 * runtime, pageable
572 * Returns:
573 * Hash value of multicast address.
575 static SK_U32 SkGmacMcHash(
576 unsigned char *pMc) /* Multicast address */
578 SK_U32 Data;
579 SK_U32 TmpData;
580 SK_U32 Crc;
581 int Byte;
582 int Bit;
584 Crc = 0xFFFFFFFFUL;
585 for (Byte = 0; Byte < 6; Byte++) {
586 /* Get next byte. */
587 Data = (SK_U32) pMc[Byte];
589 /* Change bit order in byte. */
590 TmpData = Data;
591 for (Bit = 0; Bit < 8; Bit++) {
592 if (TmpData & 1L) {
593 Data |= 1L << (7 - Bit);
595 else {
596 Data &= ~(1L << (7 - Bit));
598 TmpData >>= 1;
601 Crc ^= (Data << 24);
602 for (Bit = 0; Bit < 8; Bit++) {
603 if (Crc & 0x80000000) {
604 Crc = (Crc << 1) ^ GMAC_POLY;
606 else {
607 Crc <<= 1;
612 return (Crc & ((1 << HASH_BITS) - 1));
614 } /* SkGmacMcHash */
616 #endif /* !SK_ADDR_CHEAT */
618 /******************************************************************************
620 * SkAddrMcAdd - add a multicast address to a port
622 * Description:
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.
628 * Notes:
629 * The return code is only valid for SK_PROM_MODE_NONE.
631 * Context:
632 * runtime, pageable
633 * may be called after SK_INIT_DATA
635 * Returns:
636 * SK_MC_FILTERING_EXACT
637 * SK_MC_FILTERING_INEXACT
638 * SK_MC_ILLEGAL_ADDRESS
639 * SK_MC_ILLEGAL_PORT
640 * SK_MC_RLMT_OVERFLOW
642 int SkAddrMcAdd(
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 */
649 int ReturnCode;
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);
658 else {
659 ReturnCode = SkAddrGmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
662 return (ReturnCode);
664 } /* SkAddrMcAdd */
667 /******************************************************************************
669 * SkAddrXmacMcAdd - add a multicast address to a port
671 * Description:
672 * This routine enables reception for a given address on the given port.
674 * Notes:
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
678 * entries.
680 * Context:
681 * runtime, pageable
682 * may be called after SK_INIT_DATA
684 * Returns:
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 */
697 int i;
698 SK_U8 Inexact;
699 #ifndef SK_ADDR_CHEAT
700 SK_U32 HashBit;
701 #endif /* !defined(SK_ADDR_CHEAT) */
703 if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
704 #ifdef xDEBUG
705 if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt <
706 SK_ADDR_FIRST_MATCH_RLMT) {
707 Next0[PortNumber] |= 1;
708 return (SK_MC_RLMT_OVERFLOW);
710 #endif /* DEBUG */
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);
725 #ifdef xDEBUG
726 if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <
727 SK_ADDR_FIRST_MATCH_DRV) {
728 Next0[PortNumber] |= 2;
729 return (SK_MC_RLMT_OVERFLOW);
731 #endif /* DEBUG */
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;
744 else {
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] |=
755 1 << (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);
771 else {
772 return (SK_MC_FILTERING_INEXACT);
775 } /* SkAddrXmacMcAdd */
778 /******************************************************************************
780 * SkAddrGmacMcAdd - add a multicast address to a port
782 * Description:
783 * This routine enables reception for a given address on the given port.
785 * Notes:
786 * The return code is only valid for SK_PROM_MODE_NONE.
788 * Context:
789 * runtime, pageable
790 * may be called after SK_INIT_DATA
792 * Returns:
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 */
803 int i;
804 #ifndef SK_ADDR_CHEAT
805 SK_U32 HashBit;
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] |=
822 1 << (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];
829 #ifdef DEBUG
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]))
840 #endif /* DEBUG */
842 else { /* not permanent => DRV */
844 /* Add bit to InexactDrvFilter. */
845 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[HashBit / 8] |=
846 1 << (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];
853 #ifdef DEBUG
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]))
864 #endif /* DEBUG */
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
885 * Description:
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.
893 * Notes:
894 * The return code is only valid for SK_PROM_MODE_NONE.
896 * Context:
897 * runtime, pageable
898 * may be called after SK_INIT_IO
900 * Returns:
901 * SK_MC_FILTERING_EXACT
902 * SK_MC_FILTERING_INEXACT
903 * SK_ADDR_ILLEGAL_PORT
905 int SkAddrMcUpdate(
906 SK_AC *pAC, /* adapter context */
907 SK_IOC IoC, /* I/O context */
908 SK_U32 PortNumber) /* Port Number */
910 int ReturnCode = 0;
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 */
917 #ifdef GENESIS
918 if (pAC->GIni.GIGenesis) {
919 ReturnCode = SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
921 #endif /* GENESIS */
922 #ifdef YUKON
923 if (!pAC->GIni.GIGenesis) {
924 ReturnCode = SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
926 #endif /* YUKON */
927 return (ReturnCode);
929 } /* SkAddrMcUpdate */
932 #ifdef GENESIS
934 /******************************************************************************
936 * SkAddrXmacMcUpdate - update the HW MC address table and set the MAC address
938 * Description:
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.
943 * Notes:
944 * The return code is only valid for SK_PROM_MODE_NONE.
946 * Context:
947 * runtime, pageable
948 * may be called after SK_INIT_IO
950 * Returns:
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 */
960 SK_U32 i;
961 SK_U8 Inexact;
962 SK_U16 *OutAddr;
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];
970 #ifdef DEBUG
971 SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
972 ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
973 #endif /* DEBUG */
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);
1021 else {
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);
1035 #ifdef xDEBUG
1036 for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
1037 SK_U8 InAddr8[6];
1038 SK_U16 *InAddr;
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",
1049 PortNumber,
1050 InAddr8[0],
1051 InAddr8[1],
1052 InAddr8[2],
1053 InAddr8[3],
1054 InAddr8[4],
1055 InAddr8[5],
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]))
1063 #endif /* DEBUG */
1065 /* Determine return value. */
1066 if (Inexact == 0 && pAPort->PromMode == 0) {
1067 return (SK_MC_FILTERING_EXACT);
1069 else {
1070 return (SK_MC_FILTERING_INEXACT);
1073 } /* SkAddrXmacMcUpdate */
1075 #endif /* GENESIS */
1077 #ifdef YUKON
1079 /******************************************************************************
1081 * SkAddrGmacMcUpdate - update the HW MC address table and set the MAC address
1083 * Description:
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.
1088 * Notes:
1089 * The return code is only valid for SK_PROM_MODE_NONE.
1091 * Context:
1092 * runtime, pageable
1093 * may be called after SK_INIT_IO
1095 * Returns:
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 */
1105 #ifndef SK_SLIM
1106 SK_U32 i;
1107 SK_U8 Inexact;
1108 #endif /* not SK_SLIM */
1109 SK_U16 *OutAddr;
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];
1117 #ifdef DEBUG
1118 SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1119 ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
1120 #endif /* DEBUG */
1122 #ifndef SK_SLIM
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);
1139 else {
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);
1147 #else /* SK_SLIM */
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);
1167 #ifdef DEBUG
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]))
1185 #endif /* DEBUG */
1187 #ifndef SK_SLIM
1188 /* Determine return value. */
1189 if (Inexact == 0 && pAPort->PromMode == 0) {
1190 return (SK_MC_FILTERING_EXACT);
1192 else {
1193 return (SK_MC_FILTERING_INEXACT);
1195 #else /* SK_SLIM */
1196 return (SK_MC_FILTERING_INEXACT);
1197 #endif /* SK_SLIM */
1199 } /* SkAddrGmacMcUpdate */
1201 #endif /* YUKON */
1203 #ifndef SK_NO_MAO
1205 /******************************************************************************
1207 * SkAddrOverride - override a port's MAC address
1209 * Description:
1210 * This routine overrides the MAC address of one port.
1212 * Context:
1213 * runtime, pageable
1214 * may be called after SK_INIT_IO
1216 * Returns:
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.
1222 int SkAddrOverride(
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 */
1229 #ifndef SK_NO_RLMT
1230 SK_EVPARA Para;
1231 #endif /* !SK_NO_RLMT */
1232 SK_U32 NetNumber;
1233 SK_U32 i;
1234 SK_U16 SK_FAR *OutAddr;
1236 #ifndef SK_NO_RLMT
1237 NetNumber = pAC->Rlmt.Port[PortNumber].Net->NetNumber;
1238 #else
1239 NetNumber = 0;
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);
1261 #ifndef SK_NO_RLMT
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);
1280 #ifndef SK_NO_RLMT
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);
1308 else {
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;
1320 #ifdef GENESIS
1321 if (pAC->GIni.GIGenesis) {
1322 XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
1324 #endif /* GENESIS */
1325 #ifdef YUKON
1326 if (!pAC->GIni.GIGenesis) {
1327 GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
1329 #endif /* YUKON */
1331 #ifndef SK_NO_RLMT
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;
1368 #ifndef SK_NO_RLMT
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 */
1376 #ifndef 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;
1383 #ifdef DEBUG
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]))
1401 #endif /* DEBUG */
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
1418 * Description:
1419 * This routine manages promiscuous mode:
1420 * - none
1421 * - all LLC frames
1422 * - all MC frames
1424 * It calls either SkAddrXmacPromiscuousChange or
1425 * SkAddrGmacPromiscuousChange, according to the adapter in use.
1426 * The real work is done there.
1428 * Context:
1429 * runtime, pageable
1430 * may be called after SK_INIT_IO
1432 * Returns:
1433 * SK_ADDR_SUCCESS
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 */
1442 int ReturnCode = 0;
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 */
1449 #ifdef GENESIS
1450 if (pAC->GIni.GIGenesis) {
1451 ReturnCode =
1452 SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
1454 #endif /* GENESIS */
1455 #ifdef YUKON
1456 if (!pAC->GIni.GIGenesis) {
1457 ReturnCode =
1458 SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
1460 #endif /* YUKON */
1462 return (ReturnCode);
1464 } /* SkAddrPromiscuousChange */
1466 #ifdef GENESIS
1468 /******************************************************************************
1470 * SkAddrXmacPromiscuousChange - set promiscuous mode for given port
1472 * Description:
1473 * This routine manages promiscuous mode:
1474 * - none
1475 * - all LLC frames
1476 * - all MC frames
1478 * Context:
1479 * runtime, pageable
1480 * may be called after SK_INIT_IO
1482 * Returns:
1483 * SK_ADDR_SUCCESS
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 */
1492 int i;
1493 SK_BOOL InexactModeBit;
1494 SK_U8 Inexact;
1495 SK_U8 HwInexact;
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);
1514 else {
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];
1552 if (Inexact == 0) {
1553 /* Disable Hashing */
1554 SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE);
1556 else {
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 */
1583 #ifdef YUKON
1585 /******************************************************************************
1587 * SkAddrGmacPromiscuousChange - set promiscuous mode for given port
1589 * Description:
1590 * This routine manages promiscuous mode:
1591 * - none
1592 * - all LLC frames
1593 * - all MC frames
1595 * Context:
1596 * runtime, pageable
1597 * may be called after SK_INIT_IO
1599 * Returns:
1600 * SK_ADDR_SUCCESS
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 */
1669 #endif /* YUKON */
1671 #ifndef SK_SLIM
1673 /******************************************************************************
1675 * SkAddrSwap - swap address info
1677 * Description:
1678 * This routine swaps address info of two ports.
1680 * Context:
1681 * runtime, pageable
1682 * may be called after SK_INIT_IO
1684 * Returns:
1685 * SK_ADDR_SUCCESS
1686 * SK_ADDR_ILLEGAL_PORT
1688 int SkAddrSwap(
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 */
1694 int i;
1695 SK_U8 Byte;
1696 SK_MAC_ADDR MacAddr;
1697 SK_U32 DWord;
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);
1712 * Swap:
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
1722 * of ports.
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].
1771 ActivePort = i;
1772 /* 20001207 RA: Was "ToPortNumber;". */
1776 (void) SkAddrMcUpdate(pAC, IoC, FromPortNumber);
1777 (void) SkAddrMcUpdate(pAC, IoC, ToPortNumber);
1779 return (SK_ADDR_SUCCESS);
1781 } /* SkAddrSwap */
1783 #endif /* !SK_SLIM */
1785 #ifdef __cplusplus
1787 #endif /* __cplusplus */