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