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