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