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