]> git.ipfire.org Git - people/ms/u-boot.git/blame - drivers/net/sk98lin/skaddr.c
85xx: Drop FIT support to allow u-boot image to fit in 512k
[people/ms/u-boot.git] / drivers / net / sk98lin / skaddr.c
CommitLineData
7152b1d0
WD
1/******************************************************************************
2 *
3 * Name: skaddr.c
4 * Project: GEnesis, PCI Gigabit Ethernet Adapter
5 * Version: $Revision: 1.48 $
6 * Date: $Date: 2003/02/12 17:09:37 $
7 * Purpose: Manage Addresses (Multicast and Unicast) and Promiscuous Mode.
8 *
9 ******************************************************************************/
10
11/******************************************************************************
12 *
13 * (C)Copyright 1998-2002 SysKonnect GmbH.
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * The information in this file is provided "AS IS" without warranty.
21 *
22 ******************************************************************************/
23
24/******************************************************************************
25 *
26 * History:
27 *
28 * $Log: skaddr.c,v $
29 * Revision 1.48 2003/02/12 17:09:37 tschilli
30 * Fix in SkAddrOverride() to set both (physical and logical) MAC addresses
31 * in case that both addresses are identical.
42d1f039 32 *
7152b1d0
WD
33 * Revision 1.47 2002/09/17 06:31:10 tschilli
34 * Handling of SK_PROM_MODE_ALL_MC flag in SkAddrGmacMcUpdate()
35 * and SkAddrGmacPromiscuousChange() fixed.
36 * Editorial changes.
42d1f039 37 *
7152b1d0
WD
38 * Revision 1.46 2002/08/22 07:55:41 tschilli
39 * New function SkGmacMcHash() for GMAC multicast hashing algorithm added.
40 * Editorial changes.
42d1f039 41 *
7152b1d0
WD
42 * Revision 1.45 2002/08/15 12:29:35 tschilli
43 * SkAddrGmacMcUpdate() and SkAddrGmacPromiscuousChange() changed.
42d1f039 44 *
7152b1d0
WD
45 * Revision 1.44 2002/08/14 12:18:03 rschmidt
46 * Replaced direct handling of MAC Hashing (XMAC and GMAC)
47 * with routine SkMacHashing().
48 * Replaced wrong 3rd para 'i' with 'PortNumber' in SkMacPromiscMode().
42d1f039 49 *
7152b1d0
WD
50 * Revision 1.43 2002/08/13 09:37:43 rschmidt
51 * Corrected some SK_DBG_MSG outputs.
52 * Replaced wrong 2nd para pAC with IoC in SkMacPromiscMode().
53 * Editorial changes.
42d1f039 54 *
7152b1d0
WD
55 * Revision 1.42 2002/08/12 11:24:36 rschmidt
56 * Remove setting of logical MAC address GM_SRC_ADDR_2 in SkAddrInit().
57 * Replaced direct handling of MAC Promiscuous Mode (XMAC and GMAC)
58 * with routine SkMacPromiscMode().
59 * Editorial changes.
42d1f039 60 *
7152b1d0
WD
61 * Revision 1.41 2002/06/10 13:52:18 tschilli
62 * Changes for handling YUKON.
63 * All changes are internally and not visible to the programmer
64 * using this module.
42d1f039 65 *
7152b1d0
WD
66 * Revision 1.40 2001/02/14 14:04:59 rassmann
67 * Editorial changes.
42d1f039 68 *
7152b1d0
WD
69 * Revision 1.39 2001/01/30 10:30:04 rassmann
70 * Editorial changes.
42d1f039 71 *
7152b1d0
WD
72 * Revision 1.38 2001/01/25 16:26:52 rassmann
73 * Ensured that logical address overrides are done on net's active port.
42d1f039 74 *
7152b1d0
WD
75 * Revision 1.37 2001/01/22 13:41:34 rassmann
76 * Supporting two nets on dual-port adapters.
42d1f039 77 *
7152b1d0
WD
78 * Revision 1.36 2000/08/07 11:10:39 rassmann
79 * Editorial changes.
42d1f039 80 *
7152b1d0
WD
81 * Revision 1.35 2000/05/04 09:38:41 rassmann
82 * Editorial changes.
83 * Corrected multicast address hashing.
42d1f039 84 *
7152b1d0
WD
85 * Revision 1.34 1999/11/22 13:23:44 cgoos
86 * Changed license header to GPL.
42d1f039 87 *
7152b1d0
WD
88 * Revision 1.33 1999/05/28 10:56:06 rassmann
89 * Editorial changes.
42d1f039 90 *
7152b1d0
WD
91 * Revision 1.32 1999/03/31 10:59:20 rassmann
92 * Returning Success instead of DupAddr if address shall be overridden
93 * with same value.
42d1f039 94 *
7152b1d0
WD
95 * Revision 1.31 1999/01/14 16:18:17 rassmann
96 * Corrected multicast initialization.
42d1f039 97 *
7152b1d0
WD
98 * Revision 1.30 1999/01/04 10:30:35 rassmann
99 * SkAddrOverride only possible after SK_INIT_IO phase.
42d1f039 100 *
7152b1d0
WD
101 * Revision 1.29 1998/12/29 13:13:10 rassmann
102 * An address override is now preserved in the SK_INIT_IO phase.
103 * All functions return an int now.
104 * Extended parameter checking.
42d1f039 105 *
7152b1d0
WD
106 * Revision 1.28 1998/12/01 11:45:53 rassmann
107 * Code cleanup.
42d1f039 108 *
7152b1d0
WD
109 * Revision 1.27 1998/12/01 09:22:49 rassmann
110 * SkAddrMcAdd and SkAddrMcUpdate returned SK_MC_FILTERING_INEXACT
111 * too often.
42d1f039 112 *
7152b1d0
WD
113 * Revision 1.26 1998/11/24 12:39:44 rassmann
114 * Reserved multicast entry for BPDU address.
115 * 13 multicast entries left for protocol.
42d1f039 116 *
7152b1d0
WD
117 * Revision 1.25 1998/11/17 16:54:23 rassmann
118 * Using exact match for up to 14 multicast addresses.
119 * Still receiving all multicasts if more addresses are added.
42d1f039 120 *
7152b1d0
WD
121 * Revision 1.24 1998/11/13 17:24:31 rassmann
122 * Changed return value of SkAddrOverride to int.
42d1f039 123 *
7152b1d0
WD
124 * Revision 1.23 1998/11/13 16:56:18 rassmann
125 * Added macro SK_ADDR_COMPARE.
126 * Changed return type of SkAddrOverride to SK_BOOL.
42d1f039 127 *
7152b1d0
WD
128 * Revision 1.22 1998/11/04 17:06:17 rassmann
129 * Corrected McUpdate and PromiscuousChange functions.
42d1f039 130 *
7152b1d0
WD
131 * Revision 1.21 1998/10/29 14:34:04 rassmann
132 * Clearing SK_ADDR struct at startup.
42d1f039 133 *
7152b1d0
WD
134 * Revision 1.20 1998/10/28 18:16:34 rassmann
135 * Avoiding I/Os before SK_INIT_RUN level.
136 * Aligning InexactFilter.
42d1f039 137 *
7152b1d0
WD
138 * Revision 1.19 1998/10/28 11:29:28 rassmann
139 * Programming physical address in SkAddrMcUpdate.
140 * Corrected programming of exact match entries.
42d1f039 141 *
7152b1d0
WD
142 * Revision 1.18 1998/10/28 10:34:48 rassmann
143 * Corrected reading of physical addresses.
42d1f039 144 *
7152b1d0
WD
145 * Revision 1.17 1998/10/28 10:26:13 rassmann
146 * Getting ports' current MAC addresses from EPROM now.
147 * Added debug output.
42d1f039 148 *
7152b1d0
WD
149 * Revision 1.16 1998/10/27 16:20:12 rassmann
150 * Reading MAC address byte by byte.
42d1f039 151 *
7152b1d0
WD
152 * Revision 1.15 1998/10/22 11:39:09 rassmann
153 * Corrected signed/unsigned mismatches.
42d1f039 154 *
7152b1d0
WD
155 * Revision 1.14 1998/10/19 17:12:35 rassmann
156 * Syntax corrections.
42d1f039 157 *
7152b1d0
WD
158 * Revision 1.13 1998/10/19 17:02:19 rassmann
159 * Now reading permanent MAC addresses from CRF.
42d1f039 160 *
7152b1d0
WD
161 * Revision 1.12 1998/10/15 15:15:48 rassmann
162 * Changed Flags Parameters from SK_U8 to int.
163 * Checked with lint.
42d1f039 164 *
7152b1d0
WD
165 * Revision 1.11 1998/09/24 19:15:12 rassmann
166 * Code cleanup.
42d1f039 167 *
7152b1d0
WD
168 * Revision 1.10 1998/09/18 20:18:54 rassmann
169 * Added HW access.
170 * Implemented swapping.
42d1f039 171 *
7152b1d0
WD
172 * Revision 1.9 1998/09/16 11:32:00 rassmann
173 * Including skdrv1st.h again. :(
42d1f039 174 *
7152b1d0
WD
175 * Revision 1.8 1998/09/16 11:09:34 rassmann
176 * Syntax corrections.
42d1f039 177 *
7152b1d0
WD
178 * Revision 1.7 1998/09/14 17:06:34 rassmann
179 * Minor changes.
42d1f039 180 *
7152b1d0
WD
181 * Revision 1.6 1998/09/07 08:45:41 rassmann
182 * Syntax corrections.
42d1f039 183 *
7152b1d0
WD
184 * Revision 1.5 1998/09/04 19:40:19 rassmann
185 * Interface enhancements.
42d1f039 186 *
7152b1d0
WD
187 * Revision 1.4 1998/09/04 12:14:12 rassmann
188 * Interface cleanup.
42d1f039 189 *
7152b1d0
WD
190 * Revision 1.3 1998/09/02 16:56:40 rassmann
191 * Updated interface.
42d1f039 192 *
7152b1d0
WD
193 * Revision 1.2 1998/08/27 14:26:09 rassmann
194 * Updated interface.
42d1f039 195 *
7152b1d0
WD
196 * Revision 1.1 1998/08/21 08:30:22 rassmann
197 * First public version.
198 *
199 ******************************************************************************/
200
201/******************************************************************************
202 *
203 * Description:
204 *
205 * This module is intended to manage multicast addresses, address override,
206 * and promiscuous mode on GEnesis and Yukon adapters.
207 *
208 * Address Layout:
209 * port address: physical MAC address
210 * 1st exact match: logical MAC address (GEnesis only)
211 * 2nd exact match: RLMT multicast (GEnesis only)
212 * exact match 3-13: OS-specific multicasts (GEnesis only)
213 *
214 * Include File Hierarchy:
215 *
216 * "skdrv1st.h"
217 * "skdrv2nd.h"
218 *
219 ******************************************************************************/
220
149dded2
WD
221#include <config.h>
222
7152b1d0
WD
223#ifndef lint
224static const char SysKonnectFileId[] =
225 "@(#) $Id: skaddr.c,v 1.48 2003/02/12 17:09:37 tschilli Exp $ (C) SysKonnect.";
226#endif /* !defined(lint) */
227
228#define __SKADDR_C
229
230#ifdef __cplusplus
231#error C++ is not yet supported.
232extern "C" {
233#endif /* cplusplus */
234
235#include "h/skdrv1st.h"
236#include "h/skdrv2nd.h"
237
238/* defines ********************************************************************/
239
240
241#define XMAC_POLY 0xEDB88320UL /* CRC32-Poly - XMAC: Little Endian */
242#define GMAC_POLY 0x04C11DB7L /* CRC16-Poly - GMAC: Little Endian */
243#define HASH_BITS 6 /* #bits in hash */
244#define SK_MC_BIT 0x01
245
246/* Error numbers and messages. */
247
248#define SKERR_ADDR_E001 (SK_ERRBASE_ADDR + 0)
249#define SKERR_ADDR_E001MSG "Bad Flags."
250#define SKERR_ADDR_E002 (SKERR_ADDR_E001 + 1)
251#define SKERR_ADDR_E002MSG "New Error."
252
253/* typedefs *******************************************************************/
254
255/* None. */
256
257/* global variables ***********************************************************/
258
259/* 64-bit hash values with all bits set. */
260
261SK_U16 OnesHash[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
262
263/* local variables ************************************************************/
264
265#ifdef DEBUG
266static int Next0[SK_MAX_MACS] = {0, 0};
267#endif /* DEBUG */
268
269/* functions ******************************************************************/
270
271/******************************************************************************
272 *
273 * SkAddrInit - initialize data, set state to init
274 *
275 * Description:
276 *
277 * SK_INIT_DATA
278 * ============
279 *
280 * This routine clears the multicast tables and resets promiscuous mode.
281 * Some entries are reserved for the "logical MAC address", the
282 * SK-RLMT multicast address, and the BPDU multicast address.
283 *
284 *
285 * SK_INIT_IO
286 * ==========
287 *
288 * All permanent MAC addresses are read from EPROM.
289 * If the current MAC addresses are not already set in software,
290 * they are set to the values of the permanent addresses.
291 * The current addresses are written to the corresponding MAC.
292 *
293 *
294 * SK_INIT_RUN
295 * ===========
296 *
297 * Nothing.
298 *
299 * Context:
300 * init, pageable
301 *
302 * Returns:
303 * SK_ADDR_SUCCESS
304 */
305int SkAddrInit(
306SK_AC *pAC, /* the adapter context */
307SK_IOC IoC, /* I/O context */
308int Level) /* initialization level */
309{
310 int j;
311 SK_U32 i;
312 SK_U8 *InAddr;
313 SK_U16 *OutAddr;
314 SK_ADDR_PORT *pAPort;
315
316 switch (Level) {
317 case SK_INIT_DATA:
318 SK_MEMSET((char *) &pAC->Addr, 0, sizeof(SK_ADDR));
319
320 for (i = 0; i < SK_MAX_MACS; i++) {
321 pAPort = &pAC->Addr.Port[i];
322 pAPort->PromMode = SK_PROM_MODE_NONE;
42d1f039 323
7152b1d0
WD
324 pAPort->FirstExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
325 pAPort->FirstExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
326 pAPort->NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
327 pAPort->NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
328 }
329#ifdef xDEBUG
330 for (i = 0; i < SK_MAX_MACS; i++) {
331 if (pAC->Addr.Port[i].NextExactMatchRlmt <
332 SK_ADDR_FIRST_MATCH_RLMT) {
333 Next0[i] |= 4;
334 }
335 }
336#endif /* DEBUG */
337 /* pAC->Addr.InitDone = SK_INIT_DATA; */
338 break;
339
340 case SK_INIT_IO:
341 for (i = 0; i < SK_MAX_NETS; i++) {
342 pAC->Addr.Net[i].ActivePort = pAC->Rlmt.Net[i].ActivePort;
343 }
344#ifdef xDEBUG
345 for (i = 0; i < SK_MAX_MACS; i++) {
346 if (pAC->Addr.Port[i].NextExactMatchRlmt <
347 SK_ADDR_FIRST_MATCH_RLMT) {
348 Next0[i] |= 8;
349 }
350 }
351#endif /* DEBUG */
42d1f039 352
7152b1d0
WD
353 /* Read permanent logical MAC address from Control Register File. */
354 for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
355 InAddr = (SK_U8 *) &pAC->Addr.Net[0].PermanentMacAddress.a[j];
356 SK_IN8(IoC, B2_MAC_1 + j, InAddr);
357 }
358
359 if (!pAC->Addr.Net[0].CurrentMacAddressSet) {
360 /* Set the current logical MAC address to the permanent one. */
361 pAC->Addr.Net[0].CurrentMacAddress =
362 pAC->Addr.Net[0].PermanentMacAddress;
363 pAC->Addr.Net[0].CurrentMacAddressSet = SK_TRUE;
364 }
365
366 /* Set the current logical MAC address. */
367 pAC->Addr.Port[pAC->Addr.Net[0].ActivePort].Exact[0] =
368 pAC->Addr.Net[0].CurrentMacAddress;
369#if SK_MAX_NETS > 1
370 /* Set logical MAC address for net 2 to (log | 3). */
371 if (!pAC->Addr.Net[1].CurrentMacAddressSet) {
372 pAC->Addr.Net[1].PermanentMacAddress =
373 pAC->Addr.Net[0].PermanentMacAddress;
374 pAC->Addr.Net[1].PermanentMacAddress.a[5] |= 3;
375 /* Set the current logical MAC address to the permanent one. */
376 pAC->Addr.Net[1].CurrentMacAddress =
377 pAC->Addr.Net[1].PermanentMacAddress;
378 pAC->Addr.Net[1].CurrentMacAddressSet = SK_TRUE;
379 }
380#endif /* SK_MAX_NETS > 1 */
381
382#ifdef DEBUG
383 for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
384 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
385 ("Permanent MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
386 i,
387 pAC->Addr.Net[i].PermanentMacAddress.a[0],
388 pAC->Addr.Net[i].PermanentMacAddress.a[1],
389 pAC->Addr.Net[i].PermanentMacAddress.a[2],
390 pAC->Addr.Net[i].PermanentMacAddress.a[3],
391 pAC->Addr.Net[i].PermanentMacAddress.a[4],
392 pAC->Addr.Net[i].PermanentMacAddress.a[5]))
42d1f039 393
7152b1d0
WD
394 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
395 ("Logical MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
396 i,
397 pAC->Addr.Net[i].CurrentMacAddress.a[0],
398 pAC->Addr.Net[i].CurrentMacAddress.a[1],
399 pAC->Addr.Net[i].CurrentMacAddress.a[2],
400 pAC->Addr.Net[i].CurrentMacAddress.a[3],
401 pAC->Addr.Net[i].CurrentMacAddress.a[4],
402 pAC->Addr.Net[i].CurrentMacAddress.a[5]))
403 }
404#endif /* DEBUG */
405
406 for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
407 pAPort = &pAC->Addr.Port[i];
408
409 /* Read permanent port addresses from Control Register File. */
410 for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
411 InAddr = (SK_U8 *) &pAPort->PermanentMacAddress.a[j];
412 SK_IN8(IoC, B2_MAC_2 + 8 * i + j, InAddr);
413 }
414
415 if (!pAPort->CurrentMacAddressSet) {
416 /*
417 * Set the current and previous physical MAC address
418 * of this port to its permanent MAC address.
419 */
420 pAPort->CurrentMacAddress = pAPort->PermanentMacAddress;
421 pAPort->PreviousMacAddress = pAPort->PermanentMacAddress;
422 pAPort->CurrentMacAddressSet = SK_TRUE;
423 }
424
425 /* Set port's current physical MAC address. */
426 OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
42d1f039 427
7152b1d0
WD
428 if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
429 XM_OUTADDR(IoC, i, XM_SA, OutAddr);
430 }
431 else {
432 GM_OUTADDR(IoC, i, GM_SRC_ADDR_1L, OutAddr);
433 }
434#ifdef DEBUG
435 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
436 ("SkAddrInit: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
437 pAPort->PermanentMacAddress.a[0],
438 pAPort->PermanentMacAddress.a[1],
439 pAPort->PermanentMacAddress.a[2],
440 pAPort->PermanentMacAddress.a[3],
441 pAPort->PermanentMacAddress.a[4],
442 pAPort->PermanentMacAddress.a[5]))
42d1f039 443
7152b1d0
WD
444 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
445 ("SkAddrInit: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
446 pAPort->CurrentMacAddress.a[0],
447 pAPort->CurrentMacAddress.a[1],
448 pAPort->CurrentMacAddress.a[2],
449 pAPort->CurrentMacAddress.a[3],
450 pAPort->CurrentMacAddress.a[4],
451 pAPort->CurrentMacAddress.a[5]))
452#endif /* DEBUG */
453 }
454 /* pAC->Addr.InitDone = SK_INIT_IO; */
455 break;
456
457 case SK_INIT_RUN:
458#ifdef xDEBUG
459 for (i = 0; i < SK_MAX_MACS; i++) {
460 if (pAC->Addr.Port[i].NextExactMatchRlmt <
461 SK_ADDR_FIRST_MATCH_RLMT) {
462 Next0[i] |= 16;
463 }
464 }
465#endif /* DEBUG */
466
467 /* pAC->Addr.InitDone = SK_INIT_RUN; */
468 break;
469
470 default: /* error */
471 break;
472 }
473
474 return (SK_ADDR_SUCCESS);
42d1f039 475
7152b1d0
WD
476} /* SkAddrInit */
477
478
479/******************************************************************************
480 *
481 * SkAddrMcClear - clear the multicast table
482 *
483 * Description:
484 * This routine clears the multicast table.
485 *
486 * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
487 * immediately.
488 *
489 * It calls either SkAddrXmacMcClear or SkAddrGmacMcClear, according
490 * to the adapter in use. The real work is done there.
491 *
492 * Context:
493 * runtime, pageable
494 * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
495 * may be called after SK_INIT_IO without limitation
496 *
497 * Returns:
498 * SK_ADDR_SUCCESS
499 * SK_ADDR_ILLEGAL_PORT
500 */
501int SkAddrMcClear(
502SK_AC *pAC, /* adapter context */
503SK_IOC IoC, /* I/O context */
504SK_U32 PortNumber, /* Index of affected port */
505int Flags) /* permanent/non-perm, sw-only */
506{
507 int ReturnCode;
42d1f039 508
7152b1d0
WD
509 if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
510 return (SK_ADDR_ILLEGAL_PORT);
511 }
42d1f039 512
7152b1d0
WD
513 if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
514 ReturnCode = SkAddrXmacMcClear(pAC, IoC, PortNumber, Flags);
515 }
516 else {
517 ReturnCode = SkAddrGmacMcClear(pAC, IoC, PortNumber, Flags);
518 }
519
520 return (ReturnCode);
521
522} /* SkAddrMcClear */
523
524
525/******************************************************************************
526 *
527 * SkAddrXmacMcClear - clear the multicast table
528 *
529 * Description:
530 * This routine clears the multicast table
531 * (either entry 2 or entries 3-16 and InexactFilter) of the given port.
532 * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
533 * immediately.
534 *
535 * Context:
536 * runtime, pageable
537 * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
538 * may be called after SK_INIT_IO without limitation
539 *
540 * Returns:
541 * SK_ADDR_SUCCESS
542 * SK_ADDR_ILLEGAL_PORT
543 */
544int SkAddrXmacMcClear(
545SK_AC *pAC, /* adapter context */
546SK_IOC IoC, /* I/O context */
547SK_U32 PortNumber, /* Index of affected port */
548int Flags) /* permanent/non-perm, sw-only */
549{
550 int i;
551
552 if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
553
554 /* Clear RLMT multicast addresses. */
555 pAC->Addr.Port[PortNumber].NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
556 }
557 else { /* not permanent => DRV */
558
559 /* Clear InexactFilter */
560 for (i = 0; i < 8; i++) {
561 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
562 }
563
564 /* Clear DRV multicast addresses. */
565
566 pAC->Addr.Port[PortNumber].NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
567 }
568
569 if (!(Flags & SK_MC_SW_ONLY)) {
570 (void) SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
571 }
572
573 return (SK_ADDR_SUCCESS);
42d1f039 574
7152b1d0
WD
575} /* SkAddrXmacMcClear */
576
577
578/******************************************************************************
579 *
580 * SkAddrGmacMcClear - clear the multicast table
581 *
582 * Description:
583 * This routine clears the multicast hashing table (InexactFilter)
584 * (either the RLMT or the driver bits) of the given port.
585 *
586 * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
587 * immediately.
588 *
589 * Context:
590 * runtime, pageable
591 * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
592 * may be called after SK_INIT_IO without limitation
593 *
594 * Returns:
595 * SK_ADDR_SUCCESS
596 * SK_ADDR_ILLEGAL_PORT
597 */
598int SkAddrGmacMcClear(
599SK_AC *pAC, /* adapter context */
600SK_IOC IoC, /* I/O context */
601SK_U32 PortNumber, /* Index of affected port */
602int Flags) /* permanent/non-perm, sw-only */
603{
604 int i;
605
606#ifdef DEBUG
607 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
608 ("GMAC InexactFilter (not cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
609 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0],
610 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1],
611 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2],
612 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3],
613 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
614 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
615 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
616 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]))
617#endif /* DEBUG */
618
619 /* Clear InexactFilter */
620 for (i = 0; i < 8; i++) {
621 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
622 }
42d1f039 623
7152b1d0 624 if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
42d1f039 625
7152b1d0
WD
626 /* Copy DRV bits to InexactFilter. */
627 for (i = 0; i < 8; i++) {
628 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
629 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
42d1f039 630
7152b1d0
WD
631 /* Clear InexactRlmtFilter. */
632 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i] = 0;
633
42d1f039 634 }
7152b1d0
WD
635 }
636 else { /* not permanent => DRV */
42d1f039 637
7152b1d0
WD
638 /* Copy RLMT bits to InexactFilter. */
639 for (i = 0; i < 8; i++) {
640 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
641 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
42d1f039 642
7152b1d0
WD
643 /* Clear InexactDrvFilter. */
644 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i] = 0;
645 }
646 }
42d1f039 647
7152b1d0
WD
648#ifdef DEBUG
649 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
650 ("GMAC InexactFilter (cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
651 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0],
652 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1],
653 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2],
654 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3],
655 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
656 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
657 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
658 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]))
659#endif /* DEBUG */
42d1f039 660
7152b1d0
WD
661 if (!(Flags & SK_MC_SW_ONLY)) {
662 (void) SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
663 }
42d1f039 664
7152b1d0
WD
665 return (SK_ADDR_SUCCESS);
666
667} /* SkAddrGmacMcClear */
668
669#ifndef SK_ADDR_CHEAT
670
671/******************************************************************************
672 *
673 * SkXmacMcHash - hash multicast address
674 *
675 * Description:
676 * This routine computes the hash value for a multicast address.
677 * A CRC32 algorithm is used.
678 *
679 * Notes:
680 * The code was adapted from the XaQti data sheet.
681 *
682 * Context:
683 * runtime, pageable
684 *
685 * Returns:
686 * Hash value of multicast address.
687 */
688SK_U32 SkXmacMcHash(
689unsigned char *pMc) /* Multicast address */
690{
691 SK_U32 Idx;
692 SK_U32 Bit;
693 SK_U32 Data;
694 SK_U32 Crc;
695
696 Crc = 0xFFFFFFFFUL;
697 for (Idx = 0; Idx < SK_MAC_ADDR_LEN; Idx++) {
698 Data = *pMc++;
699 for (Bit = 0; Bit < 8; Bit++, Data >>= 1) {
700 Crc = (Crc >> 1) ^ (((Crc ^ Data) & 1) ? XMAC_POLY : 0);
701 }
702 }
703
704 return (Crc & ((1 << HASH_BITS) - 1));
705
706} /* SkXmacMcHash */
707
708
709/******************************************************************************
710 *
711 * SkGmacMcHash - hash multicast address
712 *
713 * Description:
714 * This routine computes the hash value for a multicast address.
715 * A CRC16 algorithm is used.
716 *
717 * Notes:
718 *
719 *
720 * Context:
721 * runtime, pageable
722 *
723 * Returns:
724 * Hash value of multicast address.
725 */
726SK_U32 SkGmacMcHash(
727unsigned char *pMc) /* Multicast address */
728{
729 SK_U32 Data;
730 SK_U32 TmpData;
731 SK_U32 Crc;
732 int Byte;
733 int Bit;
734
735 Crc = 0xFFFFFFFFUL;
736 for (Byte = 0; Byte < 6; Byte++) {
737 /* Get next byte. */
738 Data = (SK_U32) pMc[Byte];
42d1f039 739
7152b1d0
WD
740 /* Change bit order in byte. */
741 TmpData = Data;
742 for (Bit = 0; Bit < 8; Bit++) {
743 if (TmpData & 1L) {
744 Data |= 1L << (7 - Bit);
745 }
746 else {
747 Data &= ~(1L << (7 - Bit));
748 }
749 TmpData >>= 1;
750 }
42d1f039 751
7152b1d0
WD
752 Crc ^= (Data << 24);
753 for (Bit = 0; Bit < 8; Bit++) {
754 if (Crc & 0x80000000) {
755 Crc = (Crc << 1) ^ GMAC_POLY;
756 }
757 else {
758 Crc <<= 1;
759 }
760 }
761 }
42d1f039 762
7152b1d0
WD
763 return (Crc & ((1 << HASH_BITS) - 1));
764
765} /* SkGmacMcHash */
766
767#endif /* not SK_ADDR_CHEAT */
768
769/******************************************************************************
770 *
771 * SkAddrMcAdd - add a multicast address to a port
772 *
773 * Description:
774 * This routine enables reception for a given address on the given port.
775 *
776 * It calls either SkAddrXmacMcAdd or SkAddrGmacMcAdd, according to the
777 * adapter in use. The real work is done there.
778 *
779 * Notes:
780 * The return code is only valid for SK_PROM_MODE_NONE.
781 *
782 * Context:
783 * runtime, pageable
784 * may be called after SK_INIT_DATA
785 *
786 * Returns:
787 * SK_MC_FILTERING_EXACT
788 * SK_MC_FILTERING_INEXACT
789 * SK_MC_ILLEGAL_ADDRESS
790 * SK_MC_ILLEGAL_PORT
791 * SK_MC_RLMT_OVERFLOW
792 */
793int SkAddrMcAdd(
794SK_AC *pAC, /* adapter context */
795SK_IOC IoC, /* I/O context */
796SK_U32 PortNumber, /* Port Number */
797SK_MAC_ADDR *pMc, /* multicast address to be added */
798int Flags) /* permanent/non-permanent */
799{
800 int ReturnCode;
42d1f039 801
7152b1d0
WD
802 if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
803 return (SK_ADDR_ILLEGAL_PORT);
804 }
42d1f039 805
7152b1d0
WD
806 if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
807 ReturnCode = SkAddrXmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
808 }
809 else {
810 ReturnCode = SkAddrGmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
811 }
812
813 return (ReturnCode);
814
815} /* SkAddrMcAdd */
816
817
818/******************************************************************************
819 *
820 * SkAddrXmacMcAdd - add a multicast address to a port
821 *
822 * Description:
823 * This routine enables reception for a given address on the given port.
824 *
825 * Notes:
826 * The return code is only valid for SK_PROM_MODE_NONE.
827 *
828 * The multicast bit is only checked if there are no free exact match
829 * entries.
830 *
831 * Context:
832 * runtime, pageable
833 * may be called after SK_INIT_DATA
834 *
835 * Returns:
836 * SK_MC_FILTERING_EXACT
837 * SK_MC_FILTERING_INEXACT
838 * SK_MC_ILLEGAL_ADDRESS
839 * SK_MC_RLMT_OVERFLOW
840 */
841int SkAddrXmacMcAdd(
842SK_AC *pAC, /* adapter context */
843SK_IOC IoC, /* I/O context */
844SK_U32 PortNumber, /* Port Number */
845SK_MAC_ADDR *pMc, /* multicast address to be added */
846int Flags) /* permanent/non-permanent */
847{
848 int i;
849 SK_U8 Inexact;
850#ifndef SK_ADDR_CHEAT
851 SK_U32 HashBit;
852#endif /* !defined(SK_ADDR_CHEAT) */
853
854 if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
855#ifdef xDEBUG
856 if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt <
857 SK_ADDR_FIRST_MATCH_RLMT) {
858 Next0[PortNumber] |= 1;
859 return (SK_MC_RLMT_OVERFLOW);
860 }
861#endif /* DEBUG */
42d1f039 862
7152b1d0
WD
863 if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt >
864 SK_ADDR_LAST_MATCH_RLMT) {
865 return (SK_MC_RLMT_OVERFLOW);
866 }
867
868 /* Set a RLMT multicast address. */
869
870 pAC->Addr.Port[PortNumber].Exact[
871 pAC->Addr.Port[PortNumber].NextExactMatchRlmt++] = *pMc;
872
873 return (SK_MC_FILTERING_EXACT);
874 }
875
876#ifdef xDEBUG
877 if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <
878 SK_ADDR_FIRST_MATCH_DRV) {
879 Next0[PortNumber] |= 2;
880 return (SK_MC_RLMT_OVERFLOW);
881 }
882#endif /* DEBUG */
42d1f039 883
7152b1d0
WD
884 if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
885
886 /* Set exact match entry. */
887 pAC->Addr.Port[PortNumber].Exact[
888 pAC->Addr.Port[PortNumber].NextExactMatchDrv++] = *pMc;
889
890 /* Clear InexactFilter */
891 for (i = 0; i < 8; i++) {
892 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
893 }
894 }
895 else {
896 if (!(pMc->a[0] & SK_MC_BIT)) {
897 /* Hashing only possible with multicast addresses. */
898 return (SK_MC_ILLEGAL_ADDRESS);
899 }
900#ifndef SK_ADDR_CHEAT
901 /* Compute hash value of address. */
902 HashBit = 63 - SkXmacMcHash(&pMc->a[0]);
903
904 /* Add bit to InexactFilter. */
905 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[HashBit / 8] |=
906 1 << (HashBit % 8);
907#else /* SK_ADDR_CHEAT */
908 /* Set all bits in InexactFilter. */
909 for (i = 0; i < 8; i++) {
910 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
911 }
912#endif /* SK_ADDR_CHEAT */
913 }
914
915 for (Inexact = 0, i = 0; i < 8; i++) {
916 Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
917 }
918
919 if (Inexact == 0 && pAC->Addr.Port[PortNumber].PromMode == 0) {
920 return (SK_MC_FILTERING_EXACT);
921 }
922 else {
923 return (SK_MC_FILTERING_INEXACT);
924 }
925
926} /* SkAddrXmacMcAdd */
927
928
929/******************************************************************************
930 *
931 * SkAddrGmacMcAdd - add a multicast address to a port
932 *
933 * Description:
934 * This routine enables reception for a given address on the given port.
935 *
936 * Notes:
937 * The return code is only valid for SK_PROM_MODE_NONE.
938 *
939 * Context:
940 * runtime, pageable
941 * may be called after SK_INIT_DATA
942 *
943 * Returns:
944 * SK_MC_FILTERING_INEXACT
945 * SK_MC_ILLEGAL_ADDRESS
946 */
947int SkAddrGmacMcAdd(
948SK_AC *pAC, /* adapter context */
949SK_IOC IoC, /* I/O context */
950SK_U32 PortNumber, /* Port Number */
951SK_MAC_ADDR *pMc, /* multicast address to be added */
952int Flags) /* permanent/non-permanent */
953{
954 int i;
955#ifndef SK_ADDR_CHEAT
956 SK_U32 HashBit;
957#endif /* !defined(SK_ADDR_CHEAT) */
42d1f039 958
7152b1d0
WD
959 if (!(pMc->a[0] & SK_MC_BIT)) {
960 /* Hashing only possible with multicast addresses. */
961 return (SK_MC_ILLEGAL_ADDRESS);
962 }
42d1f039 963
7152b1d0 964#ifndef SK_ADDR_CHEAT
42d1f039 965
7152b1d0
WD
966 /* Compute hash value of address. */
967 HashBit = SkGmacMcHash(&pMc->a[0]);
42d1f039 968
7152b1d0 969 if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
42d1f039 970
7152b1d0
WD
971 /* Add bit to InexactRlmtFilter. */
972 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[HashBit / 8] |=
973 1 << (HashBit % 8);
42d1f039 974
7152b1d0
WD
975 /* Copy bit to InexactFilter. */
976 for (i = 0; i < 8; i++) {
977 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
978 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
979 }
980#ifdef DEBUG
981 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
982 ("GMAC InexactRlmtFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
983 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[0],
984 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[1],
985 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[2],
986 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[3],
987 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[4],
988 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[5],
989 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[6],
990 pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[7]))
991#endif /* DEBUG */
992 }
993 else { /* not permanent => DRV */
42d1f039 994
7152b1d0
WD
995 /* Add bit to InexactDrvFilter. */
996 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[HashBit / 8] |=
997 1 << (HashBit % 8);
42d1f039 998
7152b1d0
WD
999 /* Copy bit to InexactFilter. */
1000 for (i = 0; i < 8; i++) {
1001 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
1002 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
1003 }
1004#ifdef DEBUG
1005 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1006 ("GMAC InexactDrvFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
1007 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[0],
1008 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[1],
1009 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[2],
1010 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[3],
1011 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[4],
1012 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[5],
1013 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[6],
1014 pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[7]))
1015#endif /* DEBUG */
1016 }
42d1f039 1017
7152b1d0 1018#else /* SK_ADDR_CHEAT */
42d1f039 1019
7152b1d0
WD
1020 /* Set all bits in InexactFilter. */
1021 for (i = 0; i < 8; i++) {
1022 pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
1023 }
1024#endif /* SK_ADDR_CHEAT */
42d1f039 1025
7152b1d0 1026 return (SK_MC_FILTERING_INEXACT);
42d1f039 1027
7152b1d0
WD
1028} /* SkAddrGmacMcAdd */
1029
1030
1031/******************************************************************************
1032 *
1033 * SkAddrMcUpdate - update the HW MC address table and set the MAC address
1034 *
1035 * Description:
1036 * This routine enables reception of the addresses contained in a local
1037 * table for a given port.
1038 * It also programs the port's current physical MAC address.
1039 *
1040 * It calls either SkAddrXmacMcUpdate or SkAddrGmacMcUpdate, according
1041 * to the adapter in use. The real work is done there.
1042 *
1043 * Notes:
1044 * The return code is only valid for SK_PROM_MODE_NONE.
1045 *
1046 * Context:
1047 * runtime, pageable
1048 * may be called after SK_INIT_IO
1049 *
1050 * Returns:
1051 * SK_MC_FILTERING_EXACT
1052 * SK_MC_FILTERING_INEXACT
1053 * SK_ADDR_ILLEGAL_PORT
1054 */
1055int SkAddrMcUpdate(
1056SK_AC *pAC, /* adapter context */
1057SK_IOC IoC, /* I/O context */
1058SK_U32 PortNumber) /* Port Number */
1059{
1060 int ReturnCode;
42d1f039 1061
7152b1d0
WD
1062 if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
1063 return (SK_ADDR_ILLEGAL_PORT);
1064 }
42d1f039 1065
7152b1d0
WD
1066 if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
1067 ReturnCode = SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
1068 }
1069 else {
1070 ReturnCode = SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
1071 }
42d1f039 1072
7152b1d0
WD
1073 return (ReturnCode);
1074
1075} /* SkAddrMcUpdate */
1076
1077
1078/******************************************************************************
1079 *
1080 * SkAddrXmacMcUpdate - update the HW MC address table and set the MAC address
1081 *
1082 * Description:
1083 * This routine enables reception of the addresses contained in a local
1084 * table for a given port.
1085 * It also programs the port's current physical MAC address.
1086 *
1087 * Notes:
1088 * The return code is only valid for SK_PROM_MODE_NONE.
1089 *
1090 * Context:
1091 * runtime, pageable
1092 * may be called after SK_INIT_IO
1093 *
1094 * Returns:
1095 * SK_MC_FILTERING_EXACT
1096 * SK_MC_FILTERING_INEXACT
1097 * SK_ADDR_ILLEGAL_PORT
1098 */
1099int SkAddrXmacMcUpdate(
1100SK_AC *pAC, /* adapter context */
1101SK_IOC IoC, /* I/O context */
1102SK_U32 PortNumber) /* Port Number */
1103{
1104 SK_U32 i;
1105 SK_U8 Inexact;
1106 SK_U16 *OutAddr;
1107 SK_ADDR_PORT *pAPort;
1108
1109 SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1110 ("SkAddrXmacMcUpdate on Port %u.\n", PortNumber))
42d1f039 1111
7152b1d0
WD
1112 pAPort = &pAC->Addr.Port[PortNumber];
1113
1114#ifdef DEBUG
1115 SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1116 ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
1117#endif /* DEBUG */
1118
1119 /* Start with 0 to also program the logical MAC address. */
1120 for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
1121 /* Set exact match address i on XMAC */
1122 OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
1123 XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
1124 }
1125
1126 /* Clear other permanent exact match addresses on XMAC */
1127 if (pAPort->NextExactMatchRlmt <= SK_ADDR_LAST_MATCH_RLMT) {
42d1f039 1128
7152b1d0
WD
1129 SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchRlmt,
1130 SK_ADDR_LAST_MATCH_RLMT);
1131 }
1132
1133 for (i = pAPort->FirstExactMatchDrv; i < pAPort->NextExactMatchDrv; i++) {
1134 OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
1135 XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
1136 }
1137
1138 /* Clear other non-permanent exact match addresses on XMAC */
1139 if (pAPort->NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
42d1f039 1140
7152b1d0
WD
1141 SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchDrv,
1142 SK_ADDR_LAST_MATCH_DRV);
1143 }
1144
1145 for (Inexact = 0, i = 0; i < 8; i++) {
1146 Inexact |= pAPort->InexactFilter.Bytes[i];
1147 }
1148
1149 if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
42d1f039 1150
7152b1d0
WD
1151 /* Set all bits in 64-bit hash register. */
1152 XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
42d1f039 1153
7152b1d0
WD
1154 /* Enable Hashing */
1155 SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
1156 }
1157 else if (Inexact != 0) {
42d1f039 1158
7152b1d0
WD
1159 /* Set 64-bit hash register to InexactFilter. */
1160 XM_OUTHASH(IoC, PortNumber, XM_HSM, &pAPort->InexactFilter.Bytes[0]);
42d1f039 1161
7152b1d0
WD
1162 /* Enable Hashing */
1163 SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
1164 }
1165 else {
1166 /* Disable Hashing */
1167 SkMacHashing(pAC, IoC, PortNumber, SK_FALSE);
1168 }
1169
1170 if (pAPort->PromMode != SK_PROM_MODE_NONE) {
1171 (void) SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
1172 }
1173
1174 /* Set port's current physical MAC address. */
1175 OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
42d1f039 1176
7152b1d0
WD
1177 XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
1178
1179#ifdef xDEBUG
1180 for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
1181 SK_U8 InAddr8[6];
1182 SK_U16 *InAddr;
1183
1184 /* Get exact match address i from port PortNumber. */
1185 InAddr = (SK_U16 *) &InAddr8[0];
42d1f039 1186
7152b1d0 1187 XM_INADDR(IoC, PortNumber, XM_EXM(i), InAddr);
42d1f039 1188
7152b1d0
WD
1189 SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1190 ("SkAddrXmacMcUpdate: MC address %d on Port %u: ",
1191 "%02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x\n",
1192 i,
1193 PortNumber,
1194 InAddr8[0],
1195 InAddr8[1],
1196 InAddr8[2],
1197 InAddr8[3],
1198 InAddr8[4],
1199 InAddr8[5],
1200 pAPort->Exact[i].a[0],
1201 pAPort->Exact[i].a[1],
1202 pAPort->Exact[i].a[2],
1203 pAPort->Exact[i].a[3],
1204 pAPort->Exact[i].a[4],
1205 pAPort->Exact[i].a[5]))
1206 }
42d1f039 1207#endif /* DEBUG */
7152b1d0
WD
1208
1209 /* Determine return value. */
1210 if (Inexact == 0 && pAPort->PromMode == 0) {
1211 return (SK_MC_FILTERING_EXACT);
1212 }
1213 else {
1214 return (SK_MC_FILTERING_INEXACT);
1215 }
42d1f039 1216
7152b1d0
WD
1217} /* SkAddrXmacMcUpdate */
1218
1219
1220/******************************************************************************
1221 *
1222 * SkAddrGmacMcUpdate - update the HW MC address table and set the MAC address
1223 *
1224 * Description:
1225 * This routine enables reception of the addresses contained in a local
1226 * table for a given port.
1227 * It also programs the port's current physical MAC address.
1228 *
1229 * Notes:
1230 * The return code is only valid for SK_PROM_MODE_NONE.
1231 *
1232 * Context:
1233 * runtime, pageable
1234 * may be called after SK_INIT_IO
1235 *
1236 * Returns:
1237 * SK_MC_FILTERING_EXACT
1238 * SK_MC_FILTERING_INEXACT
1239 * SK_ADDR_ILLEGAL_PORT
1240 */
1241int SkAddrGmacMcUpdate(
1242SK_AC *pAC, /* adapter context */
1243SK_IOC IoC, /* I/O context */
1244SK_U32 PortNumber) /* Port Number */
1245{
1246 SK_U32 i;
1247 SK_U8 Inexact;
1248 SK_U16 *OutAddr;
1249 SK_ADDR_PORT *pAPort;
1250
1251 SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1252 ("SkAddrGmacMcUpdate on Port %u.\n", PortNumber))
42d1f039 1253
7152b1d0
WD
1254 pAPort = &pAC->Addr.Port[PortNumber];
1255
1256#ifdef DEBUG
1257 SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1258 ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
1259#endif /* DEBUG */
42d1f039 1260
7152b1d0
WD
1261 for (Inexact = 0, i = 0; i < 8; i++) {
1262 Inexact |= pAPort->InexactFilter.Bytes[i];
1263 }
42d1f039 1264
7152b1d0
WD
1265 /* Set 64-bit hash register to InexactFilter. */
1266 GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1,
1267 &pAPort->InexactFilter.Bytes[0]);
42d1f039
WD
1268
1269 if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
1270
7152b1d0
WD
1271 /* Set all bits in 64-bit hash register. */
1272 GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
42d1f039 1273
7152b1d0
WD
1274 /* Enable Hashing */
1275 SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
1276 }
42d1f039 1277 else {
7152b1d0
WD
1278 /* Enable Hashing. */
1279 SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
1280 }
42d1f039 1281
7152b1d0
WD
1282 if (pAPort->PromMode != SK_PROM_MODE_NONE) {
1283 (void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
1284 }
42d1f039 1285
7152b1d0
WD
1286 /* Set port's current physical MAC address. */
1287 OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
1288 GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
42d1f039 1289
7152b1d0
WD
1290 /* Set port's current logical MAC address. */
1291 OutAddr = (SK_U16 *) &pAPort->Exact[0].a[0];
1292 GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_2L, OutAddr);
42d1f039 1293
7152b1d0
WD
1294#ifdef DEBUG
1295 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1296 ("SkAddrGmacMcUpdate: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
1297 pAPort->Exact[0].a[0],
1298 pAPort->Exact[0].a[1],
1299 pAPort->Exact[0].a[2],
1300 pAPort->Exact[0].a[3],
1301 pAPort->Exact[0].a[4],
1302 pAPort->Exact[0].a[5]))
42d1f039 1303
7152b1d0
WD
1304 SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1305 ("SkAddrGmacMcUpdate: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
1306 pAPort->CurrentMacAddress.a[0],
1307 pAPort->CurrentMacAddress.a[1],
1308 pAPort->CurrentMacAddress.a[2],
1309 pAPort->CurrentMacAddress.a[3],
1310 pAPort->CurrentMacAddress.a[4],
1311 pAPort->CurrentMacAddress.a[5]))
1312#endif /* DEBUG */
42d1f039 1313
7152b1d0
WD
1314 /* Determine return value. */
1315 if (Inexact == 0 && pAPort->PromMode == 0) {
1316 return (SK_MC_FILTERING_EXACT);
1317 }
1318 else {
1319 return (SK_MC_FILTERING_INEXACT);
1320 }
42d1f039 1321
7152b1d0
WD
1322} /* SkAddrGmacMcUpdate */
1323
1324
1325/******************************************************************************
1326 *
1327 * SkAddrOverride - override a port's MAC address
1328 *
1329 * Description:
1330 * This routine overrides the MAC address of one port.
1331 *
1332 * Context:
1333 * runtime, pageable
1334 * may be called after SK_INIT_IO
1335 *
1336 * Returns:
1337 * SK_ADDR_SUCCESS if successful.
1338 * SK_ADDR_DUPLICATE_ADDRESS if duplicate MAC address.
1339 * SK_ADDR_MULTICAST_ADDRESS if multicast or broadcast address.
1340 * SK_ADDR_TOO_EARLY if SK_INIT_IO was not executed before.
1341 */
1342int SkAddrOverride(
1343SK_AC *pAC, /* adapter context */
1344SK_IOC IoC, /* I/O context */
1345SK_U32 PortNumber, /* Port Number */
1346SK_MAC_ADDR *pNewAddr, /* new MAC address */
1347int Flags) /* logical/physical MAC address */
1348{
1349 SK_EVPARA Para;
1350 SK_U32 NetNumber;
1351 SK_U32 i;
1352 SK_U16 *OutAddr;
1353
1354 NetNumber = pAC->Rlmt.Port[PortNumber].Net->NetNumber;
1355
1356 if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
1357 return (SK_ADDR_ILLEGAL_PORT);
1358 }
1359
1360 if (pNewAddr != NULL && (pNewAddr->a[0] & SK_MC_BIT) != 0) {
1361 return (SK_ADDR_MULTICAST_ADDRESS);
1362 }
1363
1364 if (!pAC->Addr.Net[NetNumber].CurrentMacAddressSet) {
1365 return (SK_ADDR_TOO_EARLY);
1366 }
1367
1368 if (Flags & SK_ADDR_SET_LOGICAL) { /* Activate logical MAC address. */
1369 /* Parameter *pNewAddr is ignored. */
1370 for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
1371 if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
1372 return (SK_ADDR_TOO_EARLY);
1373 }
1374 }
1375
1376 /* Set PortNumber to number of net's active port. */
1377 PortNumber = pAC->Rlmt.Net[NetNumber].
1378 Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
1379
1380 pAC->Addr.Port[PortNumber].Exact[0] =
1381 pAC->Addr.Net[NetNumber].CurrentMacAddress;
1382
1383 /* Write address to first exact match entry of active port. */
1384 (void) SkAddrMcUpdate(pAC, IoC, PortNumber);
1385 }
1386 else if (Flags & SK_ADDR_CLEAR_LOGICAL) {
1387 /* Deactivate logical MAC address. */
1388 /* Parameter *pNewAddr is ignored. */
1389 for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
1390 if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
1391 return (SK_ADDR_TOO_EARLY);
1392 }
1393 }
1394
1395 /* Set PortNumber to number of net's active port. */
1396 PortNumber = pAC->Rlmt.Net[NetNumber].
1397 Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
1398
1399 for (i = 0; i < SK_MAC_ADDR_LEN; i++ ) {
1400 pAC->Addr.Port[PortNumber].Exact[0].a[i] = 0;
1401 }
1402
1403 /* Write address to first exact match entry of active port. */
1404 (void) SkAddrMcUpdate(pAC, IoC, PortNumber);
1405 }
1406 else if (Flags & SK_ADDR_PHYSICAL_ADDRESS) { /* Physical MAC address. */
1407 if (SK_ADDR_EQUAL(pNewAddr->a,
1408 pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
1409 return (SK_ADDR_DUPLICATE_ADDRESS);
1410 }
1411
1412 for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
1413 if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
1414 return (SK_ADDR_TOO_EARLY);
1415 }
1416
1417 if (SK_ADDR_EQUAL(pNewAddr->a,
1418 pAC->Addr.Port[i].CurrentMacAddress.a)) {
1419 if (i == PortNumber) {
1420 return (SK_ADDR_SUCCESS);
1421 }
1422 else {
1423 return (SK_ADDR_DUPLICATE_ADDRESS);
1424 }
1425 }
1426 }
1427
1428 pAC->Addr.Port[PortNumber].PreviousMacAddress =
1429 pAC->Addr.Port[PortNumber].CurrentMacAddress;
1430 pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
1431
1432 /* Change port's physical MAC address. */
1433 OutAddr = (SK_U16 *) pNewAddr;
42d1f039 1434
7152b1d0
WD
1435 if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
1436 XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
1437 }
1438 else {
1439 GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
1440 }
1441
1442 /* Report address change to RLMT. */
1443 Para.Para32[0] = PortNumber;
1444 Para.Para32[0] = -1;
1445 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
1446 }
1447 else { /* Logical MAC address. */
1448 if (SK_ADDR_EQUAL(pNewAddr->a,
1449 pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
1450 return (SK_ADDR_SUCCESS);
1451 }
42d1f039 1452
7152b1d0
WD
1453 for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
1454 if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
1455 return (SK_ADDR_TOO_EARLY);
1456 }
1457
1458 if (SK_ADDR_EQUAL(pNewAddr->a,
1459 pAC->Addr.Port[i].CurrentMacAddress.a)) {
1460 return (SK_ADDR_DUPLICATE_ADDRESS);
1461 }
1462 }
42d1f039 1463
7152b1d0
WD
1464 /*
1465 * In case that the physical and the logical MAC addresses are equal
1466 * we must also change the physical MAC address here.
1467 * In this case we have an adapter which initially was programmed with
1468 * two identical MAC addresses.
1469 */
1470 if (SK_ADDR_EQUAL(pAC->Addr.Port[PortNumber].CurrentMacAddress.a,
1471 pAC->Addr.Port[PortNumber].Exact[0].a)) {
42d1f039 1472
7152b1d0
WD
1473 pAC->Addr.Port[PortNumber].PreviousMacAddress =
1474 pAC->Addr.Port[PortNumber].CurrentMacAddress;
1475 pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
42d1f039 1476
7152b1d0
WD
1477 /* Report address change to RLMT. */
1478 Para.Para32[0] = PortNumber;
1479 Para.Para32[0] = -1;
1480 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
1481 }
42d1f039 1482
7152b1d0
WD
1483 /* Set PortNumber to number of net's active port. */
1484 PortNumber = pAC->Rlmt.Net[NetNumber].
1485 Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
1486
1487 pAC->Addr.Net[NetNumber].CurrentMacAddress = *pNewAddr;
1488 pAC->Addr.Port[PortNumber].Exact[0] = *pNewAddr;
1489#ifdef DEBUG
1490 SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1491 ("SkAddrOverride: Permanent MAC Address: %02X %02X %02X %02X %02X %02X\n",
1492 pAC->Addr.Net[NetNumber].PermanentMacAddress.a[0],
1493 pAC->Addr.Net[NetNumber].PermanentMacAddress.a[1],
1494 pAC->Addr.Net[NetNumber].PermanentMacAddress.a[2],
1495 pAC->Addr.Net[NetNumber].PermanentMacAddress.a[3],
1496 pAC->Addr.Net[NetNumber].PermanentMacAddress.a[4],
1497 pAC->Addr.Net[NetNumber].PermanentMacAddress.a[5]))
42d1f039 1498
7152b1d0
WD
1499 SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
1500 ("SkAddrOverride: New logical MAC Address: %02X %02X %02X %02X %02X %02X\n",
1501 pAC->Addr.Net[NetNumber].CurrentMacAddress.a[0],
1502 pAC->Addr.Net[NetNumber].CurrentMacAddress.a[1],
1503 pAC->Addr.Net[NetNumber].CurrentMacAddress.a[2],
1504 pAC->Addr.Net[NetNumber].CurrentMacAddress.a[3],
1505 pAC->Addr.Net[NetNumber].CurrentMacAddress.a[4],
1506 pAC->Addr.Net[NetNumber].CurrentMacAddress.a[5]))
1507#endif /* DEBUG */
1508
42d1f039 1509 /* Write address to first exact match entry of active port. */
7152b1d0
WD
1510 (void) SkAddrMcUpdate(pAC, IoC, PortNumber);
1511 }
1512
1513 return (SK_ADDR_SUCCESS);
42d1f039 1514
7152b1d0
WD
1515} /* SkAddrOverride */
1516
1517
1518/******************************************************************************
1519 *
1520 * SkAddrPromiscuousChange - set promiscuous mode for given port
1521 *
1522 * Description:
1523 * This routine manages promiscuous mode:
1524 * - none
1525 * - all LLC frames
1526 * - all MC frames
1527 *
1528 * It calls either SkAddrXmacPromiscuousChange or
1529 * SkAddrGmacPromiscuousChange, according to the adapter in use.
1530 * The real work is done there.
1531 *
1532 * Context:
1533 * runtime, pageable
1534 * may be called after SK_INIT_IO
1535 *
1536 * Returns:
1537 * SK_ADDR_SUCCESS
1538 * SK_ADDR_ILLEGAL_PORT
1539 */
1540int SkAddrPromiscuousChange(
1541SK_AC *pAC, /* adapter context */
1542SK_IOC IoC, /* I/O context */
1543SK_U32 PortNumber, /* port whose promiscuous mode changes */
1544int NewPromMode) /* new promiscuous mode */
1545{
1546 int ReturnCode;
42d1f039 1547
7152b1d0
WD
1548 if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
1549 return (SK_ADDR_ILLEGAL_PORT);
1550 }
42d1f039 1551
7152b1d0
WD
1552 if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
1553 ReturnCode = SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
1554 }
1555 else {
1556 ReturnCode = SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
1557 }
1558
1559 return (ReturnCode);
1560
1561} /* SkAddrPromiscuousChange */
1562
1563
1564/******************************************************************************
1565 *
1566 * SkAddrXmacPromiscuousChange - set promiscuous mode for given port
1567 *
1568 * Description:
1569 * This routine manages promiscuous mode:
1570 * - none
1571 * - all LLC frames
1572 * - all MC frames
1573 *
1574 * Context:
1575 * runtime, pageable
1576 * may be called after SK_INIT_IO
1577 *
1578 * Returns:
1579 * SK_ADDR_SUCCESS
1580 * SK_ADDR_ILLEGAL_PORT
1581 */
1582int SkAddrXmacPromiscuousChange(
1583SK_AC *pAC, /* adapter context */
1584SK_IOC IoC, /* I/O context */
1585SK_U32 PortNumber, /* port whose promiscuous mode changes */
1586int NewPromMode) /* new promiscuous mode */
1587{
1588 int i;
1589 SK_BOOL InexactModeBit;
1590 SK_U8 Inexact;
1591 SK_U8 HwInexact;
1592 SK_FILTER64 HwInexactFilter;
1593 SK_U16 LoMode; /* Lower 16 bits of XMAC Mode Register. */
1594 int CurPromMode = SK_PROM_MODE_NONE;
1595
1596 /* Read CurPromMode from Hardware. */
1597 XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
1598
1599 if ((LoMode & XM_MD_ENA_PROM) != 0) {
1600 /* Promiscuous mode! */
1601 CurPromMode |= SK_PROM_MODE_LLC;
1602 }
42d1f039 1603
7152b1d0
WD
1604 for (Inexact = 0xFF, i = 0; i < 8; i++) {
1605 Inexact &= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
1606 }
1607 if (Inexact == 0xFF) {
1608 CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
1609 }
1610 else {
1611 /* Get InexactModeBit (bit XM_MD_ENA_HASH in mode register) */
1612 XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
42d1f039 1613
7152b1d0
WD
1614 InexactModeBit = (LoMode & XM_MD_ENA_HASH) != 0;
1615
1616 /* Read 64-bit hash register from XMAC */
1617 XM_INHASH(IoC, PortNumber, XM_HSM, &HwInexactFilter.Bytes[0]);
1618
1619 for (HwInexact = 0xFF, i = 0; i < 8; i++) {
1620 HwInexact &= HwInexactFilter.Bytes[i];
1621 }
1622
1623 if (InexactModeBit && (HwInexact == 0xFF)) {
1624 CurPromMode |= SK_PROM_MODE_ALL_MC;
1625 }
1626 }
1627
1628 pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
1629
1630 if (NewPromMode == CurPromMode) {
1631 return (SK_ADDR_SUCCESS);
1632 }
1633
1634 if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
1635 !(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC. */
42d1f039 1636
7152b1d0
WD
1637 /* Set all bits in 64-bit hash register. */
1638 XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
1639
1640 /* Enable Hashing */
1641 SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
1642 }
1643 else if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
1644 !(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm MC. */
1645 for (Inexact = 0, i = 0; i < 8; i++) {
1646 Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
1647 }
1648 if (Inexact == 0) {
1649 /* Disable Hashing */
1650 SkMacHashing(pAC, IoC, PortNumber, SK_FALSE);
1651 }
1652 else {
1653 /* Set 64-bit hash register to InexactFilter. */
1654 XM_OUTHASH(IoC, PortNumber, XM_HSM,
1655 &pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
1656
1657 /* Enable Hashing */
1658 SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
1659 }
1660 }
1661
1662 if ((NewPromMode & SK_PROM_MODE_LLC) &&
1663 !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */
1664 /* Set the MAC in Promiscuous Mode */
1665 SkMacPromiscMode(pAC, IoC, PortNumber, SK_TRUE);
1666 }
1667 else if ((CurPromMode & SK_PROM_MODE_LLC) &&
1668 !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC. */
1669 /* Clear Promiscuous Mode */
1670 SkMacPromiscMode(pAC, IoC, PortNumber, SK_FALSE);
1671 }
42d1f039 1672
7152b1d0 1673 return (SK_ADDR_SUCCESS);
42d1f039 1674
7152b1d0
WD
1675} /* SkAddrXmacPromiscuousChange */
1676
1677
1678/******************************************************************************
1679 *
1680 * SkAddrGmacPromiscuousChange - set promiscuous mode for given port
1681 *
1682 * Description:
1683 * This routine manages promiscuous mode:
1684 * - none
1685 * - all LLC frames
1686 * - all MC frames
1687 *
1688 * Context:
1689 * runtime, pageable
1690 * may be called after SK_INIT_IO
1691 *
1692 * Returns:
1693 * SK_ADDR_SUCCESS
1694 * SK_ADDR_ILLEGAL_PORT
1695 */
1696int SkAddrGmacPromiscuousChange(
1697SK_AC *pAC, /* adapter context */
1698SK_IOC IoC, /* I/O context */
1699SK_U32 PortNumber, /* port whose promiscuous mode changes */
1700int NewPromMode) /* new promiscuous mode */
1701{
1702 SK_U16 ReceiveControl; /* GMAC Receive Control Register */
1703 int CurPromMode = SK_PROM_MODE_NONE;
1704
1705 /* Read CurPromMode from Hardware. */
1706 GM_IN16(IoC, PortNumber, GM_RX_CTRL, &ReceiveControl);
1707
1708 if ((ReceiveControl & (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA)) == 0) {
1709 /* Promiscuous mode! */
1710 CurPromMode |= SK_PROM_MODE_LLC;
1711 }
1712
1713 if ((ReceiveControl & GM_RXCR_MCF_ENA) == 0) {
1714 /* All Multicast mode! */
1715 CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
1716 }
1717
1718 pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
1719
1720 if (NewPromMode == CurPromMode) {
1721 return (SK_ADDR_SUCCESS);
1722 }
42d1f039 1723
7152b1d0
WD
1724 if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
1725 !(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC */
42d1f039 1726
7152b1d0
WD
1727 /* Set all bits in 64-bit hash register. */
1728 GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
42d1f039 1729
7152b1d0
WD
1730 /* Enable Hashing */
1731 SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
1732 }
42d1f039 1733
7152b1d0
WD
1734 if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
1735 !(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm. MC */
1736
1737 /* Set 64-bit hash register to InexactFilter. */
1738 GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1,
1739 &pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
1740
1741 /* Enable Hashing. */
1742 SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
1743 }
1744
1745 if ((NewPromMode & SK_PROM_MODE_LLC) &&
1746 !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */
42d1f039 1747
7152b1d0
WD
1748 /* Set the MAC to Promiscuous Mode. */
1749 SkMacPromiscMode(pAC, IoC, PortNumber, SK_TRUE);
1750 }
1751 else if ((CurPromMode & SK_PROM_MODE_LLC) &&
1752 !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC */
42d1f039 1753
7152b1d0
WD
1754 /* Clear Promiscuous Mode. */
1755 SkMacPromiscMode(pAC, IoC, PortNumber, SK_FALSE);
1756 }
1757
1758 return (SK_ADDR_SUCCESS);
42d1f039 1759
7152b1d0
WD
1760} /* SkAddrGmacPromiscuousChange */
1761
1762
1763/******************************************************************************
1764 *
1765 * SkAddrSwap - swap address info
1766 *
1767 * Description:
1768 * This routine swaps address info of two ports.
1769 *
1770 * Context:
1771 * runtime, pageable
1772 * may be called after SK_INIT_IO
1773 *
1774 * Returns:
1775 * SK_ADDR_SUCCESS
1776 * SK_ADDR_ILLEGAL_PORT
1777 */
1778int SkAddrSwap(
1779SK_AC *pAC, /* adapter context */
1780SK_IOC IoC, /* I/O context */
1781SK_U32 FromPortNumber, /* Port1 Index */
1782SK_U32 ToPortNumber) /* Port2 Index */
1783{
1784 int i;
1785 SK_U8 Byte;
1786 SK_MAC_ADDR MacAddr;
1787 SK_U32 DWord;
1788
1789 if (FromPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
1790 return (SK_ADDR_ILLEGAL_PORT);
1791 }
1792
1793 if (ToPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
1794 return (SK_ADDR_ILLEGAL_PORT);
1795 }
1796
1797 if (pAC->Rlmt.Port[FromPortNumber].Net != pAC->Rlmt.Port[ToPortNumber].Net) {
1798 return (SK_ADDR_ILLEGAL_PORT);
1799 }
1800
1801 /*
1802 * Swap:
1803 * - Exact Match Entries (GEnesis and Yukon)
1804 * Yukon uses first entry for the logical MAC
1805 * address (stored in the second GMAC register).
1806 * - FirstExactMatchRlmt (GEnesis only)
1807 * - NextExactMatchRlmt (GEnesis only)
1808 * - FirstExactMatchDrv (GEnesis only)
1809 * - NextExactMatchDrv (GEnesis only)
1810 * - 64-bit filter (InexactFilter)
1811 * - Promiscuous Mode
1812 * of ports.
1813 */
1814
1815 for (i = 0; i < SK_ADDR_EXACT_MATCHES; i++) {
1816 MacAddr = pAC->Addr.Port[FromPortNumber].Exact[i];
1817 pAC->Addr.Port[FromPortNumber].Exact[i] =
1818 pAC->Addr.Port[ToPortNumber].Exact[i];
1819 pAC->Addr.Port[ToPortNumber].Exact[i] = MacAddr;
1820 }
1821
1822 for (i = 0; i < 8; i++) {
1823 Byte = pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i];
1824 pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i] =
1825 pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i];
1826 pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i] = Byte;
1827 }
42d1f039 1828
7152b1d0
WD
1829 i = pAC->Addr.Port[FromPortNumber].PromMode;
1830 pAC->Addr.Port[FromPortNumber].PromMode = pAC->Addr.Port[ToPortNumber].PromMode;
1831 pAC->Addr.Port[ToPortNumber].PromMode = i;
42d1f039 1832
7152b1d0
WD
1833 if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
1834 DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt;
1835 pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt =
1836 pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt;
1837 pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt = DWord;
42d1f039 1838
7152b1d0
WD
1839 DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt;
1840 pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt =
1841 pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt;
1842 pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt = DWord;
42d1f039 1843
7152b1d0
WD
1844 DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv;
1845 pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv =
1846 pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv;
1847 pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv = DWord;
42d1f039 1848
7152b1d0
WD
1849 DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchDrv;
1850 pAC->Addr.Port[FromPortNumber].NextExactMatchDrv =
1851 pAC->Addr.Port[ToPortNumber].NextExactMatchDrv;
1852 pAC->Addr.Port[ToPortNumber].NextExactMatchDrv = DWord;
1853 }
42d1f039 1854
7152b1d0
WD
1855 /* CAUTION: Solution works if only ports of one adapter are in use. */
1856 for (i = 0; (SK_U32) i < pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].
1857 Net->NetNumber].NumPorts; i++) {
1858 if (pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
1859 Port[i]->PortNumber == ToPortNumber) {
1860 pAC->Addr.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
1861 ActivePort = i;
1862 /* 20001207 RA: Was "ToPortNumber;". */
1863 }
1864 }
42d1f039 1865
7152b1d0
WD
1866 (void) SkAddrMcUpdate(pAC, IoC, FromPortNumber);
1867 (void) SkAddrMcUpdate(pAC, IoC, ToPortNumber);
1868
1869 return (SK_ADDR_SUCCESS);
42d1f039 1870
7152b1d0
WD
1871} /* SkAddrSwap */
1872
1873#ifdef __cplusplus
1874}
1875#endif /* __cplusplus */