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