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