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