patch-2.4.21 linux-2.4.21/drivers/net/sk98lin/skaddr.c
Next file: linux-2.4.21/drivers/net/sk98lin/skcsum.c
Previous file: linux-2.4.21/drivers/net/sk98lin/h/xmac_ii.h
Back to the patch index
Back to the overall index
- Lines: 1723
- Date:
2003-06-13 07:51:35.000000000 -0700
- Orig file:
linux-2.4.20/drivers/net/sk98lin/skaddr.c
- Orig date:
2002-08-02 17:39:44.000000000 -0700
diff -urN linux-2.4.20/drivers/net/sk98lin/skaddr.c linux-2.4.21/drivers/net/sk98lin/skaddr.c
@@ -2,15 +2,15 @@
*
* Name: skaddr.c
* Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.40 $
- * Date: $Date: 2001/02/14 14:04:59 $
+ * Version: $Revision: 1.47 $
+ * Date: $Date: 2002/09/17 06:31:10 $
* Purpose: Manage Addresses (Multicast and Unicast) and Promiscuous Mode.
*
******************************************************************************/
/******************************************************************************
*
- * (C)Copyright 1998-2001 SysKonnect GmbH.
+ * (C)Copyright 1998-2002 SysKonnect GmbH.
*
* 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
@@ -26,6 +26,39 @@
* History:
*
* $Log: skaddr.c,v $
+ * Revision 1.47 2002/09/17 06:31:10 tschilli
+ * Handling of SK_PROM_MODE_ALL_MC flag in SkAddrGmacMcUpdate()
+ * and SkAddrGmacPromiscuousChange() fixed.
+ * Editorial changes.
+ *
+ * Revision 1.46 2002/08/22 07:55:41 tschilli
+ * New function SkGmacMcHash() for GMAC multicast hashing algorithm added.
+ * Editorial changes.
+ *
+ * Revision 1.45 2002/08/15 12:29:35 tschilli
+ * SkAddrGmacMcUpdate() and SkAddrGmacPromiscuousChange() changed.
+ *
+ * Revision 1.44 2002/08/14 12:18:03 rschmidt
+ * Replaced direct handling of MAC Hashing (XMAC and GMAC)
+ * with routine SkMacHashing().
+ * Replaced wrong 3rd para 'i' with 'PortNumber' in SkMacPromiscMode().
+ *
+ * Revision 1.43 2002/08/13 09:37:43 rschmidt
+ * Corrected some SK_DBG_MSG outputs.
+ * Replaced wrong 2nd para pAC with IoC in SkMacPromiscMode().
+ * Editorial changes.
+ *
+ * Revision 1.42 2002/08/12 11:24:36 rschmidt
+ * Remove setting of logical MAC address GM_SRC_ADDR_2 in SkAddrInit().
+ * Replaced direct handling of MAC Promiscuous Mode (XMAC and GMAC)
+ * with routine SkMacPromiscMode().
+ * Editorial changes.
+ *
+ * Revision 1.41 2002/06/10 13:52:18 tschilli
+ * Changes for handling YUKON.
+ * All changes are internally and not visible to the programmer
+ * using this module.
+ *
* Revision 1.40 2001/02/14 14:04:59 rassmann
* Editorial changes.
*
@@ -166,13 +199,13 @@
* Description:
*
* This module is intended to manage multicast addresses, address override,
- * and promiscuous mode on GEnesis adapters.
+ * and promiscuous mode on GEnesis and Yukon adapters.
*
* Address Layout:
* port address: physical MAC address
- * 1st exact match: logical MAC address
- * 2nd exact match: RLMT multicast
- * exact match 3-13: OS-specific multicasts
+ * 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:
*
@@ -183,7 +216,7 @@
#ifndef lint
static const char SysKonnectFileId[] =
- "@(#) $Id: skaddr.c,v 1.40 2001/02/14 14:04:59 rassmann Exp $ (C) SysKonnect.";
+ "@(#) $Id: skaddr.c,v 1.47 2002/09/17 06:31:10 tschilli Exp $ (C) SysKonnect.";
#endif /* !defined(lint) */
#define __SKADDR_C
@@ -199,6 +232,8 @@
/* 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
@@ -247,7 +282,7 @@
* 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 XMAC.
+ * The current addresses are written to the corresponding MAC.
*
*
* SK_INIT_RUN
@@ -266,38 +301,26 @@
SK_IOC IoC, /* I/O context */
int Level) /* initialization level */
{
- int j;
- SK_U32 i;
- SK_U8 *InAddr;
- SK_U16 *OutAddr;
+ 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, 0, sizeof(SK_ADDR));
+ SK_MEMSET((char *) &pAC->Addr, 0, 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;
-
-#if 0
- /* Don't do this here ... */
-
- /* Reset Promiscuous mode. */
- (void)SkAddrPromiscuousChange(
- pAC,
- IoC,
- i,
- SK_PROM_MODE_NONE);
-#endif /* 0 */
+
+ 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 DEBUG
+#ifdef xDEBUG
for (i = 0; i < SK_MAX_MACS; i++) {
if (pAC->Addr.Port[i].NextExactMatchRlmt <
SK_ADDR_FIRST_MATCH_RLMT) {
@@ -305,7 +328,6 @@
}
}
#endif /* DEBUG */
-
/* pAC->Addr.InitDone = SK_INIT_DATA; */
break;
@@ -313,8 +335,7 @@
for (i = 0; i < SK_MAX_NETS; i++) {
pAC->Addr.Net[i].ActivePort = pAC->Rlmt.Net[i].ActivePort;
}
-
-#ifdef DEBUG
+#ifdef xDEBUG
for (i = 0; i < SK_MAX_MACS; i++) {
if (pAC->Addr.Port[i].NextExactMatchRlmt <
SK_ADDR_FIRST_MATCH_RLMT) {
@@ -322,10 +343,10 @@
}
}
#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];
+ InAddr = (SK_U8 *) &pAC->Addr.Net[0].PermanentMacAddress.a[j];
SK_IN8(IoC, B2_MAC_1 + j, InAddr);
}
@@ -339,7 +360,6 @@
/* 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) {
@@ -353,43 +373,36 @@
}
#endif /* SK_MAX_NETS > 1 */
-#ifdef xDEBUG
- SK_DBG_MSG(
- pAC,
- SK_DBGMOD_ADDR,
- SK_DBGCAT_INIT,
- ("Permanent MAC Address: %02X %02X %02X %02X %02X %02X\n",
- pAC->Addr.PermanentMacAddress.a[0],
- pAC->Addr.PermanentMacAddress.a[1],
- pAC->Addr.PermanentMacAddress.a[2],
- pAC->Addr.PermanentMacAddress.a[3],
- pAC->Addr.PermanentMacAddress.a[4],
- pAC->Addr.PermanentMacAddress.a[5]))
- SK_DBG_MSG(
- pAC,
- SK_DBGMOD_ADDR,
- SK_DBGCAT_INIT,
- ("Logical MAC Address: %02X %02X %02X %02X %02X %02X\n",
- pAC->Addr.CurrentMacAddress.a[0],
- pAC->Addr.CurrentMacAddress.a[1],
- pAC->Addr.CurrentMacAddress.a[2],
- pAC->Addr.CurrentMacAddress.a[3],
- pAC->Addr.CurrentMacAddress.a[4],
- pAC->Addr.CurrentMacAddress.a[5]))
+#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 */
-#if 0
- /* Don't do this here ... */
-
- (void)SkAddrMcUpdate(pAC, IoC, pAC->Addr.ActivePort);
-#endif /* 0 */
-
- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+ 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];
+ InAddr = (SK_U8 *) &pAPort->PermanentMacAddress.a[j];
SK_IN8(IoC, B2_MAC_2 + 8 * i + j, InAddr);
}
@@ -403,27 +416,27 @@
pAPort->CurrentMacAddressSet = SK_TRUE;
}
- /* Set port's current MAC addresses. */
- OutAddr = (SK_U16 *)&pAPort->CurrentMacAddress.a[0];
- XM_OUTADDR(IoC, i, XM_SA, OutAddr);
-
-#ifdef xDEBUG
- SK_DBG_MSG(
- pAC,
- SK_DBGMOD_ADDR,
- SK_DBGCAT_INIT,
- ("Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
+ /* Set port's current physical MAC address. */
+ OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
+
+ if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+ XM_OUTADDR(IoC, i, XM_SA, OutAddr);
+ }
+ else {
+ GM_OUTADDR(IoC, i, GM_SRC_ADDR_1L, OutAddr);
+ }
+#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,
- ("Phsical MAC Address: %02X %02X %02X %02X %02X %02X\n",
+
+ 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],
@@ -436,7 +449,7 @@
break;
case SK_INIT_RUN:
-#ifdef DEBUG
+#ifdef xDEBUG
for (i = 0; i < SK_MAX_MACS; i++) {
if (pAC->Addr.Port[i].NextExactMatchRlmt <
SK_ADDR_FIRST_MATCH_RLMT) {
@@ -453,6 +466,7 @@
}
return (SK_ADDR_SUCCESS);
+
} /* SkAddrInit */
@@ -461,11 +475,14 @@
* SkAddrMcClear - clear the multicast table
*
* Description:
- * This routine clears the multicast table
- * (either entry 2 or entries 3-16 and InexactFilter) of the given port.
+ * 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
@@ -481,21 +498,59 @@
SK_U32 PortNumber, /* Index of affected port */
int Flags) /* permanent/non-perm, sw-only */
{
- int i;
-
- if (PortNumber >= (SK_U32)pAC->GIni.GIMacsFound) {
+ int ReturnCode;
+
+ if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
return (SK_ADDR_ILLEGAL_PORT);
}
+
+ if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+ ReturnCode = SkAddrXmacMcClear(pAC, IoC, PortNumber, Flags);
+ }
+ else {
+ ReturnCode = SkAddrGmacMcClear(pAC, IoC, PortNumber, Flags);
+ }
+
+ return (ReturnCode);
+
+} /* SkAddrMcClear */
+
+
+/******************************************************************************
+ *
+ * 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
+ */
+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) {
+ 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. */
-
+ /* Clear InexactFilter */
for (i = 0; i < 8; i++) {
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
}
@@ -506,20 +561,114 @@
}
if (!(Flags & SK_MC_SW_ONLY)) {
- (void)SkAddrMcUpdate(pAC, IoC, PortNumber);
+ (void) SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
}
return (SK_ADDR_SUCCESS);
-} /* SkAddrMcClear */
+
+} /* SkAddrXmacMcClear */
+
+
+/******************************************************************************
+ *
+ * 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
+ */
+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
/******************************************************************************
*
- * SkCrc32McHash - hash multicast address
+ * 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.
@@ -530,15 +679,84 @@
* Returns:
* Hash value of multicast address.
*/
-unsigned SkCrc32McHash(
+SK_U32 SkXmacMcHash(
unsigned char *pMc) /* Multicast address */
{
- u32 Crc;
+ 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);
+ }
+ }
- Crc = ether_crc_le(SK_MAC_ADDR_LEN, pMc);
+ 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.
+ */
+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));
-} /* SkCrc32McHash */
+
+} /* SkGmacMcHash */
#endif /* not SK_ADDR_CHEAT */
@@ -549,11 +767,57 @@
* 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.
*
- * In the current version, only RLMT may add addresses to the non-active
- * port.
+ * 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.GIChipId == CHIP_ID_GENESIS) {
+ 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.
@@ -566,28 +830,23 @@
* SK_MC_FILTERING_EXACT
* SK_MC_FILTERING_INEXACT
* SK_MC_ILLEGAL_ADDRESS
- * SK_MC_ILLEGAL_PORT
* SK_MC_RLMT_OVERFLOW
*/
-int SkAddrMcAdd(
+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 Flags) /* permanent/non-permanent */
{
int i;
SK_U8 Inexact;
#ifndef SK_ADDR_CHEAT
- unsigned HashBit;
+ SK_U32 HashBit;
#endif /* !defined(SK_ADDR_CHEAT) */
- if (PortNumber >= (SK_U32)pAC->GIni.GIMacsFound) {
- return (SK_ADDR_ILLEGAL_PORT);
- }
-
- if (Flags & SK_ADDR_PERMANENT) {
-#ifdef DEBUG
+ if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
+#ifdef xDEBUG
if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt <
SK_ADDR_FIRST_MATCH_RLMT) {
Next0[PortNumber] |= 1;
@@ -600,7 +859,7 @@
return (SK_MC_RLMT_OVERFLOW);
}
- /* Set an RLMT multicast address. */
+ /* Set a RLMT multicast address. */
pAC->Addr.Port[PortNumber].Exact[
pAC->Addr.Port[PortNumber].NextExactMatchRlmt++] = *pMc;
@@ -608,15 +867,7 @@
return (SK_MC_FILTERING_EXACT);
}
-#if 0
- /* Not PERMANENT => DRV */
- if (PortNumber != pAC->Addr.ActivePort) {
- /* Only RLMT is allowed to do this. */
- return (SK_MC_ILLEGAL_PORT);
- }
-#endif /* 0 */
-
-#ifdef DEBUG
+#ifdef xDEBUG
if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <
SK_ADDR_FIRST_MATCH_DRV) {
Next0[PortNumber] |= 2;
@@ -630,22 +881,19 @@
pAC->Addr.Port[PortNumber].Exact[
pAC->Addr.Port[PortNumber].NextExactMatchDrv++] = *pMc;
- /* Clear InexactFilter. */
+ /* 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.
- */
+ /* Hashing only possible with multicast addresses. */
return (SK_MC_ILLEGAL_ADDRESS);
}
#ifndef SK_ADDR_CHEAT
/* Compute hash value of address. */
- HashBit = 63 - SkCrc32McHash(&pMc->a[0]);
+ HashBit = 63 - SkXmacMcHash(&pMc->a[0]);
/* Add bit to InexactFilter. */
pAC->Addr.Port[PortNumber].InexactFilter.Bytes[HashBit / 8] |=
@@ -668,90 +916,223 @@
else {
return (SK_MC_FILTERING_INEXACT);
}
-} /* SkAddrMcAdd */
+
+} /* SkAddrXmacMcAdd */
/******************************************************************************
*
- * SkAddrMcUpdate - update the HW MC address table and set the MAC address
+ * SkAddrGmacMcAdd - add a multicast address to a port
*
* 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.
+ * 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_IO
+ * may be called after SK_INIT_DATA
*
* Returns:
- * SK_MC_FILTERING_EXACT
* SK_MC_FILTERING_INEXACT
- * SK_ADDR_ILLEGAL_PORT
+ * SK_MC_ILLEGAL_ADDRESS
*/
-int SkAddrMcUpdate(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber) /* Port Number */
+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 */
{
- SK_U32 i;
- SK_U8 Inexact;
- SK_U16 *OutAddr;
- SK_U16 LoMode; /* Lower 16 bits of XMAC Mode Reg. */
- SK_ADDR_PORT *pAPort;
-
- if (PortNumber >= (SK_U32)pAC->GIni.GIMacsFound) {
- return (SK_ADDR_ILLEGAL_PORT);
+ 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);
}
-
- SK_DBG_MSG(
- pAC,
- SK_DBGMOD_ADDR,
- SK_DBGCAT_CTRL,
- ("SkAddrMcUpdate on Port %u.\n", PortNumber))
- pAPort = &pAC->Addr.Port[PortNumber];
-
+#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,
- ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
+ 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 */
-
- /* Start with 0 to also program the logical MAC address. */
- for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
- /* Set exact match address i on HW. */
- OutAddr = (SK_U16 *)&pAPort->Exact[i].a[0];
- XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
+ }
+ 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 */
+
+
+/******************************************************************************
+ *
+ * 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;
+
+ if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+ return (SK_ADDR_ILLEGAL_PORT);
+ }
+
+ if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+ ReturnCode = SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
+ }
+ else {
+ ReturnCode = SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
+ }
+
+ return (ReturnCode);
+
+} /* SkAddrMcUpdate */
+
+
+/******************************************************************************
+ *
+ * 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
+ */
+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 HW. */
+ /* Clear other permanent exact match addresses on XMAC */
if (pAPort->NextExactMatchRlmt <= SK_ADDR_LAST_MATCH_RLMT) {
- SkXmClrExactAddr(
- pAC,
- IoC,
- PortNumber,
- pAPort->NextExactMatchRlmt,
+
+ 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];
+ OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
}
- /* Clear other non-permanent exact match addresses on HW. */
+ /* Clear other non-permanent exact match addresses on XMAC */
if (pAPort->NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
- SkXmClrExactAddr(
- pAC,
- IoC,
- PortNumber,
- pAPort->NextExactMatchDrv,
+
+ SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchDrv,
SK_ADDR_LAST_MATCH_DRV);
}
@@ -760,36 +1141,33 @@
}
if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
+
/* Set all bits in 64-bit hash register. */
XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
-
- /* Set bit 15 in mode register. */
- XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
- LoMode |= XM_MD_ENA_HSH;
- XM_OUT16(IoC, PortNumber, XM_MODE, LoMode);
+
+ /* Enable Hashing */
+ SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
}
else if (Inexact != 0) {
+
/* Set 64-bit hash register to InexactFilter. */
XM_OUTHASH(IoC, PortNumber, XM_HSM, &pAPort->InexactFilter.Bytes[0]);
-
- /* Set bit 15 in mode register. */
- XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
- LoMode |= XM_MD_ENA_HSH;
- XM_OUT16(IoC, PortNumber, XM_MODE, LoMode);
+
+ /* Enable Hashing */
+ SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
}
else {
- /* Clear bit 15 in mode register. */
- XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
- LoMode &= ~XM_MD_ENA_HSH;
- XM_OUT16(IoC, PortNumber, XM_MODE, LoMode);
+ /* Disable Hashing */
+ SkMacHashing(pAC, IoC, PortNumber, SK_FALSE);
}
if (pAPort->PromMode != SK_PROM_MODE_NONE) {
- (void)SkAddrPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
+ (void) SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
}
- /* Set port's current MAC address. */
- OutAddr = (SK_U16 *)&pAPort->CurrentMacAddress.a[0];
+ /* Set port's current physical MAC address. */
+ OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
+
XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
#ifdef xDEBUG
@@ -798,13 +1176,13 @@
SK_U16 *InAddr;
/* Get exact match address i from port PortNumber. */
- InAddr = (SK_U16 *)&InAddr8[0];
+ InAddr = (SK_U16 *) &InAddr8[0];
+
XM_INADDR(IoC, PortNumber, XM_EXM(i), InAddr);
- SK_DBG_MSG(
- pAC,
- SK_DBGMOD_ADDR,
- SK_DBGCAT_CTRL,
- ("MC address %d on Port %u: %02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x.\n",
+
+ 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],
@@ -829,7 +1207,113 @@
else {
return (SK_MC_FILTERING_INEXACT);
}
-} /* SkAddrMcUpdate */
+
+} /* SkAddrXmacMcUpdate */
+
+
+/******************************************************************************
+ *
+ * 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
+ */
+int SkAddrGmacMcUpdate(
+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,
+ ("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 */
+
+ 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, PortNumber, SK_TRUE);
+ }
+ else {
+ /* Enable Hashing. */
+ SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
+ }
+
+ if (pAPort->PromMode != SK_PROM_MODE_NONE) {
+ (void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
+ }
+
+ /* 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 */
+
+ /* Determine return value. */
+ if (Inexact == 0 && pAPort->PromMode == 0) {
+ return (SK_MC_FILTERING_EXACT);
+ }
+ else {
+ return (SK_MC_FILTERING_INEXACT);
+ }
+
+} /* SkAddrGmacMcUpdate */
/******************************************************************************
@@ -863,7 +1347,7 @@
NetNumber = pAC->Rlmt.Port[PortNumber].Net->NetNumber;
- if (PortNumber >= (SK_U32)pAC->GIni.GIMacsFound) {
+ if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
return (SK_ADDR_ILLEGAL_PORT);
}
@@ -877,7 +1361,7 @@
if (Flags & SK_ADDR_SET_LOGICAL) { /* Activate logical MAC address. */
/* Parameter *pNewAddr is ignored. */
- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+ for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
return (SK_ADDR_TOO_EARLY);
}
@@ -891,12 +1375,12 @@
pAC->Addr.Net[NetNumber].CurrentMacAddress;
/* Write address to first exact match entry of active port. */
- (void)SkAddrMcUpdate(pAC, IoC, PortNumber);
+ (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++) {
+ for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
return (SK_ADDR_TOO_EARLY);
}
@@ -911,7 +1395,7 @@
}
/* Write address to first exact match entry of active port. */
- (void)SkAddrMcUpdate(pAC, IoC, PortNumber);
+ (void) SkAddrMcUpdate(pAC, IoC, PortNumber);
}
else if (Flags & SK_ADDR_PHYSICAL_ADDRESS) { /* Physical MAC address. */
if (SK_ADDR_EQUAL(pNewAddr->a,
@@ -919,7 +1403,7 @@
return (SK_ADDR_DUPLICATE_ADDRESS);
}
- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+ for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
return (SK_ADDR_TOO_EARLY);
}
@@ -939,9 +1423,15 @@
pAC->Addr.Port[PortNumber].CurrentMacAddress;
pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
- /* Change port's address. */
- OutAddr = (SK_U16 *)pNewAddr;
- XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
+ /* Change port's physical MAC address. */
+ OutAddr = (SK_U16 *) pNewAddr;
+
+ if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+ XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
+ }
+ else {
+ GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
+ }
/* Report address change to RLMT. */
Para.Para32[0] = PortNumber;
@@ -954,7 +1444,7 @@
return (SK_ADDR_SUCCESS);
}
- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+ for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
return (SK_ADDR_TOO_EARLY);
}
@@ -971,24 +1461,18 @@
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,
- ("Permanent MAC Address: %02X %02X %02X %02X %02X %02X\n",
+ 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,
- ("New logical MAC Address: %02X %02X %02X %02X %02X %02X\n",
+
+ 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],
@@ -998,10 +1482,11 @@
#endif /* DEBUG */
/* Write address to first exact match entry of active port. */
- (void)SkAddrMcUpdate(pAC, IoC, PortNumber);
+ (void) SkAddrMcUpdate(pAC, IoC, PortNumber);
}
return (SK_ADDR_SUCCESS);
+
} /* SkAddrOverride */
@@ -1015,6 +1500,10 @@
* - 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
@@ -1029,6 +1518,48 @@
SK_U32 PortNumber, /* port whose promiscuous mode changes */
int NewPromMode) /* new promiscuous mode */
{
+ int ReturnCode;
+
+ if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+ return (SK_ADDR_ILLEGAL_PORT);
+ }
+
+ if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+ ReturnCode = SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
+ }
+ else {
+ ReturnCode = SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
+ }
+
+ return (ReturnCode);
+
+} /* SkAddrPromiscuousChange */
+
+
+/******************************************************************************
+ *
+ * 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
+ */
+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;
@@ -1037,14 +1568,11 @@
SK_U16 LoMode; /* Lower 16 bits of XMAC Mode Register. */
int CurPromMode = SK_PROM_MODE_NONE;
- if (PortNumber >= (SK_U32)pAC->GIni.GIMacsFound) {
- return (SK_ADDR_ILLEGAL_PORT);
- }
-
/* Read CurPromMode from Hardware. */
XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
- if (LoMode & XM_MD_ENA_PROM) {
+ if ((LoMode & XM_MD_ENA_PROM) != 0) {
+ /* Promiscuous mode! */
CurPromMode |= SK_PROM_MODE_LLC;
}
@@ -1055,12 +1583,12 @@
CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
}
else {
- /* Read InexactModeBit (bit 15 in mode register). */
+ /* Get InexactModeBit (bit XM_MD_ENA_HASH in mode register) */
XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
- InexactModeBit = (LoMode & XM_MD_ENA_HSH) != 0;
+ InexactModeBit = (LoMode & XM_MD_ENA_HASH) != 0;
- /* Read 64-bit hash register from HW. */
+ /* Read 64-bit hash register from XMAC */
XM_INHASH(IoC, PortNumber, XM_HSM, &HwInexactFilter.Bytes[0]);
for (HwInexact = 0xFF, i = 0; i < 8; i++) {
@@ -1080,13 +1608,12 @@
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);
- /* Set bit 15 in mode register. */
- XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
- LoMode |= XM_MD_ENA_HSH;
- XM_OUT16(IoC, PortNumber, XM_MODE, LoMode);
+ /* Enable Hashing */
+ SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
}
else if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
!(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm MC. */
@@ -1094,55 +1621,118 @@
Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
}
if (Inexact == 0) {
- /* Clear bit 15 in mode register. */
- XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
- LoMode &= ~XM_MD_ENA_HSH;
- XM_OUT16(IoC, PortNumber, XM_MODE, LoMode);
+ /* Disable Hashing */
+ SkMacHashing(pAC, IoC, PortNumber, SK_FALSE);
}
else {
/* Set 64-bit hash register to InexactFilter. */
- XM_OUTHASH(
- IoC,
- PortNumber,
- XM_HSM,
+ XM_OUTHASH(IoC, PortNumber, XM_HSM,
&pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
- /* Set bit 15 in mode register. */
- XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
- LoMode |= XM_MD_ENA_HSH;
- XM_OUT16(IoC, PortNumber, XM_MODE, LoMode);
+ /* Enable Hashing */
+ SkMacHashing(pAC, IoC, PortNumber, SK_TRUE);
}
}
if ((NewPromMode & SK_PROM_MODE_LLC) &&
!(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */
- /* Set promiscuous bit in mode register. */
- XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
-
-#if 0
- /* Receive MAC frames. */
- LoMode |= XM_MD_RX_MCTRL;
-#endif /* 0 */
-
- LoMode |= XM_MD_ENA_PROM;
- XM_OUT16(IoC, PortNumber, XM_MODE, LoMode);
+ /* Set the MAC in Promiscuous Mode */
+ SkMacPromiscMode(pAC, IoC, PortNumber, SK_TRUE);
}
else if ((CurPromMode & SK_PROM_MODE_LLC) &&
!(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC. */
- /* Clear promiscuous bit in mode register. */
- XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
+ /* Clear Promiscuous Mode */
+ SkMacPromiscMode(pAC, IoC, PortNumber, SK_FALSE);
+ }
+
+ return (SK_ADDR_SUCCESS);
+
+} /* SkAddrXmacPromiscuousChange */
+
+
+/******************************************************************************
+ *
+ * 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
+ */
+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);
+ }
-#if 0
- /* Don't receive MAC frames. */
- LoMode &= ~XM_MD_RX_MCTRL;
-#endif /* 0 */
+ 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 */
- LoMode &= ~XM_MD_ENA_PROM;
- XM_OUT16(IoC, PortNumber, XM_MODE, LoMode);
+ /* Set all bits in 64-bit hash register. */
+ GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
+
+ /* Enable Hashing */
+ SkMacHashing(pAC, IoC, 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, 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, PortNumber, SK_TRUE);
+ }
+ else if ((CurPromMode & SK_PROM_MODE_LLC) &&
+ !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC */
+
+ /* Clear Promiscuous Mode. */
+ SkMacPromiscMode(pAC, IoC, PortNumber, SK_FALSE);
+ }
+
return (SK_ADDR_SUCCESS);
-} /* SkAddrPromiscuousChange */
+
+} /* SkAddrGmacPromiscuousChange */
/******************************************************************************
@@ -1163,7 +1753,7 @@
int SkAddrSwap(
SK_AC *pAC, /* adapter context */
SK_IOC IoC, /* I/O context */
-SK_U32 FromPortNumber, /* Port1 Index */
+SK_U32 FromPortNumber, /* Port1 Index */
SK_U32 ToPortNumber) /* Port2 Index */
{
int i;
@@ -1171,11 +1761,11 @@
SK_MAC_ADDR MacAddr;
SK_U32 DWord;
- if (FromPortNumber >= (SK_U32)pAC->GIni.GIMacsFound) {
+ if (FromPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
return (SK_ADDR_ILLEGAL_PORT);
}
- if (ToPortNumber >= (SK_U32)pAC->GIni.GIMacsFound) {
+ if (ToPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
return (SK_ADDR_ILLEGAL_PORT);
}
@@ -1184,13 +1774,15 @@
}
/*
- * Swap
- * - Exact Match Entries
- * - FirstExactMatchRlmt;
- * - NextExactMatchRlmt;
- * - FirstExactMatchDrv;
- * - NextExactMatchDrv;
- * - 64-bit filter
+ * 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.
*/
@@ -1208,46 +1800,49 @@
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;
-
- 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;
-
+
+ if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+ 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].
+ 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);
+
+ (void) SkAddrMcUpdate(pAC, IoC, FromPortNumber);
+ (void) SkAddrMcUpdate(pAC, IoC, ToPortNumber);
return (SK_ADDR_SUCCESS);
+
} /* SkAddrSwap */
#ifdef __cplusplus
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)