Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 77b2555b52a894a2e39a42e43d993df875c46a6a 1773 lines 49 kB view raw
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)))) 46static 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 53extern "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 82static const SK_U16 OnesHash[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}; 83 84/* local variables ************************************************************/ 85 86#ifdef DEBUG 87static 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 */ 126int SkAddrInit( 127SK_AC *pAC, /* the adapter context */ 128SK_IOC IoC, /* I/O context */ 129int 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 */ 329int SkAddrMcClear( 330SK_AC *pAC, /* adapter context */ 331SK_IOC IoC, /* I/O context */ 332SK_U32 PortNumber, /* Index of affected port */ 333int 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 */ 375int SkAddrXmacMcClear( 376SK_AC *pAC, /* adapter context */ 377SK_IOC IoC, /* I/O context */ 378SK_U32 PortNumber, /* Index of affected port */ 379int 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 */ 432int SkAddrGmacMcClear( 433SK_AC *pAC, /* adapter context */ 434SK_IOC IoC, /* I/O context */ 435SK_U32 PortNumber, /* Index of affected port */ 436int 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 */ 522SK_U32 SkXmacMcHash( 523unsigned 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 */ 560SK_U32 SkGmacMcHash( 561unsigned 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 */ 627int SkAddrMcAdd( 628SK_AC *pAC, /* adapter context */ 629SK_IOC IoC, /* I/O context */ 630SK_U32 PortNumber, /* Port Number */ 631SK_MAC_ADDR *pMc, /* multicast address to be added */ 632int 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 */ 675int SkAddrXmacMcAdd( 676SK_AC *pAC, /* adapter context */ 677SK_IOC IoC, /* I/O context */ 678SK_U32 PortNumber, /* Port Number */ 679SK_MAC_ADDR *pMc, /* multicast address to be added */ 680int 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 */ 781int SkAddrGmacMcAdd( 782SK_AC *pAC, /* adapter context */ 783SK_IOC IoC, /* I/O context */ 784SK_U32 PortNumber, /* Port Number */ 785SK_MAC_ADDR *pMc, /* multicast address to be added */ 786int 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 */ 890int SkAddrMcUpdate( 891SK_AC *pAC, /* adapter context */ 892SK_IOC IoC, /* I/O context */ 893SK_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 */ 940int SkAddrXmacMcUpdate( 941SK_AC *pAC, /* adapter context */ 942SK_IOC IoC, /* I/O context */ 943SK_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 */ 1085int SkAddrGmacMcUpdate( 1086SK_AC *pAC, /* adapter context */ 1087SK_IOC IoC, /* I/O context */ 1088SK_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 */ 1207int SkAddrOverride( 1208SK_AC *pAC, /* adapter context */ 1209SK_IOC IoC, /* I/O context */ 1210SK_U32 PortNumber, /* Port Number */ 1211SK_MAC_ADDR SK_FAR *pNewAddr, /* new MAC address */ 1212int 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 */ 1421int SkAddrPromiscuousChange( 1422SK_AC *pAC, /* adapter context */ 1423SK_IOC IoC, /* I/O context */ 1424SK_U32 PortNumber, /* port whose promiscuous mode changes */ 1425int 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 */ 1471int SkAddrXmacPromiscuousChange( 1472SK_AC *pAC, /* adapter context */ 1473SK_IOC IoC, /* I/O context */ 1474SK_U32 PortNumber, /* port whose promiscuous mode changes */ 1475int 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 */ 1588int SkAddrGmacPromiscuousChange( 1589SK_AC *pAC, /* adapter context */ 1590SK_IOC IoC, /* I/O context */ 1591SK_U32 PortNumber, /* port whose promiscuous mode changes */ 1592int 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 */ 1673int SkAddrSwap( 1674SK_AC *pAC, /* adapter context */ 1675SK_IOC IoC, /* I/O context */ 1676SK_U32 FromPortNumber, /* Port1 Index */ 1677SK_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