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