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