mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 05:11:48 +00:00
5ad887fa8e
This reverts commit e1abecc489
.
The driver works on some hardware that skge doesn't handle yet.
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
1789 lines
49 KiB
C
1789 lines
49 KiB
C
/******************************************************************************
|
|
*
|
|
* Name: skaddr.c
|
|
* Project: Gigabit Ethernet Adapters, ADDR-Module
|
|
* Version: $Revision: 1.52 $
|
|
* Date: $Date: 2003/06/02 13:46:15 $
|
|
* Purpose: Manage Addresses (Multicast and Unicast) and Promiscuous Mode.
|
|
*
|
|
******************************************************************************/
|
|
|
|
/******************************************************************************
|
|
*
|
|
* (C)Copyright 1998-2002 SysKonnect GmbH.
|
|
* (C)Copyright 2002-2003 Marvell.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* The information in this file is provided "AS IS" without warranty.
|
|
*
|
|
******************************************************************************/
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Description:
|
|
*
|
|
* This module is intended to manage multicast addresses, address override,
|
|
* and promiscuous mode on GEnesis and Yukon adapters.
|
|
*
|
|
* Address Layout:
|
|
* port address: physical MAC address
|
|
* 1st exact match: logical MAC address (GEnesis only)
|
|
* 2nd exact match: RLMT multicast (GEnesis only)
|
|
* exact match 3-13: OS-specific multicasts (GEnesis only)
|
|
*
|
|
* Include File Hierarchy:
|
|
*
|
|
* "skdrv1st.h"
|
|
* "skdrv2nd.h"
|
|
*
|
|
******************************************************************************/
|
|
|
|
#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
|
|
static const char SysKonnectFileId[] =
|
|
"@(#) $Id: skaddr.c,v 1.52 2003/06/02 13:46:15 tschilli Exp $ (C) Marvell.";
|
|
#endif /* DEBUG ||!LINT || !SK_SLIM */
|
|
|
|
#define __SKADDR_C
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif /* cplusplus */
|
|
|
|
#include "h/skdrv1st.h"
|
|
#include "h/skdrv2nd.h"
|
|
|
|
/* defines ********************************************************************/
|
|
|
|
|
|
#define XMAC_POLY 0xEDB88320UL /* CRC32-Poly - XMAC: Little Endian */
|
|
#define GMAC_POLY 0x04C11DB7L /* CRC16-Poly - GMAC: Little Endian */
|
|
#define HASH_BITS 6 /* #bits in hash */
|
|
#define SK_MC_BIT 0x01
|
|
|
|
/* Error numbers and messages. */
|
|
|
|
#define SKERR_ADDR_E001 (SK_ERRBASE_ADDR + 0)
|
|
#define SKERR_ADDR_E001MSG "Bad Flags."
|
|
#define SKERR_ADDR_E002 (SKERR_ADDR_E001 + 1)
|
|
#define SKERR_ADDR_E002MSG "New Error."
|
|
|
|
/* typedefs *******************************************************************/
|
|
|
|
/* None. */
|
|
|
|
/* global variables ***********************************************************/
|
|
|
|
/* 64-bit hash values with all bits set. */
|
|
|
|
static const SK_U16 OnesHash[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
|
|
|
|
/* local variables ************************************************************/
|
|
|
|
#ifdef DEBUG
|
|
static int Next0[SK_MAX_MACS] = {0};
|
|
#endif /* DEBUG */
|
|
|
|
static int SkAddrGmacMcAdd(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
|
|
SK_MAC_ADDR *pMc, int Flags);
|
|
static int SkAddrGmacMcClear(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
|
|
int Flags);
|
|
static int SkAddrGmacMcUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber);
|
|
static int SkAddrGmacPromiscuousChange(SK_AC *pAC, SK_IOC IoC,
|
|
SK_U32 PortNumber, int NewPromMode);
|
|
static int SkAddrXmacMcAdd(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
|
|
SK_MAC_ADDR *pMc, int Flags);
|
|
static int SkAddrXmacMcClear(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
|
|
int Flags);
|
|
static int SkAddrXmacMcUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber);
|
|
static int SkAddrXmacPromiscuousChange(SK_AC *pAC, SK_IOC IoC,
|
|
SK_U32 PortNumber, int NewPromMode);
|
|
|
|
/* functions ******************************************************************/
|
|
|
|
/******************************************************************************
|
|
*
|
|
* SkAddrInit - initialize data, set state to init
|
|
*
|
|
* Description:
|
|
*
|
|
* SK_INIT_DATA
|
|
* ============
|
|
*
|
|
* This routine clears the multicast tables and resets promiscuous mode.
|
|
* Some entries are reserved for the "logical MAC address", the
|
|
* SK-RLMT multicast address, and the BPDU multicast address.
|
|
*
|
|
*
|
|
* SK_INIT_IO
|
|
* ==========
|
|
*
|
|
* All permanent MAC addresses are read from EPROM.
|
|
* If the current MAC addresses are not already set in software,
|
|
* they are set to the values of the permanent addresses.
|
|
* The current addresses are written to the corresponding MAC.
|
|
*
|
|
*
|
|
* SK_INIT_RUN
|
|
* ===========
|
|
*
|
|
* Nothing.
|
|
*
|
|
* Context:
|
|
* init, pageable
|
|
*
|
|
* Returns:
|
|
* SK_ADDR_SUCCESS
|
|
*/
|
|
int SkAddrInit(
|
|
SK_AC *pAC, /* the adapter context */
|
|
SK_IOC IoC, /* I/O context */
|
|
int Level) /* initialization level */
|
|
{
|
|
int j;
|
|
SK_U32 i;
|
|
SK_U8 *InAddr;
|
|
SK_U16 *OutAddr;
|
|
SK_ADDR_PORT *pAPort;
|
|
|
|
switch (Level) {
|
|
case SK_INIT_DATA:
|
|
SK_MEMSET((char *) &pAC->Addr, (SK_U8) 0,
|
|
(SK_U16) sizeof(SK_ADDR));
|
|
|
|
for (i = 0; i < SK_MAX_MACS; i++) {
|
|
pAPort = &pAC->Addr.Port[i];
|
|
pAPort->PromMode = SK_PROM_MODE_NONE;
|
|
|
|
pAPort->FirstExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
|
|
pAPort->FirstExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
|
|
pAPort->NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
|
|
pAPort->NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
|
|
}
|
|
#ifdef xDEBUG
|
|
for (i = 0; i < SK_MAX_MACS; i++) {
|
|
if (pAC->Addr.Port[i].NextExactMatchRlmt <
|
|
SK_ADDR_FIRST_MATCH_RLMT) {
|
|
Next0[i] |= 4;
|
|
}
|
|
}
|
|
#endif /* DEBUG */
|
|
/* pAC->Addr.InitDone = SK_INIT_DATA; */
|
|
break;
|
|
|
|
case SK_INIT_IO:
|
|
#ifndef SK_NO_RLMT
|
|
for (i = 0; i < SK_MAX_NETS; i++) {
|
|
pAC->Addr.Net[i].ActivePort = pAC->Rlmt.Net[i].ActivePort;
|
|
}
|
|
#endif /* !SK_NO_RLMT */
|
|
#ifdef xDEBUG
|
|
for (i = 0; i < SK_MAX_MACS; i++) {
|
|
if (pAC->Addr.Port[i].NextExactMatchRlmt <
|
|
SK_ADDR_FIRST_MATCH_RLMT) {
|
|
Next0[i] |= 8;
|
|
}
|
|
}
|
|
#endif /* DEBUG */
|
|
|
|
/* Read permanent logical MAC address from Control Register File. */
|
|
for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
|
|
InAddr = (SK_U8 *) &pAC->Addr.Net[0].PermanentMacAddress.a[j];
|
|
SK_IN8(IoC, B2_MAC_1 + j, InAddr);
|
|
}
|
|
|
|
if (!pAC->Addr.Net[0].CurrentMacAddressSet) {
|
|
/* Set the current logical MAC address to the permanent one. */
|
|
pAC->Addr.Net[0].CurrentMacAddress =
|
|
pAC->Addr.Net[0].PermanentMacAddress;
|
|
pAC->Addr.Net[0].CurrentMacAddressSet = SK_TRUE;
|
|
}
|
|
|
|
/* Set the current logical MAC address. */
|
|
pAC->Addr.Port[pAC->Addr.Net[0].ActivePort].Exact[0] =
|
|
pAC->Addr.Net[0].CurrentMacAddress;
|
|
#if SK_MAX_NETS > 1
|
|
/* Set logical MAC address for net 2 to (log | 3). */
|
|
if (!pAC->Addr.Net[1].CurrentMacAddressSet) {
|
|
pAC->Addr.Net[1].PermanentMacAddress =
|
|
pAC->Addr.Net[0].PermanentMacAddress;
|
|
pAC->Addr.Net[1].PermanentMacAddress.a[5] |= 3;
|
|
/* Set the current logical MAC address to the permanent one. */
|
|
pAC->Addr.Net[1].CurrentMacAddress =
|
|
pAC->Addr.Net[1].PermanentMacAddress;
|
|
pAC->Addr.Net[1].CurrentMacAddressSet = SK_TRUE;
|
|
}
|
|
#endif /* SK_MAX_NETS > 1 */
|
|
|
|
#ifdef DEBUG
|
|
for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
|
|
SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
|
|
("Permanent MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
|
|
i,
|
|
pAC->Addr.Net[i].PermanentMacAddress.a[0],
|
|
pAC->Addr.Net[i].PermanentMacAddress.a[1],
|
|
pAC->Addr.Net[i].PermanentMacAddress.a[2],
|
|
pAC->Addr.Net[i].PermanentMacAddress.a[3],
|
|
pAC->Addr.Net[i].PermanentMacAddress.a[4],
|
|
pAC->Addr.Net[i].PermanentMacAddress.a[5]))
|
|
|
|
SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
|
|
("Logical MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
|
|
i,
|
|
pAC->Addr.Net[i].CurrentMacAddress.a[0],
|
|
pAC->Addr.Net[i].CurrentMacAddress.a[1],
|
|
pAC->Addr.Net[i].CurrentMacAddress.a[2],
|
|
pAC->Addr.Net[i].CurrentMacAddress.a[3],
|
|
pAC->Addr.Net[i].CurrentMacAddress.a[4],
|
|
pAC->Addr.Net[i].CurrentMacAddress.a[5]))
|
|
}
|
|
#endif /* DEBUG */
|
|
|
|
for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
|
|
pAPort = &pAC->Addr.Port[i];
|
|
|
|
/* Read permanent port addresses from Control Register File. */
|
|
for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
|
|
InAddr = (SK_U8 *) &pAPort->PermanentMacAddress.a[j];
|
|
SK_IN8(IoC, B2_MAC_2 + 8 * i + j, InAddr);
|
|
}
|
|
|
|
if (!pAPort->CurrentMacAddressSet) {
|
|
/*
|
|
* Set the current and previous physical MAC address
|
|
* of this port to its permanent MAC address.
|
|
*/
|
|
pAPort->CurrentMacAddress = pAPort->PermanentMacAddress;
|
|
pAPort->PreviousMacAddress = pAPort->PermanentMacAddress;
|
|
pAPort->CurrentMacAddressSet = SK_TRUE;
|
|
}
|
|
|
|
/* Set port's current physical MAC address. */
|
|
OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
|
|
#ifdef GENESIS
|
|
if (pAC->GIni.GIGenesis) {
|
|
XM_OUTADDR(IoC, i, XM_SA, OutAddr);
|
|
}
|
|
#endif /* GENESIS */
|
|
#ifdef YUKON
|
|
if (!pAC->GIni.GIGenesis) {
|
|
GM_OUTADDR(IoC, i, GM_SRC_ADDR_1L, OutAddr);
|
|
}
|
|
#endif /* YUKON */
|
|
#ifdef DEBUG
|
|
SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
|
|
("SkAddrInit: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
|
|
pAPort->PermanentMacAddress.a[0],
|
|
pAPort->PermanentMacAddress.a[1],
|
|
pAPort->PermanentMacAddress.a[2],
|
|
pAPort->PermanentMacAddress.a[3],
|
|
pAPort->PermanentMacAddress.a[4],
|
|
pAPort->PermanentMacAddress.a[5]))
|
|
|
|
SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
|
|
("SkAddrInit: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
|
|
pAPort->CurrentMacAddress.a[0],
|
|
pAPort->CurrentMacAddress.a[1],
|
|
pAPort->CurrentMacAddress.a[2],
|
|
pAPort->CurrentMacAddress.a[3],
|
|
pAPort->CurrentMacAddress.a[4],
|
|
pAPort->CurrentMacAddress.a[5]))
|
|
#endif /* DEBUG */
|
|
}
|
|
/* pAC->Addr.InitDone = SK_INIT_IO; */
|
|
break;
|
|
|
|
case SK_INIT_RUN:
|
|
#ifdef xDEBUG
|
|
for (i = 0; i < SK_MAX_MACS; i++) {
|
|
if (pAC->Addr.Port[i].NextExactMatchRlmt <
|
|
SK_ADDR_FIRST_MATCH_RLMT) {
|
|
Next0[i] |= 16;
|
|
}
|
|
}
|
|
#endif /* DEBUG */
|
|
|
|
/* pAC->Addr.InitDone = SK_INIT_RUN; */
|
|
break;
|
|
|
|
default: /* error */
|
|
break;
|
|
}
|
|
|
|
return (SK_ADDR_SUCCESS);
|
|
|
|
} /* SkAddrInit */
|
|
|
|
#ifndef SK_SLIM
|
|
|
|
/******************************************************************************
|
|
*
|
|
* SkAddrMcClear - clear the multicast table
|
|
*
|
|
* Description:
|
|
* This routine clears the multicast table.
|
|
*
|
|
* If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
|
|
* immediately.
|
|
*
|
|
* It calls either SkAddrXmacMcClear or SkAddrGmacMcClear, according
|
|
* to the adapter in use. The real work is done there.
|
|
*
|
|
* Context:
|
|
* runtime, pageable
|
|
* may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
|
|
* may be called after SK_INIT_IO without limitation
|
|
*
|
|
* Returns:
|
|
* SK_ADDR_SUCCESS
|
|
* SK_ADDR_ILLEGAL_PORT
|
|
*/
|
|
int SkAddrMcClear(
|
|
SK_AC *pAC, /* adapter context */
|
|
SK_IOC IoC, /* I/O context */
|
|
SK_U32 PortNumber, /* Index of affected port */
|
|
int Flags) /* permanent/non-perm, sw-only */
|
|
{
|
|
int ReturnCode;
|
|
|
|
if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
|
|
return (SK_ADDR_ILLEGAL_PORT);
|
|
}
|
|
|
|
if (pAC->GIni.GIGenesis) {
|
|
ReturnCode = SkAddrXmacMcClear(pAC, IoC, PortNumber, Flags);
|
|
}
|
|
else {
|
|
ReturnCode = SkAddrGmacMcClear(pAC, IoC, PortNumber, Flags);
|
|
}
|
|
|
|
return (ReturnCode);
|
|
|
|
} /* SkAddrMcClear */
|
|
|
|
#endif /* !SK_SLIM */
|
|
|
|
#ifndef SK_SLIM
|
|
|
|
/******************************************************************************
|
|
*
|
|
* SkAddrXmacMcClear - clear the multicast table
|
|
*
|
|
* Description:
|
|
* This routine clears the multicast table
|
|
* (either entry 2 or entries 3-16 and InexactFilter) of the given port.
|
|
* If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
|
|
* immediately.
|
|
*
|
|
* Context:
|
|
* runtime, pageable
|
|
* may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
|
|
* may be called after SK_INIT_IO without limitation
|
|
*
|
|
* Returns:
|
|
* SK_ADDR_SUCCESS
|
|
* SK_ADDR_ILLEGAL_PORT
|
|
*/
|
|
static int SkAddrXmacMcClear(
|
|
SK_AC *pAC, /* adapter context */
|
|
SK_IOC IoC, /* I/O context */
|
|
SK_U32 PortNumber, /* Index of affected port */
|
|
int Flags) /* permanent/non-perm, sw-only */
|
|
{
|
|
int i;
|
|
|
|
if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
|
|
|
|
/* Clear RLMT multicast addresses. */
|
|
pAC->Addr.Port[PortNumber].NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
|
|
}
|
|
else { /* not permanent => DRV */
|
|
|
|
/* Clear InexactFilter */
|
|
for (i = 0; i < 8; i++) {
|
|
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
|
|
}
|
|
|
|
/* Clear DRV multicast addresses. */
|
|
|
|
pAC->Addr.Port[PortNumber].NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
|
|
}
|
|
|
|
if (!(Flags & SK_MC_SW_ONLY)) {
|
|
(void) SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
|
|
}
|
|
|
|
return (SK_ADDR_SUCCESS);
|
|
|
|
} /* SkAddrXmacMcClear */
|
|
|
|
#endif /* !SK_SLIM */
|
|
|
|
#ifndef SK_SLIM
|
|
|
|
/******************************************************************************
|
|
*
|
|
* SkAddrGmacMcClear - clear the multicast table
|
|
*
|
|
* Description:
|
|
* This routine clears the multicast hashing table (InexactFilter)
|
|
* (either the RLMT or the driver bits) of the given port.
|
|
*
|
|
* If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
|
|
* immediately.
|
|
*
|
|
* Context:
|
|
* runtime, pageable
|
|
* may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
|
|
* may be called after SK_INIT_IO without limitation
|
|
*
|
|
* Returns:
|
|
* SK_ADDR_SUCCESS
|
|
* SK_ADDR_ILLEGAL_PORT
|
|
*/
|
|
static int SkAddrGmacMcClear(
|
|
SK_AC *pAC, /* adapter context */
|
|
SK_IOC IoC, /* I/O context */
|
|
SK_U32 PortNumber, /* Index of affected port */
|
|
int Flags) /* permanent/non-perm, sw-only */
|
|
{
|
|
int i;
|
|
|
|
#ifdef DEBUG
|
|
SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
|
|
("GMAC InexactFilter (not cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
|
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0],
|
|
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1],
|
|
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2],
|
|
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3],
|
|
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
|
|
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
|
|
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
|
|
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]))
|
|
#endif /* DEBUG */
|
|
|
|
/* Clear InexactFilter */
|
|
for (i = 0; i < 8; i++) {
|
|
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
|
|
}
|
|
|
|
if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
|
|
|
|
/* Copy DRV bits to InexactFilter. */
|
|
for (i = 0; i < 8; i++) {
|
|
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
|
|
pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
|
|
|
|
/* Clear InexactRlmtFilter. */
|
|
pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i] = 0;
|
|
|
|
}
|
|
}
|
|
else { /* not permanent => DRV */
|
|
|
|
/* Copy RLMT bits to InexactFilter. */
|
|
for (i = 0; i < 8; i++) {
|
|
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
|
|
pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
|
|
|
|
/* Clear InexactDrvFilter. */
|
|
pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i] = 0;
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
|
|
("GMAC InexactFilter (cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
|
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0],
|
|
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1],
|
|
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2],
|
|
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3],
|
|
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
|
|
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
|
|
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
|
|
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]))
|
|
#endif /* DEBUG */
|
|
|
|
if (!(Flags & SK_MC_SW_ONLY)) {
|
|
(void) SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
|
|
}
|
|
|
|
return (SK_ADDR_SUCCESS);
|
|
|
|
} /* SkAddrGmacMcClear */
|
|
|
|
#ifndef SK_ADDR_CHEAT
|
|
|
|
/******************************************************************************
|
|
*
|
|
* SkXmacMcHash - hash multicast address
|
|
*
|
|
* Description:
|
|
* This routine computes the hash value for a multicast address.
|
|
* A CRC32 algorithm is used.
|
|
*
|
|
* Notes:
|
|
* The code was adapted from the XaQti data sheet.
|
|
*
|
|
* Context:
|
|
* runtime, pageable
|
|
*
|
|
* Returns:
|
|
* Hash value of multicast address.
|
|
*/
|
|
static SK_U32 SkXmacMcHash(
|
|
unsigned char *pMc) /* Multicast address */
|
|
{
|
|
SK_U32 Idx;
|
|
SK_U32 Bit;
|
|
SK_U32 Data;
|
|
SK_U32 Crc;
|
|
|
|
Crc = 0xFFFFFFFFUL;
|
|
for (Idx = 0; Idx < SK_MAC_ADDR_LEN; Idx++) {
|
|
Data = *pMc++;
|
|
for (Bit = 0; Bit < 8; Bit++, Data >>= 1) {
|
|
Crc = (Crc >> 1) ^ (((Crc ^ Data) & 1) ? XMAC_POLY : 0);
|
|
}
|
|
}
|
|
|
|
return (Crc & ((1 << HASH_BITS) - 1));
|
|
|
|
} /* SkXmacMcHash */
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* SkGmacMcHash - hash multicast address
|
|
*
|
|
* Description:
|
|
* This routine computes the hash value for a multicast address.
|
|
* A CRC16 algorithm is used.
|
|
*
|
|
* Notes:
|
|
*
|
|
*
|
|
* Context:
|
|
* runtime, pageable
|
|
*
|
|
* Returns:
|
|
* Hash value of multicast address.
|
|
*/
|
|
static SK_U32 SkGmacMcHash(
|
|
unsigned char *pMc) /* Multicast address */
|
|
{
|
|
SK_U32 Data;
|
|
SK_U32 TmpData;
|
|
SK_U32 Crc;
|
|
int Byte;
|
|
int Bit;
|
|
|
|
Crc = 0xFFFFFFFFUL;
|
|
for (Byte = 0; Byte < 6; Byte++) {
|
|
/* Get next byte. */
|
|
Data = (SK_U32) pMc[Byte];
|
|
|
|
/* Change bit order in byte. */
|
|
TmpData = Data;
|
|
for (Bit = 0; Bit < 8; Bit++) {
|
|
if (TmpData & 1L) {
|
|
Data |= 1L << (7 - Bit);
|
|
}
|
|
else {
|
|
Data &= ~(1L << (7 - Bit));
|
|
}
|
|
TmpData >>= 1;
|
|
}
|
|
|
|
Crc ^= (Data << 24);
|
|
for (Bit = 0; Bit < 8; Bit++) {
|
|
if (Crc & 0x80000000) {
|
|
Crc = (Crc << 1) ^ GMAC_POLY;
|
|
}
|
|
else {
|
|
Crc <<= 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return (Crc & ((1 << HASH_BITS) - 1));
|
|
|
|
} /* SkGmacMcHash */
|
|
|
|
#endif /* !SK_ADDR_CHEAT */
|
|
|
|
/******************************************************************************
|
|
*
|
|
* SkAddrMcAdd - add a multicast address to a port
|
|
*
|
|
* Description:
|
|
* This routine enables reception for a given address on the given port.
|
|
*
|
|
* It calls either SkAddrXmacMcAdd or SkAddrGmacMcAdd, according to the
|
|
* adapter in use. The real work is done there.
|
|
*
|
|
* Notes:
|
|
* The return code is only valid for SK_PROM_MODE_NONE.
|
|
*
|
|
* Context:
|
|
* runtime, pageable
|
|
* may be called after SK_INIT_DATA
|
|
*
|
|
* Returns:
|
|
* SK_MC_FILTERING_EXACT
|
|
* SK_MC_FILTERING_INEXACT
|
|
* SK_MC_ILLEGAL_ADDRESS
|
|
* SK_MC_ILLEGAL_PORT
|
|
* SK_MC_RLMT_OVERFLOW
|
|
*/
|
|
int SkAddrMcAdd(
|
|
SK_AC *pAC, /* adapter context */
|
|
SK_IOC IoC, /* I/O context */
|
|
SK_U32 PortNumber, /* Port Number */
|
|
SK_MAC_ADDR *pMc, /* multicast address to be added */
|
|
int Flags) /* permanent/non-permanent */
|
|
{
|
|
int ReturnCode;
|
|
|
|
if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
|
|
return (SK_ADDR_ILLEGAL_PORT);
|
|
}
|
|
|
|
if (pAC->GIni.GIGenesis) {
|
|
ReturnCode = SkAddrXmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
|
|
}
|
|
else {
|
|
ReturnCode = SkAddrGmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
|
|
}
|
|
|
|
return (ReturnCode);
|
|
|
|
} /* SkAddrMcAdd */
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* SkAddrXmacMcAdd - add a multicast address to a port
|
|
*
|
|
* Description:
|
|
* This routine enables reception for a given address on the given port.
|
|
*
|
|
* Notes:
|
|
* The return code is only valid for SK_PROM_MODE_NONE.
|
|
*
|
|
* The multicast bit is only checked if there are no free exact match
|
|
* entries.
|
|
*
|
|
* Context:
|
|
* runtime, pageable
|
|
* may be called after SK_INIT_DATA
|
|
*
|
|
* Returns:
|
|
* SK_MC_FILTERING_EXACT
|
|
* SK_MC_FILTERING_INEXACT
|
|
* SK_MC_ILLEGAL_ADDRESS
|
|
* SK_MC_RLMT_OVERFLOW
|
|
*/
|
|
static int SkAddrXmacMcAdd(
|
|
SK_AC *pAC, /* adapter context */
|
|
SK_IOC IoC, /* I/O context */
|
|
SK_U32 PortNumber, /* Port Number */
|
|
SK_MAC_ADDR *pMc, /* multicast address to be added */
|
|
int Flags) /* permanent/non-permanent */
|
|
{
|
|
int i;
|
|
SK_U8 Inexact;
|
|
#ifndef SK_ADDR_CHEAT
|
|
SK_U32 HashBit;
|
|
#endif /* !defined(SK_ADDR_CHEAT) */
|
|
|
|
if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
|
|
#ifdef xDEBUG
|
|
if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt <
|
|
SK_ADDR_FIRST_MATCH_RLMT) {
|
|
Next0[PortNumber] |= 1;
|
|
return (SK_MC_RLMT_OVERFLOW);
|
|
}
|
|
#endif /* DEBUG */
|
|
|
|
if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt >
|
|
SK_ADDR_LAST_MATCH_RLMT) {
|
|
return (SK_MC_RLMT_OVERFLOW);
|
|
}
|
|
|
|
/* Set a RLMT multicast address. */
|
|
|
|
pAC->Addr.Port[PortNumber].Exact[
|
|
pAC->Addr.Port[PortNumber].NextExactMatchRlmt++] = *pMc;
|
|
|
|
return (SK_MC_FILTERING_EXACT);
|
|
}
|
|
|
|
#ifdef xDEBUG
|
|
if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <
|
|
SK_ADDR_FIRST_MATCH_DRV) {
|
|
Next0[PortNumber] |= 2;
|
|
return (SK_MC_RLMT_OVERFLOW);
|
|
}
|
|
#endif /* DEBUG */
|
|
|
|
if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
|
|
|
|
/* Set exact match entry. */
|
|
pAC->Addr.Port[PortNumber].Exact[
|
|
pAC->Addr.Port[PortNumber].NextExactMatchDrv++] = *pMc;
|
|
|
|
/* Clear InexactFilter */
|
|
for (i = 0; i < 8; i++) {
|
|
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
|
|
}
|
|
}
|
|
else {
|
|
if (!(pMc->a[0] & SK_MC_BIT)) {
|
|
/* Hashing only possible with multicast addresses */
|
|
return (SK_MC_ILLEGAL_ADDRESS);
|
|
}
|
|
#ifndef SK_ADDR_CHEAT
|
|
/* Compute hash value of address. */
|
|
HashBit = 63 - SkXmacMcHash(&pMc->a[0]);
|
|
|
|
/* Add bit to InexactFilter. */
|
|
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[HashBit / 8] |=
|
|
1 << (HashBit % 8);
|
|
#else /* SK_ADDR_CHEAT */
|
|
/* Set all bits in InexactFilter. */
|
|
for (i = 0; i < 8; i++) {
|
|
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
|
|
}
|
|
#endif /* SK_ADDR_CHEAT */
|
|
}
|
|
|
|
for (Inexact = 0, i = 0; i < 8; i++) {
|
|
Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
|
|
}
|
|
|
|
if (Inexact == 0 && pAC->Addr.Port[PortNumber].PromMode == 0) {
|
|
return (SK_MC_FILTERING_EXACT);
|
|
}
|
|
else {
|
|
return (SK_MC_FILTERING_INEXACT);
|
|
}
|
|
|
|
} /* SkAddrXmacMcAdd */
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* SkAddrGmacMcAdd - add a multicast address to a port
|
|
*
|
|
* Description:
|
|
* This routine enables reception for a given address on the given port.
|
|
*
|
|
* Notes:
|
|
* The return code is only valid for SK_PROM_MODE_NONE.
|
|
*
|
|
* Context:
|
|
* runtime, pageable
|
|
* may be called after SK_INIT_DATA
|
|
*
|
|
* Returns:
|
|
* SK_MC_FILTERING_INEXACT
|
|
* SK_MC_ILLEGAL_ADDRESS
|
|
*/
|
|
static int SkAddrGmacMcAdd(
|
|
SK_AC *pAC, /* adapter context */
|
|
SK_IOC IoC, /* I/O context */
|
|
SK_U32 PortNumber, /* Port Number */
|
|
SK_MAC_ADDR *pMc, /* multicast address to be added */
|
|
int Flags) /* permanent/non-permanent */
|
|
{
|
|
int i;
|
|
#ifndef SK_ADDR_CHEAT
|
|
SK_U32 HashBit;
|
|
#endif /* !defined(SK_ADDR_CHEAT) */
|
|
|
|
if (!(pMc->a[0] & SK_MC_BIT)) {
|
|
/* Hashing only possible with multicast addresses */
|
|
return (SK_MC_ILLEGAL_ADDRESS);
|
|
}
|
|
|
|
#ifndef SK_ADDR_CHEAT
|
|
|
|
/* Compute hash value of address. */
|
|
HashBit = SkGmacMcHash(&pMc->a[0]);
|
|
|
|
if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
|
|
|
|
/* Add bit to InexactRlmtFilter. */
|
|
pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[HashBit / 8] |=
|
|
1 << (HashBit % 8);
|
|
|
|
/* Copy bit to InexactFilter. */
|
|
for (i = 0; i < 8; i++) {
|
|
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
|
|
pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
|
|
}
|
|
#ifdef DEBUG
|
|
SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
|
|
("GMAC InexactRlmtFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
|
pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[0],
|
|
pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[1],
|
|
pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[2],
|
|
pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[3],
|
|
pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[4],
|
|
pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[5],
|
|
pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[6],
|
|
pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[7]))
|
|
#endif /* DEBUG */
|
|
}
|
|
else { /* not permanent => DRV */
|
|
|
|
/* Add bit to InexactDrvFilter. */
|
|
pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[HashBit / 8] |=
|
|
1 << (HashBit % 8);
|
|
|
|
/* Copy bit to InexactFilter. */
|
|
for (i = 0; i < 8; i++) {
|
|
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
|
|
pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
|
|
}
|
|
#ifdef DEBUG
|
|
SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
|
|
("GMAC InexactDrvFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
|
pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[0],
|
|
pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[1],
|
|
pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[2],
|
|
pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[3],
|
|
pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[4],
|
|
pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[5],
|
|
pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[6],
|
|
pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[7]))
|
|
#endif /* DEBUG */
|
|
}
|
|
|
|
#else /* SK_ADDR_CHEAT */
|
|
|
|
/* Set all bits in InexactFilter. */
|
|
for (i = 0; i < 8; i++) {
|
|
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
|
|
}
|
|
#endif /* SK_ADDR_CHEAT */
|
|
|
|
return (SK_MC_FILTERING_INEXACT);
|
|
|
|
} /* SkAddrGmacMcAdd */
|
|
|
|
#endif /* !SK_SLIM */
|
|
|
|
/******************************************************************************
|
|
*
|
|
* SkAddrMcUpdate - update the HW MC address table and set the MAC address
|
|
*
|
|
* Description:
|
|
* This routine enables reception of the addresses contained in a local
|
|
* table for a given port.
|
|
* It also programs the port's current physical MAC address.
|
|
*
|
|
* It calls either SkAddrXmacMcUpdate or SkAddrGmacMcUpdate, according
|
|
* to the adapter in use. The real work is done there.
|
|
*
|
|
* Notes:
|
|
* The return code is only valid for SK_PROM_MODE_NONE.
|
|
*
|
|
* Context:
|
|
* runtime, pageable
|
|
* may be called after SK_INIT_IO
|
|
*
|
|
* Returns:
|
|
* SK_MC_FILTERING_EXACT
|
|
* SK_MC_FILTERING_INEXACT
|
|
* SK_ADDR_ILLEGAL_PORT
|
|
*/
|
|
int SkAddrMcUpdate(
|
|
SK_AC *pAC, /* adapter context */
|
|
SK_IOC IoC, /* I/O context */
|
|
SK_U32 PortNumber) /* Port Number */
|
|
{
|
|
int ReturnCode = 0;
|
|
#if (!defined(SK_SLIM) || defined(DEBUG))
|
|
if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
|
|
return (SK_ADDR_ILLEGAL_PORT);
|
|
}
|
|
#endif /* !SK_SLIM || DEBUG */
|
|
|
|
#ifdef GENESIS
|
|
if (pAC->GIni.GIGenesis) {
|
|
ReturnCode = SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
|
|
}
|
|
#endif /* GENESIS */
|
|
#ifdef YUKON
|
|
if (!pAC->GIni.GIGenesis) {
|
|
ReturnCode = SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
|
|
}
|
|
#endif /* YUKON */
|
|
return (ReturnCode);
|
|
|
|
} /* SkAddrMcUpdate */
|
|
|
|
|
|
#ifdef GENESIS
|
|
|
|
/******************************************************************************
|
|
*
|
|
* SkAddrXmacMcUpdate - update the HW MC address table and set the MAC address
|
|
*
|
|
* Description:
|
|
* This routine enables reception of the addresses contained in a local
|
|
* table for a given port.
|
|
* It also programs the port's current physical MAC address.
|
|
*
|
|
* Notes:
|
|
* The return code is only valid for SK_PROM_MODE_NONE.
|
|
*
|
|
* Context:
|
|
* runtime, pageable
|
|
* may be called after SK_INIT_IO
|
|
*
|
|
* Returns:
|
|
* SK_MC_FILTERING_EXACT
|
|
* SK_MC_FILTERING_INEXACT
|
|
* SK_ADDR_ILLEGAL_PORT
|
|
*/
|
|
static int SkAddrXmacMcUpdate(
|
|
SK_AC *pAC, /* adapter context */
|
|
SK_IOC IoC, /* I/O context */
|
|
SK_U32 PortNumber) /* Port Number */
|
|
{
|
|
SK_U32 i;
|
|
SK_U8 Inexact;
|
|
SK_U16 *OutAddr;
|
|
SK_ADDR_PORT *pAPort;
|
|
|
|
SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
|
|
("SkAddrXmacMcUpdate on Port %u.\n", PortNumber))
|
|
|
|
pAPort = &pAC->Addr.Port[PortNumber];
|
|
|
|
#ifdef DEBUG
|
|
SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
|
|
("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
|
|
#endif /* DEBUG */
|
|
|
|
/* Start with 0 to also program the logical MAC address. */
|
|
for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
|
|
/* Set exact match address i on XMAC */
|
|
OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
|
|
XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
|
|
}
|
|
|
|
/* Clear other permanent exact match addresses on XMAC */
|
|
if (pAPort->NextExactMatchRlmt <= SK_ADDR_LAST_MATCH_RLMT) {
|
|
|
|
SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchRlmt,
|
|
SK_ADDR_LAST_MATCH_RLMT);
|
|
}
|
|
|
|
for (i = pAPort->FirstExactMatchDrv; i < pAPort->NextExactMatchDrv; i++) {
|
|
OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
|
|
XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
|
|
}
|
|
|
|
/* Clear other non-permanent exact match addresses on XMAC */
|
|
if (pAPort->NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
|
|
|
|
SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchDrv,
|
|
SK_ADDR_LAST_MATCH_DRV);
|
|
}
|
|
|
|
for (Inexact = 0, i = 0; i < 8; i++) {
|
|
Inexact |= pAPort->InexactFilter.Bytes[i];
|
|
}
|
|
|
|
if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
|
|
|
|
/* Set all bits in 64-bit hash register. */
|
|
XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
|
|
|
|
/* Enable Hashing */
|
|
SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
|
|
}
|
|
else if (Inexact != 0) {
|
|
|
|
/* Set 64-bit hash register to InexactFilter. */
|
|
XM_OUTHASH(IoC, PortNumber, XM_HSM, &pAPort->InexactFilter.Bytes[0]);
|
|
|
|
/* Enable Hashing */
|
|
SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
|
|
}
|
|
else {
|
|
/* Disable Hashing */
|
|
SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE);
|
|
}
|
|
|
|
if (pAPort->PromMode != SK_PROM_MODE_NONE) {
|
|
(void) SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
|
|
}
|
|
|
|
/* Set port's current physical MAC address. */
|
|
OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
|
|
|
|
XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
|
|
|
|
#ifdef xDEBUG
|
|
for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
|
|
SK_U8 InAddr8[6];
|
|
SK_U16 *InAddr;
|
|
|
|
/* Get exact match address i from port PortNumber. */
|
|
InAddr = (SK_U16 *) &InAddr8[0];
|
|
|
|
XM_INADDR(IoC, PortNumber, XM_EXM(i), InAddr);
|
|
|
|
SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
|
|
("SkAddrXmacMcUpdate: MC address %d on Port %u: ",
|
|
"%02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x\n",
|
|
i,
|
|
PortNumber,
|
|
InAddr8[0],
|
|
InAddr8[1],
|
|
InAddr8[2],
|
|
InAddr8[3],
|
|
InAddr8[4],
|
|
InAddr8[5],
|
|
pAPort->Exact[i].a[0],
|
|
pAPort->Exact[i].a[1],
|
|
pAPort->Exact[i].a[2],
|
|
pAPort->Exact[i].a[3],
|
|
pAPort->Exact[i].a[4],
|
|
pAPort->Exact[i].a[5]))
|
|
}
|
|
#endif /* DEBUG */
|
|
|
|
/* Determine return value. */
|
|
if (Inexact == 0 && pAPort->PromMode == 0) {
|
|
return (SK_MC_FILTERING_EXACT);
|
|
}
|
|
else {
|
|
return (SK_MC_FILTERING_INEXACT);
|
|
}
|
|
|
|
} /* SkAddrXmacMcUpdate */
|
|
|
|
#endif /* GENESIS */
|
|
|
|
#ifdef YUKON
|
|
|
|
/******************************************************************************
|
|
*
|
|
* SkAddrGmacMcUpdate - update the HW MC address table and set the MAC address
|
|
*
|
|
* Description:
|
|
* This routine enables reception of the addresses contained in a local
|
|
* table for a given port.
|
|
* It also programs the port's current physical MAC address.
|
|
*
|
|
* Notes:
|
|
* The return code is only valid for SK_PROM_MODE_NONE.
|
|
*
|
|
* Context:
|
|
* runtime, pageable
|
|
* may be called after SK_INIT_IO
|
|
*
|
|
* Returns:
|
|
* SK_MC_FILTERING_EXACT
|
|
* SK_MC_FILTERING_INEXACT
|
|
* SK_ADDR_ILLEGAL_PORT
|
|
*/
|
|
static int SkAddrGmacMcUpdate(
|
|
SK_AC *pAC, /* adapter context */
|
|
SK_IOC IoC, /* I/O context */
|
|
SK_U32 PortNumber) /* Port Number */
|
|
{
|
|
#ifndef SK_SLIM
|
|
SK_U32 i;
|
|
SK_U8 Inexact;
|
|
#endif /* not SK_SLIM */
|
|
SK_U16 *OutAddr;
|
|
SK_ADDR_PORT *pAPort;
|
|
|
|
SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
|
|
("SkAddrGmacMcUpdate on Port %u.\n", PortNumber))
|
|
|
|
pAPort = &pAC->Addr.Port[PortNumber];
|
|
|
|
#ifdef DEBUG
|
|
SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
|
|
("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
|
|
#endif /* DEBUG */
|
|
|
|
#ifndef SK_SLIM
|
|
for (Inexact = 0, i = 0; i < 8; i++) {
|
|
Inexact |= pAPort->InexactFilter.Bytes[i];
|
|
}
|
|
|
|
/* Set 64-bit hash register to InexactFilter. */
|
|
GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1,
|
|
&pAPort->InexactFilter.Bytes[0]);
|
|
|
|
if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
|
|
|
|
/* Set all bits in 64-bit hash register. */
|
|
GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
|
|
|
|
/* Enable Hashing */
|
|
SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
|
|
}
|
|
else {
|
|
/* Enable Hashing. */
|
|
SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
|
|
}
|
|
|
|
if (pAPort->PromMode != SK_PROM_MODE_NONE) {
|
|
(void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
|
|
}
|
|
#else /* SK_SLIM */
|
|
|
|
/* Set all bits in 64-bit hash register. */
|
|
GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
|
|
|
|
/* Enable Hashing */
|
|
SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
|
|
|
|
(void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
|
|
|
|
#endif /* SK_SLIM */
|
|
|
|
/* Set port's current physical MAC address. */
|
|
OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
|
|
GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
|
|
|
|
/* Set port's current logical MAC address. */
|
|
OutAddr = (SK_U16 *) &pAPort->Exact[0].a[0];
|
|
GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_2L, OutAddr);
|
|
|
|
#ifdef DEBUG
|
|
SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
|
|
("SkAddrGmacMcUpdate: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
|
|
pAPort->Exact[0].a[0],
|
|
pAPort->Exact[0].a[1],
|
|
pAPort->Exact[0].a[2],
|
|
pAPort->Exact[0].a[3],
|
|
pAPort->Exact[0].a[4],
|
|
pAPort->Exact[0].a[5]))
|
|
|
|
SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
|
|
("SkAddrGmacMcUpdate: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
|
|
pAPort->CurrentMacAddress.a[0],
|
|
pAPort->CurrentMacAddress.a[1],
|
|
pAPort->CurrentMacAddress.a[2],
|
|
pAPort->CurrentMacAddress.a[3],
|
|
pAPort->CurrentMacAddress.a[4],
|
|
pAPort->CurrentMacAddress.a[5]))
|
|
#endif /* DEBUG */
|
|
|
|
#ifndef SK_SLIM
|
|
/* Determine return value. */
|
|
if (Inexact == 0 && pAPort->PromMode == 0) {
|
|
return (SK_MC_FILTERING_EXACT);
|
|
}
|
|
else {
|
|
return (SK_MC_FILTERING_INEXACT);
|
|
}
|
|
#else /* SK_SLIM */
|
|
return (SK_MC_FILTERING_INEXACT);
|
|
#endif /* SK_SLIM */
|
|
|
|
} /* SkAddrGmacMcUpdate */
|
|
|
|
#endif /* YUKON */
|
|
|
|
#ifndef SK_NO_MAO
|
|
|
|
/******************************************************************************
|
|
*
|
|
* SkAddrOverride - override a port's MAC address
|
|
*
|
|
* Description:
|
|
* This routine overrides the MAC address of one port.
|
|
*
|
|
* Context:
|
|
* runtime, pageable
|
|
* may be called after SK_INIT_IO
|
|
*
|
|
* Returns:
|
|
* SK_ADDR_SUCCESS if successful.
|
|
* SK_ADDR_DUPLICATE_ADDRESS if duplicate MAC address.
|
|
* SK_ADDR_MULTICAST_ADDRESS if multicast or broadcast address.
|
|
* SK_ADDR_TOO_EARLY if SK_INIT_IO was not executed before.
|
|
*/
|
|
int SkAddrOverride(
|
|
SK_AC *pAC, /* adapter context */
|
|
SK_IOC IoC, /* I/O context */
|
|
SK_U32 PortNumber, /* Port Number */
|
|
SK_MAC_ADDR SK_FAR *pNewAddr, /* new MAC address */
|
|
int Flags) /* logical/physical MAC address */
|
|
{
|
|
#ifndef SK_NO_RLMT
|
|
SK_EVPARA Para;
|
|
#endif /* !SK_NO_RLMT */
|
|
SK_U32 NetNumber;
|
|
SK_U32 i;
|
|
SK_U16 SK_FAR *OutAddr;
|
|
|
|
#ifndef SK_NO_RLMT
|
|
NetNumber = pAC->Rlmt.Port[PortNumber].Net->NetNumber;
|
|
#else
|
|
NetNumber = 0;
|
|
#endif /* SK_NO_RLMT */
|
|
#if (!defined(SK_SLIM) || defined(DEBUG))
|
|
if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
|
|
return (SK_ADDR_ILLEGAL_PORT);
|
|
}
|
|
#endif /* !SK_SLIM || DEBUG */
|
|
if (pNewAddr != NULL && (pNewAddr->a[0] & SK_MC_BIT) != 0) {
|
|
return (SK_ADDR_MULTICAST_ADDRESS);
|
|
}
|
|
|
|
if (!pAC->Addr.Net[NetNumber].CurrentMacAddressSet) {
|
|
return (SK_ADDR_TOO_EARLY);
|
|
}
|
|
|
|
if (Flags & SK_ADDR_SET_LOGICAL) { /* Activate logical MAC address. */
|
|
/* Parameter *pNewAddr is ignored. */
|
|
for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
|
|
if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
|
|
return (SK_ADDR_TOO_EARLY);
|
|
}
|
|
}
|
|
#ifndef SK_NO_RLMT
|
|
/* Set PortNumber to number of net's active port. */
|
|
PortNumber = pAC->Rlmt.Net[NetNumber].
|
|
Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
|
|
#endif /* !SK_NO_RLMT */
|
|
pAC->Addr.Port[PortNumber].Exact[0] =
|
|
pAC->Addr.Net[NetNumber].CurrentMacAddress;
|
|
|
|
/* Write address to first exact match entry of active port. */
|
|
(void) SkAddrMcUpdate(pAC, IoC, PortNumber);
|
|
}
|
|
else if (Flags & SK_ADDR_CLEAR_LOGICAL) {
|
|
/* Deactivate logical MAC address. */
|
|
/* Parameter *pNewAddr is ignored. */
|
|
for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
|
|
if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
|
|
return (SK_ADDR_TOO_EARLY);
|
|
}
|
|
}
|
|
#ifndef SK_NO_RLMT
|
|
/* Set PortNumber to number of net's active port. */
|
|
PortNumber = pAC->Rlmt.Net[NetNumber].
|
|
Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
|
|
#endif /* !SK_NO_RLMT */
|
|
for (i = 0; i < SK_MAC_ADDR_LEN; i++ ) {
|
|
pAC->Addr.Port[PortNumber].Exact[0].a[i] = 0;
|
|
}
|
|
|
|
/* Write address to first exact match entry of active port. */
|
|
(void) SkAddrMcUpdate(pAC, IoC, PortNumber);
|
|
}
|
|
else if (Flags & SK_ADDR_PHYSICAL_ADDRESS) { /* Physical MAC address. */
|
|
if (SK_ADDR_EQUAL(pNewAddr->a,
|
|
pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
|
|
return (SK_ADDR_DUPLICATE_ADDRESS);
|
|
}
|
|
|
|
for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
|
|
if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
|
|
return (SK_ADDR_TOO_EARLY);
|
|
}
|
|
|
|
if (SK_ADDR_EQUAL(pNewAddr->a,
|
|
pAC->Addr.Port[i].CurrentMacAddress.a)) {
|
|
if (i == PortNumber) {
|
|
return (SK_ADDR_SUCCESS);
|
|
}
|
|
else {
|
|
return (SK_ADDR_DUPLICATE_ADDRESS);
|
|
}
|
|
}
|
|
}
|
|
|
|
pAC->Addr.Port[PortNumber].PreviousMacAddress =
|
|
pAC->Addr.Port[PortNumber].CurrentMacAddress;
|
|
pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
|
|
|
|
/* Change port's physical MAC address. */
|
|
OutAddr = (SK_U16 SK_FAR *) pNewAddr;
|
|
#ifdef GENESIS
|
|
if (pAC->GIni.GIGenesis) {
|
|
XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
|
|
}
|
|
#endif /* GENESIS */
|
|
#ifdef YUKON
|
|
if (!pAC->GIni.GIGenesis) {
|
|
GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
|
|
}
|
|
#endif /* YUKON */
|
|
|
|
#ifndef SK_NO_RLMT
|
|
/* Report address change to RLMT. */
|
|
Para.Para32[0] = PortNumber;
|
|
Para.Para32[0] = -1;
|
|
SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
|
|
#endif /* !SK_NO_RLMT */
|
|
}
|
|
else { /* Logical MAC address. */
|
|
if (SK_ADDR_EQUAL(pNewAddr->a,
|
|
pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
|
|
return (SK_ADDR_SUCCESS);
|
|
}
|
|
|
|
for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
|
|
if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
|
|
return (SK_ADDR_TOO_EARLY);
|
|
}
|
|
|
|
if (SK_ADDR_EQUAL(pNewAddr->a,
|
|
pAC->Addr.Port[i].CurrentMacAddress.a)) {
|
|
return (SK_ADDR_DUPLICATE_ADDRESS);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* In case that the physical and the logical MAC addresses are equal
|
|
* we must also change the physical MAC address here.
|
|
* In this case we have an adapter which initially was programmed with
|
|
* two identical MAC addresses.
|
|
*/
|
|
if (SK_ADDR_EQUAL(pAC->Addr.Port[PortNumber].CurrentMacAddress.a,
|
|
pAC->Addr.Port[PortNumber].Exact[0].a)) {
|
|
|
|
pAC->Addr.Port[PortNumber].PreviousMacAddress =
|
|
pAC->Addr.Port[PortNumber].CurrentMacAddress;
|
|
pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
|
|
|
|
#ifndef SK_NO_RLMT
|
|
/* Report address change to RLMT. */
|
|
Para.Para32[0] = PortNumber;
|
|
Para.Para32[0] = -1;
|
|
SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
|
|
#endif /* !SK_NO_RLMT */
|
|
}
|
|
|
|
#ifndef SK_NO_RLMT
|
|
/* Set PortNumber to number of net's active port. */
|
|
PortNumber = pAC->Rlmt.Net[NetNumber].
|
|
Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
|
|
#endif /* !SK_NO_RLMT */
|
|
pAC->Addr.Net[NetNumber].CurrentMacAddress = *pNewAddr;
|
|
pAC->Addr.Port[PortNumber].Exact[0] = *pNewAddr;
|
|
#ifdef DEBUG
|
|
SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
|
|
("SkAddrOverride: Permanent MAC Address: %02X %02X %02X %02X %02X %02X\n",
|
|
pAC->Addr.Net[NetNumber].PermanentMacAddress.a[0],
|
|
pAC->Addr.Net[NetNumber].PermanentMacAddress.a[1],
|
|
pAC->Addr.Net[NetNumber].PermanentMacAddress.a[2],
|
|
pAC->Addr.Net[NetNumber].PermanentMacAddress.a[3],
|
|
pAC->Addr.Net[NetNumber].PermanentMacAddress.a[4],
|
|
pAC->Addr.Net[NetNumber].PermanentMacAddress.a[5]))
|
|
|
|
SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
|
|
("SkAddrOverride: New logical MAC Address: %02X %02X %02X %02X %02X %02X\n",
|
|
pAC->Addr.Net[NetNumber].CurrentMacAddress.a[0],
|
|
pAC->Addr.Net[NetNumber].CurrentMacAddress.a[1],
|
|
pAC->Addr.Net[NetNumber].CurrentMacAddress.a[2],
|
|
pAC->Addr.Net[NetNumber].CurrentMacAddress.a[3],
|
|
pAC->Addr.Net[NetNumber].CurrentMacAddress.a[4],
|
|
pAC->Addr.Net[NetNumber].CurrentMacAddress.a[5]))
|
|
#endif /* DEBUG */
|
|
|
|
/* Write address to first exact match entry of active port. */
|
|
(void) SkAddrMcUpdate(pAC, IoC, PortNumber);
|
|
}
|
|
|
|
return (SK_ADDR_SUCCESS);
|
|
|
|
} /* SkAddrOverride */
|
|
|
|
|
|
#endif /* SK_NO_MAO */
|
|
|
|
/******************************************************************************
|
|
*
|
|
* SkAddrPromiscuousChange - set promiscuous mode for given port
|
|
*
|
|
* Description:
|
|
* This routine manages promiscuous mode:
|
|
* - none
|
|
* - all LLC frames
|
|
* - all MC frames
|
|
*
|
|
* It calls either SkAddrXmacPromiscuousChange or
|
|
* SkAddrGmacPromiscuousChange, according to the adapter in use.
|
|
* The real work is done there.
|
|
*
|
|
* Context:
|
|
* runtime, pageable
|
|
* may be called after SK_INIT_IO
|
|
*
|
|
* Returns:
|
|
* SK_ADDR_SUCCESS
|
|
* SK_ADDR_ILLEGAL_PORT
|
|
*/
|
|
int SkAddrPromiscuousChange(
|
|
SK_AC *pAC, /* adapter context */
|
|
SK_IOC IoC, /* I/O context */
|
|
SK_U32 PortNumber, /* port whose promiscuous mode changes */
|
|
int NewPromMode) /* new promiscuous mode */
|
|
{
|
|
int ReturnCode = 0;
|
|
#if (!defined(SK_SLIM) || defined(DEBUG))
|
|
if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
|
|
return (SK_ADDR_ILLEGAL_PORT);
|
|
}
|
|
#endif /* !SK_SLIM || DEBUG */
|
|
|
|
#ifdef GENESIS
|
|
if (pAC->GIni.GIGenesis) {
|
|
ReturnCode =
|
|
SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
|
|
}
|
|
#endif /* GENESIS */
|
|
#ifdef YUKON
|
|
if (!pAC->GIni.GIGenesis) {
|
|
ReturnCode =
|
|
SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
|
|
}
|
|
#endif /* YUKON */
|
|
|
|
return (ReturnCode);
|
|
|
|
} /* SkAddrPromiscuousChange */
|
|
|
|
#ifdef GENESIS
|
|
|
|
/******************************************************************************
|
|
*
|
|
* SkAddrXmacPromiscuousChange - set promiscuous mode for given port
|
|
*
|
|
* Description:
|
|
* This routine manages promiscuous mode:
|
|
* - none
|
|
* - all LLC frames
|
|
* - all MC frames
|
|
*
|
|
* Context:
|
|
* runtime, pageable
|
|
* may be called after SK_INIT_IO
|
|
*
|
|
* Returns:
|
|
* SK_ADDR_SUCCESS
|
|
* SK_ADDR_ILLEGAL_PORT
|
|
*/
|
|
static int SkAddrXmacPromiscuousChange(
|
|
SK_AC *pAC, /* adapter context */
|
|
SK_IOC IoC, /* I/O context */
|
|
SK_U32 PortNumber, /* port whose promiscuous mode changes */
|
|
int NewPromMode) /* new promiscuous mode */
|
|
{
|
|
int i;
|
|
SK_BOOL InexactModeBit;
|
|
SK_U8 Inexact;
|
|
SK_U8 HwInexact;
|
|
SK_FILTER64 HwInexactFilter;
|
|
SK_U16 LoMode; /* Lower 16 bits of XMAC Mode Register. */
|
|
int CurPromMode = SK_PROM_MODE_NONE;
|
|
|
|
/* Read CurPromMode from Hardware. */
|
|
XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
|
|
|
|
if ((LoMode & XM_MD_ENA_PROM) != 0) {
|
|
/* Promiscuous mode! */
|
|
CurPromMode |= SK_PROM_MODE_LLC;
|
|
}
|
|
|
|
for (Inexact = 0xFF, i = 0; i < 8; i++) {
|
|
Inexact &= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
|
|
}
|
|
if (Inexact == 0xFF) {
|
|
CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
|
|
}
|
|
else {
|
|
/* Get InexactModeBit (bit XM_MD_ENA_HASH in mode register) */
|
|
XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
|
|
|
|
InexactModeBit = (LoMode & XM_MD_ENA_HASH) != 0;
|
|
|
|
/* Read 64-bit hash register from XMAC */
|
|
XM_INHASH(IoC, PortNumber, XM_HSM, &HwInexactFilter.Bytes[0]);
|
|
|
|
for (HwInexact = 0xFF, i = 0; i < 8; i++) {
|
|
HwInexact &= HwInexactFilter.Bytes[i];
|
|
}
|
|
|
|
if (InexactModeBit && (HwInexact == 0xFF)) {
|
|
CurPromMode |= SK_PROM_MODE_ALL_MC;
|
|
}
|
|
}
|
|
|
|
pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
|
|
|
|
if (NewPromMode == CurPromMode) {
|
|
return (SK_ADDR_SUCCESS);
|
|
}
|
|
|
|
if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
|
|
!(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC. */
|
|
|
|
/* Set all bits in 64-bit hash register. */
|
|
XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
|
|
|
|
/* Enable Hashing */
|
|
SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
|
|
}
|
|
else if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
|
|
!(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm MC. */
|
|
for (Inexact = 0, i = 0; i < 8; i++) {
|
|
Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
|
|
}
|
|
if (Inexact == 0) {
|
|
/* Disable Hashing */
|
|
SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE);
|
|
}
|
|
else {
|
|
/* Set 64-bit hash register to InexactFilter. */
|
|
XM_OUTHASH(IoC, PortNumber, XM_HSM,
|
|
&pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
|
|
|
|
/* Enable Hashing */
|
|
SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
|
|
}
|
|
}
|
|
|
|
if ((NewPromMode & SK_PROM_MODE_LLC) &&
|
|
!(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */
|
|
/* Set the MAC in Promiscuous Mode */
|
|
SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_TRUE);
|
|
}
|
|
else if ((CurPromMode & SK_PROM_MODE_LLC) &&
|
|
!(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC. */
|
|
/* Clear Promiscuous Mode */
|
|
SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_FALSE);
|
|
}
|
|
|
|
return (SK_ADDR_SUCCESS);
|
|
|
|
} /* SkAddrXmacPromiscuousChange */
|
|
|
|
#endif /* GENESIS */
|
|
|
|
#ifdef YUKON
|
|
|
|
/******************************************************************************
|
|
*
|
|
* SkAddrGmacPromiscuousChange - set promiscuous mode for given port
|
|
*
|
|
* Description:
|
|
* This routine manages promiscuous mode:
|
|
* - none
|
|
* - all LLC frames
|
|
* - all MC frames
|
|
*
|
|
* Context:
|
|
* runtime, pageable
|
|
* may be called after SK_INIT_IO
|
|
*
|
|
* Returns:
|
|
* SK_ADDR_SUCCESS
|
|
* SK_ADDR_ILLEGAL_PORT
|
|
*/
|
|
static int SkAddrGmacPromiscuousChange(
|
|
SK_AC *pAC, /* adapter context */
|
|
SK_IOC IoC, /* I/O context */
|
|
SK_U32 PortNumber, /* port whose promiscuous mode changes */
|
|
int NewPromMode) /* new promiscuous mode */
|
|
{
|
|
SK_U16 ReceiveControl; /* GMAC Receive Control Register */
|
|
int CurPromMode = SK_PROM_MODE_NONE;
|
|
|
|
/* Read CurPromMode from Hardware. */
|
|
GM_IN16(IoC, PortNumber, GM_RX_CTRL, &ReceiveControl);
|
|
|
|
if ((ReceiveControl & (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA)) == 0) {
|
|
/* Promiscuous mode! */
|
|
CurPromMode |= SK_PROM_MODE_LLC;
|
|
}
|
|
|
|
if ((ReceiveControl & GM_RXCR_MCF_ENA) == 0) {
|
|
/* All Multicast mode! */
|
|
CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
|
|
}
|
|
|
|
pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
|
|
|
|
if (NewPromMode == CurPromMode) {
|
|
return (SK_ADDR_SUCCESS);
|
|
}
|
|
|
|
if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
|
|
!(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC */
|
|
|
|
/* Set all bits in 64-bit hash register. */
|
|
GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
|
|
|
|
/* Enable Hashing */
|
|
SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
|
|
}
|
|
|
|
if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
|
|
!(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm. MC */
|
|
|
|
/* Set 64-bit hash register to InexactFilter. */
|
|
GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1,
|
|
&pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
|
|
|
|
/* Enable Hashing. */
|
|
SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
|
|
}
|
|
|
|
if ((NewPromMode & SK_PROM_MODE_LLC) &&
|
|
!(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */
|
|
|
|
/* Set the MAC to Promiscuous Mode. */
|
|
SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_TRUE);
|
|
}
|
|
else if ((CurPromMode & SK_PROM_MODE_LLC) &&
|
|
!(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC */
|
|
|
|
/* Clear Promiscuous Mode. */
|
|
SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_FALSE);
|
|
}
|
|
|
|
return (SK_ADDR_SUCCESS);
|
|
|
|
} /* SkAddrGmacPromiscuousChange */
|
|
|
|
#endif /* YUKON */
|
|
|
|
#ifndef SK_SLIM
|
|
|
|
/******************************************************************************
|
|
*
|
|
* SkAddrSwap - swap address info
|
|
*
|
|
* Description:
|
|
* This routine swaps address info of two ports.
|
|
*
|
|
* Context:
|
|
* runtime, pageable
|
|
* may be called after SK_INIT_IO
|
|
*
|
|
* Returns:
|
|
* SK_ADDR_SUCCESS
|
|
* SK_ADDR_ILLEGAL_PORT
|
|
*/
|
|
int SkAddrSwap(
|
|
SK_AC *pAC, /* adapter context */
|
|
SK_IOC IoC, /* I/O context */
|
|
SK_U32 FromPortNumber, /* Port1 Index */
|
|
SK_U32 ToPortNumber) /* Port2 Index */
|
|
{
|
|
int i;
|
|
SK_U8 Byte;
|
|
SK_MAC_ADDR MacAddr;
|
|
SK_U32 DWord;
|
|
|
|
if (FromPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
|
|
return (SK_ADDR_ILLEGAL_PORT);
|
|
}
|
|
|
|
if (ToPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
|
|
return (SK_ADDR_ILLEGAL_PORT);
|
|
}
|
|
|
|
if (pAC->Rlmt.Port[FromPortNumber].Net != pAC->Rlmt.Port[ToPortNumber].Net) {
|
|
return (SK_ADDR_ILLEGAL_PORT);
|
|
}
|
|
|
|
/*
|
|
* Swap:
|
|
* - Exact Match Entries (GEnesis and Yukon)
|
|
* Yukon uses first entry for the logical MAC
|
|
* address (stored in the second GMAC register).
|
|
* - FirstExactMatchRlmt (GEnesis only)
|
|
* - NextExactMatchRlmt (GEnesis only)
|
|
* - FirstExactMatchDrv (GEnesis only)
|
|
* - NextExactMatchDrv (GEnesis only)
|
|
* - 64-bit filter (InexactFilter)
|
|
* - Promiscuous Mode
|
|
* of ports.
|
|
*/
|
|
|
|
for (i = 0; i < SK_ADDR_EXACT_MATCHES; i++) {
|
|
MacAddr = pAC->Addr.Port[FromPortNumber].Exact[i];
|
|
pAC->Addr.Port[FromPortNumber].Exact[i] =
|
|
pAC->Addr.Port[ToPortNumber].Exact[i];
|
|
pAC->Addr.Port[ToPortNumber].Exact[i] = MacAddr;
|
|
}
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
Byte = pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i];
|
|
pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i] =
|
|
pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i];
|
|
pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i] = Byte;
|
|
}
|
|
|
|
i = pAC->Addr.Port[FromPortNumber].PromMode;
|
|
pAC->Addr.Port[FromPortNumber].PromMode = pAC->Addr.Port[ToPortNumber].PromMode;
|
|
pAC->Addr.Port[ToPortNumber].PromMode = i;
|
|
|
|
if (pAC->GIni.GIGenesis) {
|
|
DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt;
|
|
pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt =
|
|
pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt;
|
|
pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt = DWord;
|
|
|
|
DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt;
|
|
pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt =
|
|
pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt;
|
|
pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt = DWord;
|
|
|
|
DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv;
|
|
pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv =
|
|
pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv;
|
|
pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv = DWord;
|
|
|
|
DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchDrv;
|
|
pAC->Addr.Port[FromPortNumber].NextExactMatchDrv =
|
|
pAC->Addr.Port[ToPortNumber].NextExactMatchDrv;
|
|
pAC->Addr.Port[ToPortNumber].NextExactMatchDrv = DWord;
|
|
}
|
|
|
|
/* CAUTION: Solution works if only ports of one adapter are in use. */
|
|
for (i = 0; (SK_U32) i < pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].
|
|
Net->NetNumber].NumPorts; i++) {
|
|
if (pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
|
|
Port[i]->PortNumber == ToPortNumber) {
|
|
pAC->Addr.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
|
|
ActivePort = i;
|
|
/* 20001207 RA: Was "ToPortNumber;". */
|
|
}
|
|
}
|
|
|
|
(void) SkAddrMcUpdate(pAC, IoC, FromPortNumber);
|
|
(void) SkAddrMcUpdate(pAC, IoC, ToPortNumber);
|
|
|
|
return (SK_ADDR_SUCCESS);
|
|
|
|
} /* SkAddrSwap */
|
|
|
|
#endif /* !SK_SLIM */
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif /* __cplusplus */
|
|
|