diff -Naru linux-2.6.16_orig/drivers/net/netxen/netxen_nic_hw.c linux-2.6.16/drivers/net/netxen/netxen_nic_hw.c --- linux-2.6.16_orig/drivers/net/netxen/netxen_nic_hw.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.16/drivers/net/netxen/netxen_nic_hw.c 2006-03-24 14:13:57.000000000 -0800 @@ -0,0 +1,1077 @@ +/* + * 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 + */ +/* + * Source file for NIC routines to access the Phantom hardware + * + * $Id: netxen_nic_hw.c,v 1.66.6.15 2006/03/21 00:31:29 vijo Exp $ + * + */ +#include <linux/delay.h> +#include <linux/netdevice.h> +#include <linux/ethtool.h> +#include <linux/version.h> +#include "netxen_nic.h" +#include "netxen_nic_hw.h" +#include "nic_cmn.h" +#include "netxen_version.h" +#include "netxen_brdcfg.h" + +/* static unsigned long netxen_nic_pci_set_crbwindow(netxen_adapter *adapter, + u64 off); */ +static unsigned long netxen_nic_pci_set_window (unsigned long long pci_base, + unsigned long long addr); +extern struct netxen_adapter_s *g_adapter; +extern spinlock_t hal_lock; + +/* + * Changes the CRB window to the specified window. + */ +void +netxen_nic_pci_change_crbwindow(netxen_adapter *adapter, uint32_t wndw) +{ + netxen_pcix_crb_window_t window; + unsigned long offset; + uint32_t tmp; + + if (adapter->curr_window == wndw) { + return; + } + + /* + * Move the CRB window. + * We need to write to the "direct access" region of PCI + * to avoid a race condition where the window register has + * not been successfully written across CRB before the target + * register address is received by PCI. The direct region bypasses + * the CRB bus. + */ + /* + * NOTE: When B0 arrives, we can use direct access registers for + * better performance + */ + offset = adapter->ahw.pci_base + NetXen_PCIX_PH_REG(PCIX_CRB_WINDOW); + + *(netxen_crbword_t *)&window = 0; + window.addrbit = wndw; + NetXen_NIC_PCI_WRITE_32(*(unsigned int *)&window, (void*)(offset)); + + //printk("set crbw : 0x%08x\n",off); + /* MUST make sure window is set before we forge on... */ + while ((tmp = NetXen_NIC_PCI_READ_32((void*)offset)) != + *(uint32_t *)&window) { + printk(KERN_WARNING "%s: %s WARNING: CRB window value not " + "registered properly: 0x%08x.\n", + netxen_nic_driver_name, __FUNCTION__, tmp); + } + + adapter->curr_window = wndw; + return; +} + +/* + * Set the CRB window based on the offset. + */ +static inline unsigned long +netxen_nic_pci_set_crbwindow(netxen_adapter *adapter, u64 off) +{ + /* + * See if we are currently pointing to the region we want to use next. + */ + + if ((off >= NetXen_CRB_PCIX_HOST) && (off < NetXen_CRB_DDR_NET)) { + /* + * No need to change window. PCIX and PCIE regs are in both + * windows. + */ + return (off); + } + + if ((off >= NetXen_CRB_PCIX_HOST) && (off < NetXen_CRB_PCIX_HOST2)) { + /* We are in first CRB window */ + if (adapter->curr_window != 0) { + netxen_nic_pci_change_crbwindow(adapter, 0); + } + return (off); + } + + if ((off > NetXen_CRB_PCIX_HOST2) && (off < NetXen_CRB_MAX)) { + /* We are in second CRB window */ + off = off - NetXen_CRB_PCIX_HOST2 + NetXen_CRB_PCIX_HOST; + + if (adapter->curr_window != 1) { + netxen_nic_pci_change_crbwindow(adapter, 1); + } + return (off); + } + + if ((off >= NetXen_PCI_DIRECT_CRB) && (off < NetXen_PCI_CAMQM_MAX)) { + /* + * We are in the QM or direct access register region - do + * nothing + */ + return (off); + } + + /* strange address given */ + dump_stack(); + printk(KERN_WARNING"%s: Warning: netxen_nic_pci_set_crbwindow called with" + " an unknown address(%llx)\n", netxen_nic_driver_name, off); + + return (off); +} + +int +netxen_nic_hw_write_wx(netxen_adapter *adapter, u64 off, void *data, int len) +{//This is modified from _netxen_nic_hw_write()._netxen_nic_hw_write does not exist now. + void *addr; + unsigned long flags=0; + + if(ADDR_IN_WINDOW1(off)) + {//Window 1 + addr = CRB_NORMALIZE(adapter, off); + read_lock(&adapter->adapter_lock); + } + else{//Window 0 + addr = (void *)(uptr_t)(adapter->ahw.pci_base + off); + write_lock_irqsave(&adapter->adapter_lock, flags); + netxen_nic_pci_change_crbwindow(adapter, 0); + } + + + DPRINTK(1, INFO, "writing to base %lx offset %llx addr %p" + " data %llx len %d\n", + adapter->ahw.pci_base, off, addr, + *(unsigned long long *)data, len); + switch (len) { + case 1: + NetXen_NIC_PCI_WRITE_8 (*(__uint8_t *)data, addr); + break; + case 2: + NetXen_NIC_PCI_WRITE_16 (*(__uint16_t *)data, addr); + break; + case 4: + NetXen_NIC_PCI_WRITE_32 (*(__uint32_t *)data, addr); + break; + case 8: + NetXen_NIC_PCI_WRITE_64 (*(__uint64_t *)data, addr); + break; + default: +#if !defined(NDEBUG) + if ((len & 0x7) != 0) + printk("%s: %s len(%d) not multiple of 8.\n", + netxen_nic_driver_name, __FUNCTION__, len); +#endif + DPRINTK(1, INFO, "writing data %lx to offset %llx, num words=%d\n", + *(unsigned long *)data, off, (len>>3)); + + NetXen_NIC_HW_BLOCK_WRITE_64(data, addr, (len>>3)); + break; + } + if(ADDR_IN_WINDOW1(off)) + {//Window 1 + read_unlock(&adapter->adapter_lock); + } + else{//Window 0 + netxen_nic_pci_change_crbwindow(adapter, 1); + write_unlock_irqrestore(&adapter->adapter_lock, flags); + } + + return 0; +} + +int +netxen_nic_hw_read_wx (netxen_adapter *adapter, u64 off, void *data, int len) +{ + void *addr; + unsigned long flags=0; + + if(ADDR_IN_WINDOW1(off)) + {//Window 1 + addr = CRB_NORMALIZE(adapter, off); + read_lock(&adapter->adapter_lock); + } + else{//Window 0 + addr = (void *)(uptr_t)(adapter->ahw.pci_base + off); + write_lock_irqsave(&adapter->adapter_lock, flags); + netxen_nic_pci_change_crbwindow(adapter, 0); + } + + DPRINTK(1, INFO, "reading from base %lx offset %llx addr %p\n", + adapter->ahw.pci_base, off, addr); + switch (len) { + case 1: + *(__uint8_t *)data = NetXen_NIC_PCI_READ_8(addr); + break; + case 2: + *(__uint16_t *)data = NetXen_NIC_PCI_READ_16(addr); + break; + case 4: + *(__uint32_t *)data = NetXen_NIC_PCI_READ_32(addr); + break; + case 8: + *(__uint64_t *)data = NetXen_NIC_PCI_READ_64(addr); + break; + default: +#if !defined(NDEBUG) + if ((len & 0x7) != 0) + printk("%s: %s len(%d) not multiple of 8.\n", + netxen_nic_driver_name, __FUNCTION__, len); +#endif + NetXen_NIC_HW_BLOCK_READ_64(data, addr, (len>>3)); + break; + } + DPRINTK(1, INFO, "read %lx\n", *(unsigned long *)data); + + if(ADDR_IN_WINDOW1(off)) + {//Window 1 + read_unlock(&adapter->adapter_lock); + } + else{//Window 0 + netxen_nic_pci_change_crbwindow(adapter, 1); + write_unlock_irqrestore(&adapter->adapter_lock, flags); + } + + return 0; +} + +/* PCI Windowing for DDR regions. */ + +#define ADDR_IN_RANGE(addr, low, high) \ + (((addr) <= (high)) && ((addr) >= (low))) + +int netxen_pci_set_window_warning_count = 0; + +static unsigned long +netxen_nic_pci_set_window (unsigned long long pci_base, unsigned long long addr) +{ + static int ddr_mn_window=-1; + static int qdr_sn_window=-1; + int window; + + /* printk("addr: %lx\n", addr); */ + if (ADDR_IN_RANGE(addr, NetXen_ADDR_DDR_NET, NetXen_ADDR_DDR_NET_MAX)) { + /* DDR network side */ + /* printk("MN DDR\n"); */ + addr -= NetXen_ADDR_DDR_NET; + window = (addr >> 25 ) & 0x3ff; + if (ddr_mn_window != window) { + /* printk("Change the MN window!!! \n"); */ + ddr_mn_window = window; + NetXen_NIC_PCI_WRITE_32(window, (void *)(uptr_t)(pci_base + + NetXen_PCIX_PH_REG(PCIX_MN_WINDOW))); + /* MUST make sure window is set before we forge on... */ + NetXen_NIC_PCI_READ_32((void *)(uptr_t)(pci_base + + NetXen_PCIX_PH_REG(PCIX_MN_WINDOW))); + } + addr -= (window * 0x2000000); + addr+= NetXen_PCI_DDR_NET; + } else if (ADDR_IN_RANGE(addr, NetXen_ADDR_OCM0, NetXen_ADDR_OCM0_MAX)) { + addr -= NetXen_ADDR_OCM0; + addr += NetXen_PCI_OCM0; + } else if (ADDR_IN_RANGE(addr, NetXen_ADDR_OCM1, NetXen_ADDR_OCM1_MAX)) { + addr -= NetXen_ADDR_OCM1; + addr += NetXen_PCI_OCM1; + } else if (ADDR_IN_RANGE(addr, NetXen_ADDR_QDR_NET, NetXen_ADDR_QDR_NET_MAX)) { + /* printk("SN QDR\n"); */ + /* QDR network side */ + addr -= NetXen_ADDR_QDR_NET; + window = (addr >> 22 ) & 0x3f; + if (qdr_sn_window != window) { + /* printk("Change the SN window!!! \n"); */ + qdr_sn_window = window; + NetXen_NIC_PCI_WRITE_32((window << 22), + (void *)(uptr_t)(pci_base + + NetXen_PCIX_PH_REG(PCIX_SN_WINDOW))); + /* MUST make sure window is set before we forge on... */ + NetXen_NIC_PCI_READ_32((void *)(uptr_t)(pci_base + + NetXen_PCIX_PH_REG(PCIX_SN_WINDOW))); + } + addr -= (window * 0x400000); + addr+= NetXen_PCI_QDR_NET; + } else { + /* + * peg gdb frequently accesses memory that doesn't exist, + * this limits the chit chat so debugging isn't slowed down. + */ + if((netxen_pci_set_window_warning_count++ < 8) + || (netxen_pci_set_window_warning_count%64 == 0)) { + printk("%s: Warning:netxen_nic_pci_set_window()" + " Unknown address range!\n", netxen_nic_driver_name); + } + } + /* printk("New address: 0x%08lx\n",addr); */ + return addr; +} + +/* read num_words from hardware (num_words in 64 bits */ +void +netxen_nic_mem_block_read(struct netxen_adapter_s *adapter, u64 off, + void *data, int num_words) +{ + void *addr; + unsigned long flags; + + write_lock_irqsave(&adapter->adapter_lock, flags); + off = netxen_nic_pci_set_window(adapter->ahw.pci_base, off); + addr = (void *)(uptr_t)(adapter->ahw.pci_base + off); + DPRINTK(1, INFO, "reading from base %lx offset %lx addr %p\n", + adapter->ahw.pci_base, (unsigned long)off, addr); + NetXen_NIC_HW_BLOCK_READ_64(data, addr, num_words); + write_unlock_irqrestore(&adapter->adapter_lock, flags); + + return; +} + +/* Write num_words (in 64 bits) in the phantom memory */ +/*void +netxen_nic_mem_block_write(struct netxen_adapter_s *adapter, u64 off, + void *data, int num_words) +{ + void *addr; + unsigned long flags; + + write_lock_irqsave(&adapter->adapter_lock, flags); + off = netxen_nic_pci_set_window(adapter->ahw.pci_base, off); + addr = (void *)(uptr_t)(off + adapter->ahw.pci_base); + DPRINTK(1, INFO, "writing data %lx to offset %lx\n", + *(unsigned long *)data, (unsigned long)off); + NetXen_NIC_HW_BLOCK_WRITE_64(data, addr, num_words); + write_unlock_irqrestore(&adapter->adapter_lock, flags); + + return; +}*/ +int +netxen_nic_pci_mem_write(struct netxen_adapter_s *adapter, u64 off, + void *data, int size) +{ + unsigned long flags; + void *addr; + int ret = 0; + + write_lock_irqsave(&adapter->adapter_lock, flags); + off = netxen_nic_pci_set_window(adapter->ahw.pci_base, off); + addr = (void *)(uptr_t)(adapter->ahw.pci_base + off); + DPRINTK(1, INFO, "writing data %llx to offset %llx\n", + *(unsigned long long *)data, off); + switch (size) { + case 1: + NetXen_NIC_PCI_WRITE_8( *(__uint8_t *)data, addr); + break; + case 2: + NetXen_NIC_PCI_WRITE_16(*(__uint16_t *)data, addr); + break; + case 4: + NetXen_NIC_PCI_WRITE_32(*(__uint32_t *)data, addr); + break; + case 8: + NetXen_NIC_PCI_WRITE_64(*(__uint64_t *)data, addr); + break; + default: + ret = 1; + break; + } + write_unlock_irqrestore(&adapter->adapter_lock, flags); + DPRINTK(1, INFO, "wrote %llx\n", *(unsigned long long*)data); + + return ret; +} + +int +netxen_nic_pci_mem_read(struct netxen_adapter_s *adapter, + u64 off, void *data, int size) +{ + unsigned long flags; + void *addr; + int ret = 0; + + write_lock_irqsave(&adapter->adapter_lock, flags); + off = netxen_nic_pci_set_window(adapter->ahw.pci_base, off); + addr = (void *)(uptr_t)(adapter->ahw.pci_base + off); + switch (size) { + case 1: + *(__uint8_t *)data = NetXen_NIC_PCI_READ_8(addr); + break; + case 2: + *(__uint16_t *)data = NetXen_NIC_PCI_READ_16(addr); + break; + case 4: + *(__uint32_t *)data = NetXen_NIC_PCI_READ_32(addr); + break; + case 8: + *(__uint64_t *)data = NetXen_NIC_PCI_READ_64(addr); + break; + default: + ret = 1; + break; + } + write_unlock_irqrestore(&adapter->adapter_lock, flags); + DPRINTK(1, INFO, "read %llx\n", *(unsigned long long*)data); + + return ret; +} +/* + *static void + *netxen_load_cam_ram(struct netxen_adapter_s *adapter) + *{ + * DPRINTK(1, INFO, "writing to LOAD CAM RAM.....START \n"); + * netxen_nic_reg_write(adapter, NetXen_CRB_CAM + 0x2000, 0); + * // may be we need to have some value for bootpeg - IND + * + * // Hw bug - needs an extra write after reset + * netxen_nic_reg_write(adapter, NetXen_CRB_CAM + 0x2000, 0); + * // one more for good measure + * netxen_nic_reg_write(adapter, NetXen_CRB_CAM + 0x2000, 0); + * + * return; + *} +*/ + +int +netxen_nic_get_board_info(struct netxen_adapter_s *adapter) +{ + int rv=0; + netxen_board_info_t *boardinfo; + int i; + int addr = 0x4000; + uint32_t *ptr32; + + boardinfo = &adapter->ahw.boardcfg; + ptr32 = (uint32_t *)boardinfo; + + for (i=0;i<sizeof(netxen_board_info_t)/sizeof(uint32_t);i++) { + *ptr32++ = rom_fast_read(adapter, addr); + //printk("ROM: %x\n",*ptr32); + addr+= sizeof(uint32_t); + } + if (boardinfo->magic != NetXen_BDINFO_MAGIC) { + printk("%s: ERROR reading %s board config." + " Read %x, expected %x\n", netxen_nic_driver_name, + netxen_nic_driver_name, + boardinfo->magic, NetXen_BDINFO_MAGIC); + rv=-1; + } + if (boardinfo->header_version != NetXen_BDINFO_VERSION) { + printk("%s: Unknown board config version." + " Read %x, expected %x\n", netxen_nic_driver_name, + boardinfo->header_version, NetXen_BDINFO_VERSION); + rv=-1; + } + + DPRINTK(1, INFO, "Discovered board type:0x%x ",boardinfo->board_type); + switch((netxen_brdtype_t)boardinfo->board_type){ + case NetXen_BRDTYPE_P2_SB35_4G: + adapter->ahw.board_type = NetXen_NIC_GBE; + break; + case NetXen_BRDTYPE_P2_SB31_10G: + case NetXen_BRDTYPE_P2_SB31_10G_IMEZ: + case NetXen_BRDTYPE_P2_SB31_10G_HMEZ: + case NetXen_BRDTYPE_P2_SB31_10G_CX4: + adapter->ahw.board_type = NetXen_NIC_XGBE; + break; + case NetXen_BRDTYPE_P1_BD: + case NetXen_BRDTYPE_P1_SB: + case NetXen_BRDTYPE_P1_SMAX: + case NetXen_BRDTYPE_P1_SOCK: + adapter->ahw.board_type = NetXen_NIC_GBE; + break; + default: + printk("%s: Unknown(%x)\n", netxen_nic_driver_name, + boardinfo->board_type); + break; + } + + return rv; +} + +int +netxen_nic_get_board_num(netxen_adapter *adapter) +{ + return adapter->ahw.boardcfg.board_num; +} + +/* NIU access sections */ + +/* Set the MAC address for a port */ +int +netxen_nic_macaddr_set(struct netxen_port *port, __uint8_t *addr) +{ + struct netxen_adapter_s *adapter = port->adapter; + int phy = port->portnum, ret = 0; + unsigned long flags; + + if ((phy < 0) || (phy > 3)) + return -1; + + switch (adapter->ahw.board_type) { + case NetXen_NIC_GBE: + spin_lock_irqsave(&hal_lock, flags); + g_adapter = adapter; + ret = netxen_niu_macaddr_set(phy, addr); + spin_unlock_irqrestore(&hal_lock, flags); + break; + + case NetXen_NIC_XGBE: + spin_lock_irqsave(&hal_lock, flags); + g_adapter = adapter; + ret = netxen_niu_xg_macaddr_set(phy, addr); + spin_unlock_irqrestore(&hal_lock, flags); + break; + + default: + dump_stack(); + printk(KERN_ERR "%s: Unknown board type\n",netxen_nic_driver_name); + } + + return ret; +} + +/* Return the current MAC address of the given port. */ +int +netxen_nic_macaddr_get(struct netxen_port *port, __uint8_t **addr) +{ + struct netxen_adapter_s *adapter = port->adapter; + int phy = port->portnum; + int ret = 0; + unsigned long flags; + + if (addr == NULL) + return -1; + if ((phy < 0) || (phy > 3)) + return -1; + + switch (adapter->ahw.board_type) { + case NetXen_NIC_GBE: + spin_lock_irqsave(&hal_lock, flags); + g_adapter = adapter; + ret = netxen_niu_macaddr_get(phy, (netxen_ethernet_macaddr_t *)*addr); + spin_unlock_irqrestore(&hal_lock, flags); + break; + + case NetXen_NIC_XGBE: + printk(KERN_ERR "%s: Function %s is not implemented for XG\n", + netxen_nic_driver_name,__FUNCTION__); + break; + + default: + printk(KERN_ERR "%s: Unknown board type\n",netxen_nic_driver_name); + ret = -1; + } + + return ret; +} + +int +netxen_nic_set_mtu(struct netxen_port *port, int new_mtu) +{ + struct netxen_adapter_s *adapter = port->adapter; + int ret = 0; + + switch (adapter->ahw.board_type) { + case NetXen_NIC_GBE: + /*netxen_nic_hw_write(adapter, + NetXen_NIU_GB_MAX_FRAME_SIZE(port->portnum), + &new_mtu, 4);*/ + netxen_nic_write_w0 ( + adapter,NetXen_NIU_GB_MAX_FRAME_SIZE(port->portnum), + new_mtu); + + break; + + case NetXen_NIC_XGBE: + new_mtu += 100; /* so that MAC accepts frames > MTU */ + /*netxen_nic_hw_write(adapter, NetXen_NIU_XGE_MAX_FRAME_SIZE, + &new_mtu, 4);*/ + netxen_nic_write_w0 (adapter, NetXen_NIU_XGE_MAX_FRAME_SIZE, new_mtu); + break; + + default: + printk(KERN_ERR "%s: Unknown board type\n",netxen_nic_driver_name); + } + + return ret; +} + +int +netxen_nic_set_promisc_mode(struct netxen_port *port) +{ + struct netxen_adapter_s *adapter = port->adapter; + int phy = port->portnum; + int ret = 0; + unsigned long flags; + if ((phy < 0) || (phy > 3)) + return -1; + + switch (adapter->ahw.board_type) { + case NetXen_NIC_GBE: + spin_lock_irqsave(&hal_lock, flags); + g_adapter = adapter; + ret = netxen_niu_set_promiscuous_mode(phy, + NetXen_NIU_PROMISCOUS_MODE); + spin_unlock_irqrestore(&hal_lock, flags); + break; + + case NetXen_NIC_XGBE: + spin_lock_irqsave(&hal_lock, flags); + g_adapter = adapter; + ret = netxen_niu_xg_set_promiscuous_mode(phy, + NetXen_NIU_PROMISCOUS_MODE); + spin_unlock_irqrestore(&hal_lock, flags); + break; + + default: + printk(KERN_ERR "%s: Unknown board type\n",netxen_nic_driver_name); + } + + return ret; +} + +int +netxen_nic_unset_promisc_mode(struct netxen_port *port) +{ + struct netxen_adapter_s *adapter = port->adapter; + int phy = port->portnum; + int ret = -1; + unsigned long flags; + + if ((phy < 0) || (phy > 3)) + return -1; + + switch (adapter->ahw.board_type) { + case NetXen_NIC_GBE: + spin_lock_irqsave(&hal_lock, flags); + g_adapter = adapter; + ret = netxen_niu_set_promiscuous_mode(phy, + NetXen_NIU_NON_PROMISCOUS_MODE); + spin_unlock_irqrestore(&hal_lock, flags); + break; + + case NetXen_NIC_XGBE: + spin_lock_irqsave(&hal_lock, flags); + g_adapter = adapter; + ret = netxen_niu_xg_set_promiscuous_mode(phy, + NetXen_NIU_NON_PROMISCOUS_MODE); + spin_unlock_irqrestore(&hal_lock, flags); + break; + + default: + printk(KERN_ERR "%s: Unknown board type\n",netxen_nic_driver_name); + } + + return ret; +} + +long +netxen_nic_phy_read (netxen_adapter *adapter, long phy, long reg, + __uint32_t *readval) +{ + long ret = 0; + unsigned long flags; + + switch (adapter->ahw.board_type) { + case NetXen_NIC_GBE: + spin_lock_irqsave(&hal_lock, flags); + g_adapter = adapter; + ret = netxen_niu_gbe_phy_read (phy, reg, readval); + spin_unlock_irqrestore(&hal_lock, flags); + break; + + case NetXen_NIC_XGBE: + printk(KERN_ERR "%s: Function %s is not implemented for XG\n", + netxen_nic_driver_name,__FUNCTION__); + break; + + default: + printk(KERN_ERR "%s: Unknown board type\n",netxen_nic_driver_name); + } + + return ret; +} + +long +netxen_nic_phy_write (netxen_adapter *adapter, long phy, long reg, __uint32_t val) +{ + long ret = 0; + unsigned long flags; + + switch (adapter->ahw.board_type) { + case NetXen_NIC_GBE: + spin_lock_irqsave(&hal_lock, flags); + g_adapter = adapter; + ret = netxen_niu_gbe_phy_write (phy, reg, val); + spin_unlock_irqrestore(&hal_lock, flags); + break; + + case NetXen_NIC_XGBE: + printk(KERN_ERR "%s: Function %s is not implemented for XG\n", + netxen_nic_driver_name, __FUNCTION__); + break; + + default: + printk(KERN_ERR "%s: Unknown board type\n",netxen_nic_driver_name); + } + + return ret; +} + +long +netxen_nic_init_port (struct netxen_port *port) +{ + struct netxen_adapter_s *adapter = port->adapter; + long portnum = port->portnum; + long ret = 0; + unsigned long flags; + + switch (adapter->ahw.board_type) { + case NetXen_NIC_GBE: + netxen_nic_disable_phy_interrupts (adapter, portnum); + udelay(20000); + spin_lock_irqsave(&hal_lock, flags); + g_adapter = adapter; + netxen_niu_gbe_init_port(portnum); + spin_unlock_irqrestore(&hal_lock, flags); + + + break; + + case NetXen_NIC_XGBE: + /* Nothing to be done for XG */ + break; + + default: + printk(KERN_ERR "%s: Unknown board type\n",netxen_nic_driver_name); + } + + return ret; +} + +void +netxen_nic_init_niu (struct netxen_adapter_s *adapter) +{ + long rv; + int portno; + unsigned long flags; + + switch (adapter->ahw.board_type) { + case NetXen_NIC_GBE: + spin_lock_irqsave(&hal_lock, flags); + g_adapter = adapter; + for (portno = 0; portno < NetXen_NIU_MAX_GBE_PORTS; portno++) + netxen_niu_gbe_init_port(portno); + spin_unlock_irqrestore(&hal_lock, flags); + break; + + case NetXen_NIC_XGBE: + /* DO niu_init also, for HW bug workaround */ + spin_lock_irqsave(&hal_lock, flags); + g_adapter = adapter; + xge_mdio_init(); + netxen_niu_xginit(); + rv = xge_mdio_init(); + if ((rv & 2) != 0) { + /* XG link is down. Need to do additional init + when INT comes */ + adapter->ahw.xg_linkup=0; + } else { + adapter->ahw.xg_linkup=1; + } + spin_unlock_irqrestore(&hal_lock, flags); + break; + + default: + printk(KERN_ERR "%s: Unknown board type\n",netxen_nic_driver_name); + } + + return; +} + +void +netxen_nic_stop_port(struct netxen_port *port) +{ + long portnum = port->portnum; + struct netxen_adapter_s *adapter = port->adapter; + unsigned long flags; + switch (adapter->ahw.board_type) { + case NetXen_NIC_GBE: + spin_lock_irqsave(&hal_lock, flags); + g_adapter = adapter; + netxen_niu_disable_gbe_port(portnum); + spin_unlock_irqrestore(&hal_lock, flags); + break; + + case NetXen_NIC_XGBE: + spin_lock_irqsave(&hal_lock, flags); + g_adapter = adapter; + netxen_niu_disable_xg_port(portnum); + spin_unlock_irqrestore(&hal_lock, flags); + break; + + default: + printk(KERN_ERR "%s: Unknown board type\n",netxen_nic_driver_name); + } + + return; +} + +void +netxen_nic_stop_all_ports(struct netxen_adapter_s *adapter) +{ + int i; + struct netxen_port *port; + + for (i=0; i < adapter->ahw.max_ports; i++) { + port = adapter->port[i]; + netxen_nic_stop_port(port); + } + + return; +} + +/* Functions required by NetXen Hal routines */ +unsigned long +netxen_xport_lock(void) +{ + /* No lock necessary */ + return 0; +} + +void +netxen_xport_unlock(unsigned long unused) +{ + /* No lock/unlock necessary */ + return; +} + +int +netxen_crb_writelit_adapter (unsigned long off, int data, struct netxen_adapter_s *adapter) +{ //Modified. All the direct calls to this func are changed. + //This gets called only thru' some macros like NetXen_CRB_WRITELIT + unsigned long flags; + void *addr; + + if(ADDR_IN_WINDOW1(off)) + { + read_lock(&adapter->adapter_lock); + NetXen_NIC_PCI_WRITE_32(data, CRB_NORMALIZE(adapter, off)); + read_unlock(&adapter->adapter_lock); + } + else{ + //netxen_nic_write_w0 (adapter, off, data); + write_lock_irqsave(&adapter->adapter_lock, flags); + netxen_nic_pci_change_crbwindow(adapter, 0); + addr = (void *)(adapter->ahw.pci_base + off); + NetXen_NIC_PCI_WRITE_32(data, addr); + netxen_nic_pci_change_crbwindow(adapter, 1); + write_unlock_irqrestore(&adapter->adapter_lock, flags); + } + + return 0; +} +int +netxen_crb_write (unsigned long off, void *data) +{ + return netxen_nic_hw_write_wx (g_adapter, off, data, 4); +} + +int +netxen_crb_writelit(unsigned long off, int data) +{ + return netxen_crb_writelit_adapter(off, data, g_adapter); +} +int +netxen_crb_read (unsigned long off, void *data) +{ + return netxen_nic_hw_read_wx (g_adapter, off, data, 4); +} + +native_t +netxen_crb_read_val (unsigned long off) +{ + int data; + + netxen_nic_hw_read_wx (g_adapter, off, &data, 4); + return data; +} + +int +netxen_crb_write_adapter (unsigned long off, void *data, struct netxen_adapter_s *adapter) +{ + return netxen_nic_hw_write_wx (adapter, off, data, 4); +} + +int +netxen_crb_read_adapter (unsigned long off, void *data, struct netxen_adapter_s *adapter) +{ + return netxen_nic_hw_read_wx (adapter, off, data, 4); +} + +int +netxen_crb_read_val_adapter (unsigned long off, struct netxen_adapter_s *adapter) +{ + int data; + + netxen_nic_hw_read_wx (adapter, off, &data, 4); + return data; +} + + +void DELAY(A) +{ + unsigned long remainder; + + remainder = A/50000; + do { + if (remainder > 1000) { + udelay(1000); + remainder -= 1000; + } else { + udelay(remainder + 1); + remainder = 0; + } + } while (remainder > 0); +} + +void netxen_nic_set_link_parameters(struct netxen_port *port) +{ + struct netxen_adapter_s *adapter = port->adapter; + netxen_niu_phy_status_t status; + uint16_t autoneg; + netxen_niu_control_t mode; + + netxen_nic_read_w0(adapter, NetXen_NIU_MODE, (uint32_t *)&mode); + if(mode.enable_ge) { // Gb 10/100/1000 Mbps mode + if (netxen_nic_phy_read(port->adapter,port->portnum, + NetXen_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, + (netxen_crbword_t *)&status) == 0) { + if(status.link) { + port->state = 1; + switch(status.speed) { + case 0: port->link_speed = SPEED_10; + break; + case 1: port->link_speed = SPEED_100; + break; + case 2: port->link_speed = SPEED_1000; + break; + default: + port->link_speed = -1; // unknown speed + break; + } + switch(status.duplex) { + case 0: port->link_duplex = DUPLEX_HALF; + break; + case 1: port->link_duplex = DUPLEX_FULL; + break; + default: + port->link_duplex = -1; // unknown mode + break; + } + if (netxen_nic_phy_read(port->adapter, + port->portnum, + NetXen_NIU_GB_MII_MGMT_ADDR_AUTONEG, + (netxen_crbword_t *)&autoneg)!= 0) + port->link_autoneg = autoneg; + } else { + port->state = -1; + port->link_speed = -1; + port->link_duplex = -1; + } + } else { + port->state = -1; + port->link_speed = -1; + port->link_duplex = -1; + } + } +} + +#define FLASH_SIZE (0x100000) + +int +netxen_nic_get_flash_size(void) +{ + return FLASH_SIZE; +} + +void +netxen_nic_flash_print(struct netxen_adapter_s* adapter) +{ + int valid = 1; + uint32_t fw_major = 0; + uint32_t fw_minor = 0; + uint32_t fw_build = 0; + + netxen_board_info_t* board_info = &(adapter->ahw.boardcfg); + if (board_info->magic != NetXen_BDINFO_MAGIC) { + printk("NetXen Unknown board config, Read 0x%x expected as 0x%x\n", board_info->magic, + NetXen_BDINFO_MAGIC); + valid = 0; + } + if (board_info->header_version != NetXen_BDINFO_VERSION) { + printk("NetXen Unknown board config version." + " Read %x, expected %x\n", + board_info->header_version, NetXen_BDINFO_VERSION); + valid = 0; + } + if(valid) { + printk("NetXen %s Board #%d, Chip id 0x%x\n", + board_info->board_type == 0x0b ? "XGB" : "GBE", + board_info->board_num, board_info->chip_id); + read_lock(&adapter->adapter_lock); + fw_major = NetXen_NIC_PCI_READ_32(CRB_NORMALIZE(adapter, + NetXen_FW_VERSION_MAJOR)); + fw_minor = NetXen_NIC_PCI_READ_32(CRB_NORMALIZE(adapter, + NetXen_FW_VERSION_MINOR)); + fw_build = NetXen_NIC_PCI_READ_32(CRB_NORMALIZE(adapter, + NetXen_FW_VERSION_SUB)); + read_unlock(&adapter->adapter_lock); + + printk("NetXen Firmware version %d.%d.%d\n", fw_major, fw_minor, + fw_build); + } + if(fw_major != _NetXen_NIC_LINUX_MAJOR) { + printk(KERN_ERR"The mismatch in driver version and firmware " + "version major number\n" + "Driver version major number = %d \t" + "Firmware version major number = %d \n", + _NetXen_NIC_LINUX_MAJOR, fw_major); + adapter->driver_mismatch = 1; + } + if(fw_minor != _NetXen_NIC_LINUX_MINOR) { + printk(KERN_ERR"The mismatch in driver version and firmware " + "version minor number\n" + "Driver version minor number = %d \t" + "Firmware version minor number = %d \n", + _NetXen_NIC_LINUX_MINOR, fw_minor); + adapter->driver_mismatch = 1; + } + if(adapter->driver_mismatch) { + printk(KERN_INFO"Use the driver with version no %d.%d.xxx\n" + ,fw_major,fw_minor); + } else { + DPRINTK(1, INFO,"The major and minor number of driver and " + "firmware versions match\n"); + } +}
- 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