diff -Naru linux-2.6.16_orig/drivers/net/netxen/niu.c
linux-2.6.16/drivers/net/netxen/niu.c
--- linux-2.6.16_orig/drivers/net/netxen/niu.c 1969-12-31 16:00:00.000000000
-0800
+++ linux-2.6.16/drivers/net/netxen/niu.c 2006-03-24 14:13:57.000000000
-0800
@@ -0,0 +1,858 @@
+/*
+ * Copyright (C) 2003 - 2006 NetXen Inc.
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.
+ *
+ * Contact Information:
+ * [EMAIL PROTECTED]
+ * NetXen, 3965 Freedom Circle, Fourth Floor,
+ * Santa Clara, CA 95054
+ */
+/*
+ * Provides access to the Network Interface Unit h/w block.
+ */
+#include "netxen_inc.h"
+
+int netxen_niu_init_test(void);
+
+/*
+ * netxen_niu_gbe_phy_read - read a register from the GbE PHY via
+ * mii management interface.
+ *
+ * Note: The MII management interface goes through port 0.
+ * Individual phys are addressed as follows:
+ * [15:8] phy id
+ * [7:0] register number
+ *
+ * Returns: 0 success
+ * -1 error
+ *
+ */
+long netxen_niu_gbe_phy_read (long phy, long reg, netxen_crbword_t *readval) {
+ netxen_niu_gb_mii_mgmt_address_t address;
+ netxen_niu_gb_mii_mgmt_command_t command;
+ netxen_niu_gb_mii_mgmt_indicators_t status;
+ netxen_niu_gb_mii_mgmt_config_t mii_cfg;
+
+ long timeout=0;
+ long result = 0;
+ long restore = 0;
+ netxen_niu_gb_mac_config_0_t mac_cfg0;
+
+ /* MII mgmt all goes through port 0 MAC interface, so it cannot be in
reset */
+ NetXen_CRB_READ_CHECK(NetXen_NIU_GB_MAC_CONFIG_0(0), &mac_cfg0);
+ if (mac_cfg0.soft_reset) {
+ netxen_niu_gb_mac_config_0_t temp;
+ *(netxen_crbword_t *)&temp = 0;
+ temp.tx_reset_pb = 1;
+ temp.rx_reset_pb = 1;
+ temp.tx_reset_mac = 1;
+ temp.rx_reset_mac = 1;
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_GB_MAC_CONFIG_0(0), &temp );
+ restore = 1;
+ }
+
+ /* reset MII management interface */
+ *(netxen_crbword_t *)&mii_cfg = 0;
+ mii_cfg.clockselect = 7;
+ mii_cfg.reset = 1;
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_GB_MII_MGMT_CONFIG(0), &mii_cfg);
+ mii_cfg.reset = 0;
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_GB_MII_MGMT_CONFIG(0), &mii_cfg);
+
+ *(netxen_crbword_t *)&address = 0;
+ address.reg_addr = reg;
+ address.phy_addr = phy;
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_GB_MII_MGMT_ADDR(0), &address);
+
+ *(netxen_crbword_t *)&command = 0; /* turn off any prior activity */
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_GB_MII_MGMT_COMMAND(0), &command);
+
+ /* send read command */
+ command.read_cycle=1;
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_GB_MII_MGMT_COMMAND(0), &command);
+
+ *(netxen_crbword_t *)&status = 0;
+ do {
+ NetXen_CRB_READ_CHECK(NetXen_NIU_GB_MII_MGMT_INDICATE(0),&status);
+ timeout++;
+ } while ((status.busy || status.notvalid) && (timeout++ <
NetXen_NIU_PHY_WAITMAX));
+
+ if (timeout < NetXen_NIU_PHY_WAITMAX) {
+ NetXen_CRB_READ_CHECK(NetXen_NIU_GB_MII_MGMT_STATUS(0),readval);
+ result = 0;
+ }else {
+ result = -1;
+ }
+
+ if (restore)
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_GB_MAC_CONFIG_0(0), &mac_cfg0);
+
+ return (result);
+
+}
+/*
+ * netxen_niu_gbe_phy_write - write a register to the GbE PHY via
+ * mii management interface.
+ *
+ * Note: The MII management interface goes through port 0.
+ * Individual phys are addressed as follows:
+ * [15:8] phy id
+ * [7:0] register number
+ *
+ * Returns: 0 success
+ * -1 error
+ *
+ */
+long netxen_niu_gbe_phy_write (long phy, long reg, netxen_crbword_t val) {
+ netxen_niu_gb_mii_mgmt_address_t address;
+ netxen_niu_gb_mii_mgmt_command_t command;
+ netxen_niu_gb_mii_mgmt_indicators_t status;
+ long timeout=0;
+ long result = 0;
+ long restore = 0;
+ netxen_niu_gb_mac_config_0_t mac_cfg0;
+
+ /* MII mgmt all goes through port 0 MAC interface, so it cannot be in
reset */
+ NetXen_CRB_READ_CHECK(NetXen_NIU_GB_MAC_CONFIG_0(0), &mac_cfg0);
+ if (mac_cfg0.soft_reset) {
+ netxen_niu_gb_mac_config_0_t temp;
+ *(netxen_crbword_t *)&temp = 0;
+ temp.tx_reset_pb = 1;
+ temp.rx_reset_pb = 1;
+ temp.tx_reset_mac = 1;
+ temp.rx_reset_mac = 1;
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_GB_MAC_CONFIG_0(0), &temp );
+ restore = 1;
+ }
+
+ *(netxen_crbword_t *)&command = 0; /* turn off any prior activity */
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_GB_MII_MGMT_COMMAND(0), &command);
+
+ *(netxen_crbword_t *)&address = 0;
+ address.reg_addr = reg;
+ address.phy_addr = phy;
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_GB_MII_MGMT_ADDR(0), &address);
+
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_GB_MII_MGMT_CTRL(0), &val);
+
+
+ *(netxen_crbword_t *)&status = 0;
+ do {
+ NetXen_CRB_READ_CHECK(NetXen_NIU_GB_MII_MGMT_INDICATE(0),&status);
+ timeout++;
+ } while ((status.busy) && (timeout++ < NetXen_NIU_PHY_WAITMAX));
+
+ if (timeout < NetXen_NIU_PHY_WAITMAX) {
+ result = 0;
+ }else {
+ result = -1;
+ }
+
+ /* restore the state of port 0 MAC in case we tampered with it */
+ if (restore)
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_GB_MAC_CONFIG_0(0), &mac_cfg0);
+
+ return (result);
+
+}
+
+long netxen_niu_gbe_enable_phy_interrupts(long port) {
+ long result = 0;
+ netxen_niu_phy_interrupt_t enable;
+ *(netxen_crbword_t *)&enable = 0;
+ enable.link_status_changed = 1;
+ enable.autoneg_completed= 1;
+ enable.speed_changed = 1;
+ if (0 !=
netxen_niu_gbe_phy_write(port,NetXen_NIU_GB_MII_MGMT_ADDR_INT_ENABLE,*(netxen_crbword_t
*)&enable)) {
+ result = -1;
+ }
+ return result;
+}
+
+long netxen_niu_gbe_disable_phy_interrupts(long port) {
+ long result = 0;
+ if (0 !=
netxen_niu_gbe_phy_write(port,NetXen_NIU_GB_MII_MGMT_ADDR_INT_ENABLE,0)) {
+ result = -1;
+ }
+ return result;
+}
+long netxen_niu_gbe_clear_phy_interrupts(long port) {
+ long result = 0;
+ if (0 !=
netxen_niu_gbe_phy_write(port,NetXen_NIU_GB_MII_MGMT_ADDR_INT_STATUS,-1)) {
+ result = -1;
+ }
+ return result;
+}
+
+/*
+ * netxen_niu_gbe_set_mii_mode- Set 10/100 Mbit Mode for GbE MAC
+ *
+ */
+void netxen_niu_gbe_set_mii_mode(long port, long enable) {
+
+ NetXen_CRB_WRITELIT(NetXen_NIU_MODE, 0x2); /* Set mode to 2 */
+ NetXen_CRB_WRITELIT(NetXen_NIU_GB_MAC_CONFIG_0(port), 0x80000000);
+ NetXen_CRB_WRITELIT(NetXen_NIU_GB_MAC_CONFIG_0(port), 0x0000f0025);
+ NetXen_CRB_WRITELIT(NetXen_NIU_GB_MAC_CONFIG_1(port), 0xf1ff);
+ NetXen_CRB_WRITELIT(NetXen_NIU_GB0_GMII_MODE + (port << 3), 0);
+ NetXen_CRB_WRITELIT(NetXen_NIU_GB0_MII_MODE + (port << 3), 1);
+ NetXen_CRB_WRITELIT((NetXen_NIU_GB0_HALF_DUPLEX + port *4), 0);
+ NetXen_CRB_WRITELIT(NetXen_NIU_GB_MII_MGMT_CONFIG(port), 0x7);
+
+ if (enable) {
+ /* Do NOT enable flow control until a suitable solution for
+ * shutting down pause frames is found.
+ */
+ //NetXen_CRB_WRITELIT(NetXen_NIU_GB_MAC_CONFIG_0(port), 0x35);
+ NetXen_CRB_WRITELIT(NetXen_NIU_GB_MAC_CONFIG_0(port), 0x5);
+ }
+
+ if (netxen_niu_gbe_enable_phy_interrupts(port))
+ printf_0("ERROR enabling PHY interrupts\n");
+ if (netxen_niu_gbe_clear_phy_interrupts(port))
+ printf_0("ERROR clearing PHY interrupts\n");
+}
+
+/*
+ * netxen_niu_gbe_set_gmii_mode- Set GbE Mode for GbE MAC
+ */
+void netxen_niu_gbe_set_gmii_mode(long port, long enable) {
+ NetXen_CRB_WRITELIT(NetXen_NIU_MODE, 0x2); /* Set mode to 2 */
+ NetXen_CRB_WRITELIT(NetXen_NIU_GB_MAC_CONFIG_0(port), 0x80000000);
+ NetXen_CRB_WRITELIT(NetXen_NIU_GB_MAC_CONFIG_0(port), 0x0000f0025);
+ NetXen_CRB_WRITELIT(NetXen_NIU_GB_MAC_CONFIG_1(port), 0xf2ff);
+ NetXen_CRB_WRITELIT(NetXen_NIU_GB0_MII_MODE + (port << 3), 0);
+ NetXen_CRB_WRITELIT(NetXen_NIU_GB0_GMII_MODE + (port << 3), 1);
+ NetXen_CRB_WRITELIT((NetXen_NIU_GB0_HALF_DUPLEX + port *4), 0);
+ NetXen_CRB_WRITELIT(NetXen_NIU_GB_MII_MGMT_CONFIG(port), 0x7);
+
+ if (enable) {
+ /* Do NOT enable flow control until a suitable solution for
+ * shutting down pause frames is found.
+ */
+ //NetXen_CRB_WRITELIT(NetXen_NIU_GB_MAC_CONFIG_0(port), 0x35);
+ NetXen_CRB_WRITELIT(NetXen_NIU_GB_MAC_CONFIG_0(port), 0x5);
+ }
+
+ if (netxen_niu_gbe_enable_phy_interrupts(port))
+ printf_0("ERROR enabling PHY interrupts\n");
+ if (netxen_niu_gbe_clear_phy_interrupts(port))
+ printf_0("ERROR clearing PHY interrupts\n");
+}
+
+long netxen_niu_gbe_init_port(long port) {
+ long result = 0;
+
+ netxen_niu_phy_status_t status;
+#ifdef PHANTOM_PROTO_BOARD
+ /* no interrupts on proto board, so just enable it */
+ netxen_niu_gbe_set_gmii_mode(port, 1);
+#else
+ if (0 ==
netxen_niu_gbe_phy_read(port,NetXen_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
+ (netxen_crbword_t *)&status)) {
+ if (status.link) {
+ if (status.speed == 2) {
+ netxen_niu_gbe_set_gmii_mode(port, 1);
+ } else if ((status.speed == 1) || (status.speed == 0)) {
+ netxen_niu_gbe_set_mii_mode(port, 1);
+ } else {
+ result = -1;
+ }
+
+ } else {
+ /* We don't have link. Cable must be unconnected. */
+ /* Enable phy interrupts so we take action when plugged in */
+ NetXen_CRB_WRITELIT(NetXen_NIU_GB_MAC_CONFIG_0(port), 0x80000000);
+ NetXen_CRB_WRITELIT(NetXen_NIU_GB_MAC_CONFIG_0(port), 0x0000f0025);
+ if (netxen_niu_gbe_clear_phy_interrupts(port))
+ printf_0("ERROR clearing PHY interrupts\n");
+ if (netxen_niu_gbe_enable_phy_interrupts(port))
+ printf_0("ERROR enabling PHY interrupts\n");
+ if (netxen_niu_gbe_clear_phy_interrupts(port))
+ printf_0("ERROR clearing PHY interrupts\n");
+ result = -1;
+ }
+ } else {
+ result = -1;
+
+ }
+#endif /* ifdef PHANTOM_PROTO_BOARD */
+ return result;
+}
+
+/*
+ * netxen_niu_gbe_handle_phy_interrupt - Handles GbE PHY interrupts
+ * enable - 0 means don't enable the port
+ * 1 means enable (or re-enable) the port
+ */
+long
+netxen_niu_gbe_handle_phy_interrupt(long port, long enable) {
+ long result = 0;
+ netxen_niu_phy_interrupt_t int_src;
+
+ printf_2("HAL: Handling PHY interrupt on port %d (device enable =
%d)\n",(int)port, (int) enable);
+
+ /* The read of the PHY INT status will clear the pending interrupt status
*/
+ if (netxen_niu_gbe_phy_read(port,NetXen_NIU_GB_MII_MGMT_ADDR_INT_STATUS,
+ (netxen_crbword_t *)&int_src) != 0) {
+ result = -1;
+ } else {
+ printf_1("PHY Interrupt source = 0x%x \n",
+ *(__uint32_t*)&int_src);
+ if (int_src.jabber) {
+ printf_0("jabber Interrupt ");
+ }
+ if (int_src.polarity_changed) {
+ printf_0("polarity changed ");
+ }
+ if (int_src.energy_detect) {
+ printf_0("energy detect \n");
+ }
+ if (int_src.downshift) {
+ printf_0("downshift \n");
+ }
+ if (int_src.mdi_xover_changed) {
+ printf_0("mdi_xover_changed ");
+ }
+ if (int_src.fifo_over_underflow) {
+ printf_0("fifo_over_underflow ");
+ }
+ if (int_src.false_carrier) {
+ printf_0("false_carrier ");
+ }
+ if (int_src.symbol_error) {
+ printf_0("symbol_error ");
+ }
+ if (int_src.autoneg_completed) {
+ printf_0("autoneg_completed ");
+ }
+ if (int_src.page_received) {
+ printf_0("page_received ");
+ }
+ if (int_src.duplex_changed) {
+ printf_0("duplex_changed ");
+ }
+ if (int_src.autoneg_error) {
+ printf_0("autoneg_error ");
+ }
+ if ((int_src.speed_changed) || (int_src.link_status_changed)){
+ netxen_niu_phy_status_t status;
+
+ printf_0("speed_changed or link status changed");
+ if
(netxen_niu_gbe_phy_read(port,NetXen_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
+ (netxen_crbword_t *)&status) == 0) {
+ printf_0("\n");
+ if (status.speed == 2) {
+ printf_0("Link speed changed to 1000 Mbps\n");
+ netxen_niu_gbe_set_gmii_mode(port,enable);
+ } else if (status.speed == 1) {
+ printf_0("Link speed changed to 100 Mbps\n");
+ netxen_niu_gbe_set_mii_mode(port,enable);
+ } else if (status.speed == 0) {
+ printf_0("Link speed changed to 10 Mbps\n");
+ netxen_niu_gbe_set_mii_mode(port, enable);
+ } else {
+ printf_0("ERROR reading PHY status. Illegal speed
setting.\n");
+ result = -1;
+ }
+ } else {
+ printf_0("ERROR reading PHY status.\n");
+ result = -1;
+ }
+
+ }
+ printf_0("\n");
+ }
+ return result;
+}
+
+/*
+ * Return the current station MAC address.
+ * Note that the passed-in value must already be in network byte order.
+ */
+int
+netxen_niu_macaddr_get(int phy, netxen_ethernet_macaddr_t *addr)
+{
+ netxen_niu_gb_station_address_high_t stationhigh;
+ netxen_niu_gb_station_address_low_t stationlow;
+ __uint64_t result;
+ unsigned long flags;
+
+ if (addr == NULL)
+ return -1;
+ if ((phy < 0) || (phy > 3))
+ return -1;
+
+ flags= netxen_xport_lock();
+#if !defined(XG_MAC)
+ NetXen_CRB_READ_CHECK(NetXen_NIU_GB_STATION_ADDR_0(phy), &stationhigh);
+ NetXen_CRB_READ_CHECK(NetXen_NIU_GB_STATION_ADDR_1(phy), &stationlow);
+#else
+ NetXen_CRB_READ_CHECK(NetXen_NIU_XGE_STATION_ADDR_0_HI, &stationhigh);
+ NetXen_CRB_READ_CHECK(NetXen_NIU_XGE_STATION_ADDR_0_1, &stationlow);
+#endif /* XG_MAC */
+
+ result = (__uint64_t)stationlow.address;
+ result |= (__uint64_t)stationhigh.address << 16;
+ memcpy(*addr,&result,sizeof(netxen_ethernet_macaddr_t));
+ netxen_xport_unlock(flags);
+
+ return 0;
+}
+
+/*
+ * Set the station MAC address.
+ * Note that the passed-in value must already be in network byte order.
+ */
+int
+netxen_niu_macaddr_set(int phy, netxen_ethernet_macaddr_t addr)
+{
+ netxen_crbword_t temp = 0;
+ unsigned long flags;
+
+ if ((phy < 0) || (phy > 3))
+ return -1;
+
+ flags=netxen_xport_lock();
+
+ memcpy(&temp,addr,2);
+ temp <<= 16;
+#if !defined(XG_MAC)
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_GB_STATION_ADDR_1(phy), &temp);
+#else
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_XGE_STATION_ADDR_0_1, &temp);
+#endif /* XG_MAC */
+
+ temp = 0;
+
+ memcpy(&temp,((__uint8_t *)addr)+2,sizeof(netxen_crbword_t));
+#if !defined(XG_MAC)
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_GB_STATION_ADDR_0(phy), &temp);
+#else
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_XGE_STATION_ADDR_0_HI, &temp);
+#endif /* XG_MAC */
+
+ netxen_xport_unlock(flags);
+
+ return 0;
+}
+
+/* Enable a GbE interface */
+native_t netxen_niu_enable_gbe_port(native_t port, netxen_niu_gbe_ifmode_t
mode) {
+ netxen_niu_gb_mac_config_0_t mac_cfg0;
+ netxen_niu_gb_mac_config_1_t mac_cfg1;
+ netxen_niu_gb_mii_mgmt_config_t mii_cfg;
+
+ if ((port < 0) || (port > NetXen_NIU_MAX_GBE_PORTS)) {
+ return -1;
+ }
+ *(netxen_crbword_t *)&mac_cfg0 = 0;
+ mac_cfg0.soft_reset = 1;
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_GB_MAC_CONFIG_0(port), &mac_cfg0);
+
+ *(netxen_crbword_t *)&mac_cfg0 = 0;
+ mac_cfg0.tx_enable = 1;
+ mac_cfg0.rx_enable = 1;
+ mac_cfg0.rx_flowctl = 0;
+ mac_cfg0.tx_reset_pb = 1;
+ mac_cfg0.rx_reset_pb = 1;
+ mac_cfg0.tx_reset_mac = 1;
+ mac_cfg0.rx_reset_mac = 1;
+
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_GB_MAC_CONFIG_0(port), &mac_cfg0);
+
+ *(netxen_crbword_t *)&mac_cfg1 = 0;
+ mac_cfg1.preamblelen = 0xf;
+ mac_cfg1.duplex=1;
+ mac_cfg1.crc_enable=1;
+ mac_cfg1.padshort=1;
+ mac_cfg1.checklength=1;
+ mac_cfg1.hugeframes=1;
+
+ if (mode == NetXen_NIU_10_100_MB) {
+ mac_cfg1.intfmode=1;
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_GB_MAC_CONFIG_1(port), &mac_cfg1);
+
+ /* set mii mode */
+ NetXen_CRB_WRITELIT(NetXen_NIU_GB0_GMII_MODE + (port << 3), 0);
+ NetXen_CRB_WRITELIT(NetXen_NIU_GB0_MII_MODE + (port << 3), 1);
+
+ } else if (mode == NetXen_NIU_1000_MB) {
+ mac_cfg1.intfmode=2;
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_GB_MAC_CONFIG_1(port), &mac_cfg1);
+ /* set gmii mode */
+ NetXen_CRB_WRITELIT(NetXen_NIU_GB0_MII_MODE + (port << 3), 0);
+ NetXen_CRB_WRITELIT(NetXen_NIU_GB0_GMII_MODE + (port << 3), 1);
+ }
+ *(netxen_crbword_t *)&mii_cfg = 0;
+ mii_cfg.clockselect = 7;
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_GB_MII_MGMT_CONFIG(port), &mii_cfg);
+
+ *(netxen_crbword_t *)&mac_cfg0 = 0;
+ mac_cfg0.tx_enable = 1;
+ mac_cfg0.rx_enable = 1;
+ mac_cfg0.tx_flowctl = 0;
+ mac_cfg0.rx_flowctl = 0;
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_GB_MAC_CONFIG_0(port), &mac_cfg0);
+ return 0;
+}
+
+/* Disable a GbE interface */
+native_t netxen_niu_disable_gbe_port(native_t port) {
+ netxen_niu_gb_mac_config_0_t mac_cfg0;
+ if ((port < 0) || (port > NetXen_NIU_MAX_GBE_PORTS)) {
+ return -1;
+ }
+ *(netxen_crbword_t *)&mac_cfg0 = 0;
+ mac_cfg0.soft_reset = 1;
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_GB_MAC_CONFIG_0(port), &mac_cfg0);
+ return 0;
+}
+
+/* Disable an XG interface */
+native_t netxen_niu_disable_xg_port(native_t port) {
+ netxen_niu_xg_mac_config_0_t mac_cfg;
+ if (port != 0) {
+ return -1;
+ }
+ *(netxen_crbword_t *)&mac_cfg = 0;
+ mac_cfg.soft_reset = 1;
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_XGE_CONFIG_0, &mac_cfg);
+ return 0;
+}
+
+
+/* Set promiscuous mode for a GbE interface */
+native_t netxen_niu_set_promiscuous_mode(native_t port, netxen_niu_prom_mode_t
mode) {
+ netxen_niu_gb_drop_crc_t reg;
+ native_t data;
+ if ((port < 0) || (port > NetXen_NIU_MAX_GBE_PORTS)) {
+ return -1;
+ }
+ if (mode == NetXen_NIU_PROMISCOUS_MODE) {
+ data = 0;
+ } else {
+ data = 1;
+ }
+ /* save previous contents */
+ NetXen_CRB_READ_CHECK(NetXen_NIU_GB_DROP_WRONGADDR, ®);
+ switch (port) {
+ case 0:
+ reg.drop_gb0 = data;
+ break;
+ case 1:
+ reg.drop_gb0 = data;
+ break;
+ case 2:
+ reg.drop_gb0 = data;
+ break;
+ case 3:
+ reg.drop_gb0 = data;
+ break;
+ default:
+ return -1;
+ }
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_GB_DROP_WRONGADDR, ®);
+ return 0;
+}
+/******************************************************************************
+*
+* Initialize the XG interface
+*
+*******************************************************************************
+*/
+long netxen_niu_xginit(void) {
+ long i, timeout, val;
+ long rv=0;
+ long srebufctl;
+
+ // select the xg interface serdes
+ NetXen_CRB_WRITELIT(NetXen_NIU_XG_SEL,0);
+
+ //big fifo rst
+ NetXen_CRB_WRITELIT(NetXen_NIU_RESET_SYS_FIFOS,0x80000001);
+
+ //setting for b0
+ //wrreg 0x006000a0 0xc80
+ NetXen_CRB_WRITELIT(NetXen_CRB_NIU+0xa0, 0xc80);
+ //setting for a2
+ //wrreg 0x006000a0 0x300
+ //NetXen_CRB_WRITELIT(NetXen_CRB_NIU+0xa0, 0x300);
+
+ //xg mode
+ NetXen_CRB_WRITELIT(NetXen_NIU_MODE,1);
+ NetXen_CRB_WRITELIT(NetXen_NIU_XG_SINGLE_TERM,1);
+
+ // do byte allign
+ NetXen_CRB_WRITELIT(NetXen_NIU_XG_DO_BYTE_ALIGN,0xf);
+ // Word allign
+
+ // Equalization setting for copper
+ NetXen_CRB_WRITELIT(NetXen_NIU_XG_DEQ,0x7777);
+
+
+ // reset the MAC
+ NetXen_CRB_WRITELIT(NetXen_NIU_XGE_CONFIG_0,0xf8000010);
+
+
+ //---------------- Serdes Bring up -------------
+ // xg PwrdnAB
+ NetXen_CRB_WRITELIT(NetXen_NIU_XG_POWER_DOWN,0xfffe);
+ DELAY(10000);
+
+ //xg resetPLLAB
+ NetXen_CRB_WRITELIT(NetXen_NIU_XG_RESET_PLL,0xfffe);
+ DELAY(10000);
+
+ // xg ResetAB
+ NetXen_CRB_WRITELIT(NetXen_NIU_XG_RESET,0xfffe);
+ DELAY(10000);
+
+ // xg PwrdnCD
+ NetXen_CRB_WRITELIT(NetXen_NIU_XG_POWER_DOWN,0xfffc);
+ DELAY(10000);
+
+ // xg resetPLLCD
+ NetXen_CRB_WRITELIT(NetXen_NIU_XG_RESET_PLL,0xfffc);
+ DELAY(10000);
+
+ // xg ResetCD
+ NetXen_CRB_WRITELIT(NetXen_NIU_XG_RESET,0xfffc);
+ DELAY(10000);
+
+ //Enable xgmii_xaui Tx, Rx FIFOs
+ NetXen_CRB_WRITELIT(NetXen_NIU_XG_TX_ENABLE,1);
+ NetXen_CRB_WRITELIT(NetXen_NIU_XG_RX_ENABLE,1);
+
+
+ // turn on free-run in SRE for next part
+ srebufctl = NetXen_CRB_READ_VAL(NetXen_SRE_BUF_CTL);
+ NetXen_CRB_WRITELIT(NetXen_SRE_BUF_CTL, srebufctl | 0x2);
+
+ // Enable Tx only
+ NetXen_CRB_WRITELIT(NetXen_NIU_XGE_CONFIG_0,1);
+
+
+ val=0;
+ timeout= 1000000;
+ for (i=0; i < timeout;i++) {
+ long prev=val;
+
+ val=NetXen_CRB_READ_VAL(NetXen_NIU_XG_STATUS);
+
+ if ((val & 0xf0) == 0xf0) {
+ break;
+ } else {
+ if (prev != val) {
+ printf_1("Reg 0x38 == 0x%08lx\n",val);
+ }
+
+ }
+ }
+
+ if ((val & 0xf0) == 0xf0) {
+ } else {
+ printf_0("NetXen NIU XGINIT: NIU ERROR! Lanes Not Synced!\n");
+ return -1;
+ }
+
+ val=0;
+ timeout= 10;
+ for (i=0; i < timeout;i++) {
+ long prev=val;
+
+ val=NetXen_CRB_READ_VAL(NetXen_NIU_XG_STATUS);
+
+ if ((val & 0xfff) == 0xffb) {
+ break;
+ } else {
+ if (prev != val) {
+ printf_1("Reg 0x38 == 0x%08lx\n",val);
+ }
+
+ }
+ }
+ //reset the rambus serdes parallel interface
+ //wrreg 0x0060001c 0x3
+ NetXen_CRB_WRITELIT(NetXen_NIU_XG_RESET, 0x3);
+ //wrreg 0x0060001c 0x0
+ NetXen_CRB_WRITELIT(NetXen_NIU_XG_RESET, 0x0);
+
+/* if ((val & 0xfff) == 0xffb) {
+ printf_1("NetXen NIU XGINIT: Byte Align Done after %ld iterations!\n",
i);
+ } else {
+ printf_0("NetXen NIU XGINIT: NIU ERROR! Byte Align not done!\n");
+ rv = -1;
+ }*/
+ if ((val & 0xfff) != 0xffb) {
+ printf_0("NetXen NIU XGINIT: NIU ERROR! Byte Align not done!\n");
+ rv = -1;
+ }
+
+ // unreset the MAC
+ NetXen_CRB_WRITELIT(NetXen_NIU_XGE_CONFIG_0,0);
+
+ // Enable Tx only
+ NetXen_CRB_WRITELIT(NetXen_NIU_XGE_CONFIG_0,1);
+
+
+ // XG Config 1 reg
+ NetXen_CRB_WRITELIT(NetXen_NIU_XGE_CONFIG_1,0x1467);
+ // Back to back IPG
+ NetXen_CRB_WRITELIT(NetXen_NIU_XGE_IPG,3);
+
+ // default mac addresses
+ NetXen_CRB_WRITELIT(NetXen_NIU_XGE_STATION_ADDR_0_HI,0xffffffff);
+ NetXen_CRB_WRITELIT(NetXen_NIU_XGE_STATION_ADDR_0_1,0xffffffff);
+ NetXen_CRB_WRITELIT(NetXen_NIU_XGE_STATION_ADDR_1_LO,0xdeadbeaf);
+
+ // Max frame size
+ NetXen_CRB_WRITELIT(NetXen_NIU_XGE_MAX_FRAME_SIZE,0x00001f40);
+
+ // pause on to pause off time gap
+ NetXen_CRB_WRITELIT(NetXen_NIU_XG_PAUSE_THRESHOLD,0x00200020);
+
+ // disable pause frames
+ NetXen_CRB_WRITELIT(NetXen_NIU_XG_PAUSE_CTL,0x9);
+
+ // pause frame value
+ NetXen_CRB_WRITELIT(NetXen_NIU_XGE_PAUSE_FRAME_VALUE,0x100);
+
+ // tx pause frame count
+ NetXen_CRB_WRITELIT(NetXen_NIU_XG_PAUSE_LEVEL,0x400);
+
+ // Reset and unreset ingress and egress afifos
+ // enable MAC and Tx/Rx
+ NetXen_CRB_WRITELIT(NetXen_NIU_XGE_CONFIG_0,0xc0000000);
+ NetXen_CRB_WRITELIT(NetXen_NIU_XGE_CONFIG_0,0xe5);
+
+
+ // check the MAC ready state
+ NetXen_CRB_WRITELIT(NetXen_NIU_TEST_MUX_CTL,0xc);
+ val=NetXen_CRB_READ_VAL(NetXen_CRB_NIU+0xc0);
+ //printf_1("MAC ready test mux is 0x%lx\n", val);
+
+ //big fifo rst
+ NetXen_CRB_WRITELIT(NetXen_NIU_RESET_SYS_FIFOS,0);
+
+ // undo the SRE Free run enable
+ NetXen_CRB_WRITELIT(NetXen_SRE_BUF_CTL, srebufctl );
+
+ return rv;
+}
+
+/*
+ * Set the MAC address for an XG port
+ * Note that the passed-in value must already be in network byte order.
+ */
+int
+netxen_niu_xg_macaddr_set(int phy, netxen_ethernet_macaddr_t addr)
+{
+ netxen_crbword_t temp = 0;
+ unsigned long flags;
+
+ if ((phy < 0) || (phy > 3))
+ return -1;
+
+ flags=netxen_xport_lock();
+
+ memcpy(&temp, addr, 2);
+ temp <<= 16;
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_XGE_STATION_ADDR_0_1, &temp);
+
+ temp = 0;
+
+ memcpy(&temp,((__uint8_t *)addr)+2,sizeof(netxen_crbword_t));
+ NetXen_CRB_WRITE_CHECK(NetXen_NIU_XGE_STATION_ADDR_0_HI, &temp);
+
+ netxen_xport_unlock(flags);
+
+ return 0;
+}
+/*
+ * Return the current station MAC address.
+ * Note that the passed-in value must already be in network byte order.
+ */
+int
+netxen_niu_xg_macaddr_get(int phy, netxen_ethernet_macaddr_t *addr)
+{
+ netxen_crbword_t stationhigh;
+ netxen_crbword_t stationlow;
+ __uint64_t result;
+ unsigned long flags;
+
+ if (addr == NULL)
+ return -1;
+ if (phy != 0)
+ return -1;
+
+ flags= netxen_xport_lock();
+ NetXen_CRB_READ_CHECK(NetXen_NIU_XGE_STATION_ADDR_0_HI, &stationhigh);
+ NetXen_CRB_READ_CHECK(NetXen_NIU_XGE_STATION_ADDR_0_1, &stationlow);
+
+ result = ((__uint64_t)stationlow) >> 16;
+ result |= (__uint64_t)stationhigh << 16;
+ memcpy(*addr,&result,sizeof(netxen_ethernet_macaddr_t));
+ netxen_xport_unlock(flags);
+
+ return 0;
+}
+
+
+native_t
+netxen_niu_xg_set_promiscuous_mode(native_t port, netxen_niu_prom_mode_t mode)
+{
+ unsigned long flags;
+ long reg;
+
+ flags=netxen_xport_lock();
+
+ if ((port < 0) || (port > NetXen_NIU_MAX_GBE_PORTS)) {
+ return -1;
+ }
+
+ NetXen_CRB_READ_CHECK(NetXen_NIU_XGE_CONFIG_1, ®);
+ if (mode == NetXen_NIU_PROMISCOUS_MODE) {
+ reg = (reg | 0x2000UL);
+ } else { /* FIXME use the correct mode value here*/
+ reg = (reg & ~0x2000UL);
+ }
+ NetXen_CRB_WRITELIT(NetXen_NIU_XGE_CONFIG_1, reg);
+
+ netxen_xport_unlock(flags);
+
+ return 0;
+}
+
+long netxen_niu_xg_enable_phy_interrupts(long port) {
+ NetXen_CRB_WRITELIT(NetXen_NIU_INT_MASK, 0x3f);
+ return 0;
+}
+
+long netxen_niu_xg_disable_phy_interrupts(long port) {
+ NetXen_CRB_WRITELIT(NetXen_NIU_INT_MASK, 0x7f);
+ return 0;
+}
+
+long netxen_niu_xg_clear_phy_interrupts(long port) {
+ NetXen_CRB_WRITELIT(NetXen_NIU_ACTIVE_INT, -1);
+ return 0;
+}
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html