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