netxen_nic_hw.c

来自「linux 内核源代码」· C语言 代码 · 共 1,201 行 · 第 1/3 页

C
1,201
字号
/* * 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: *    info@netxen.com * NetXen, * 3965 Freedom Circle, Fourth floor, * Santa Clara, CA 95054 * * * Source file for NIC routines to access the Phantom hardware * */#include "netxen_nic.h"#include "netxen_nic_hw.h"#define DEFINE_GLOBAL_RECV_CRB#include "netxen_nic_phan_reg.h"#include <net/ip.h>struct netxen_recv_crb recv_crb_registers[] = {	/*	 * Instance 0.	 */	{	 /* rcv_desc_crb: */	 {	  {	   /* crb_rcv_producer_offset: */	   NETXEN_NIC_REG(0x100),	   /* crb_rcv_consumer_offset: */	   NETXEN_NIC_REG(0x104),	   /* crb_gloablrcv_ring: */	   NETXEN_NIC_REG(0x108),	   /* crb_rcv_ring_size */	   NETXEN_NIC_REG(0x10c),	   },	  /* Jumbo frames */	  {	   /* crb_rcv_producer_offset: */	   NETXEN_NIC_REG(0x110),	   /* crb_rcv_consumer_offset: */	   NETXEN_NIC_REG(0x114),	   /* crb_gloablrcv_ring: */	   NETXEN_NIC_REG(0x118),	   /* crb_rcv_ring_size */	   NETXEN_NIC_REG(0x11c),	   },	  /* LRO */	  {	   /* crb_rcv_producer_offset: */	   NETXEN_NIC_REG(0x120),	   /* crb_rcv_consumer_offset: */	   NETXEN_NIC_REG(0x124),	   /* crb_gloablrcv_ring: */	   NETXEN_NIC_REG(0x128),	   /* crb_rcv_ring_size */	   NETXEN_NIC_REG(0x12c),	   }	  },	 /* crb_rcvstatus_ring: */	 NETXEN_NIC_REG(0x130),	 /* crb_rcv_status_producer: */	 NETXEN_NIC_REG(0x134),	 /* crb_rcv_status_consumer: */	 NETXEN_NIC_REG(0x138),	 /* crb_rcvpeg_state: */	 NETXEN_NIC_REG(0x13c),	 /* crb_status_ring_size */	 NETXEN_NIC_REG(0x140),	 },	/*	 * Instance 1,	 */	{	 /* rcv_desc_crb: */	 {	  {	   /* crb_rcv_producer_offset: */	   NETXEN_NIC_REG(0x144),	   /* crb_rcv_consumer_offset: */	   NETXEN_NIC_REG(0x148),	   /* crb_globalrcv_ring: */	   NETXEN_NIC_REG(0x14c),	   /* crb_rcv_ring_size */	   NETXEN_NIC_REG(0x150),	   },	  /* Jumbo frames */	  {	   /* crb_rcv_producer_offset: */	   NETXEN_NIC_REG(0x154),	   /* crb_rcv_consumer_offset: */	   NETXEN_NIC_REG(0x158),	   /* crb_globalrcv_ring: */	   NETXEN_NIC_REG(0x15c),	   /* crb_rcv_ring_size */	   NETXEN_NIC_REG(0x160),	   },	  /* LRO */	  {	   /* crb_rcv_producer_offset: */	   NETXEN_NIC_REG(0x164),	   /* crb_rcv_consumer_offset: */	   NETXEN_NIC_REG(0x168),	   /* crb_globalrcv_ring: */	   NETXEN_NIC_REG(0x16c),	   /* crb_rcv_ring_size */	   NETXEN_NIC_REG(0x170),	   }	  },	 /* crb_rcvstatus_ring: */	 NETXEN_NIC_REG(0x174),	 /* crb_rcv_status_producer: */	 NETXEN_NIC_REG(0x178),	 /* crb_rcv_status_consumer: */	 NETXEN_NIC_REG(0x17c),	 /* crb_rcvpeg_state: */	 NETXEN_NIC_REG(0x180),	 /* crb_status_ring_size */	 NETXEN_NIC_REG(0x184),	 },	/*	 * Instance 2,	 */	{	  {	    {	    /* crb_rcv_producer_offset: */	    NETXEN_NIC_REG(0x1d8),	    /* crb_rcv_consumer_offset: */	    NETXEN_NIC_REG(0x1dc),	    /* crb_gloablrcv_ring: */	    NETXEN_NIC_REG(0x1f0),	    /* crb_rcv_ring_size */	    NETXEN_NIC_REG(0x1f4),	    },	    /* Jumbo frames */	    {	    /* crb_rcv_producer_offset: */		    	    NETXEN_NIC_REG(0x1f8),	    /* crb_rcv_consumer_offset: */	    NETXEN_NIC_REG(0x1fc),	    /* crb_gloablrcv_ring: */	    NETXEN_NIC_REG(0x200),	    /* crb_rcv_ring_size */	    NETXEN_NIC_REG(0x204),	    },	    /* LRO */	    {	    /* crb_rcv_producer_offset: */	    NETXEN_NIC_REG(0x208),	    /* crb_rcv_consumer_offset: */	    NETXEN_NIC_REG(0x20c),	    /* crb_gloablrcv_ring: */	    NETXEN_NIC_REG(0x210),	    /* crb_rcv_ring_size */	    NETXEN_NIC_REG(0x214),	    }	  },	  /* crb_rcvstatus_ring: */	  NETXEN_NIC_REG(0x218),	  /* crb_rcv_status_producer: */	  NETXEN_NIC_REG(0x21c),	  /* crb_rcv_status_consumer: */	  NETXEN_NIC_REG(0x220),	  /* crb_rcvpeg_state: */	  NETXEN_NIC_REG(0x224),	  /* crb_status_ring_size */	  NETXEN_NIC_REG(0x228),	},	/*	 * Instance 3,	 */	{	  {	    {	    /* crb_rcv_producer_offset: */	    NETXEN_NIC_REG(0x22c),	    /* crb_rcv_consumer_offset: */	    NETXEN_NIC_REG(0x230),	    /* crb_gloablrcv_ring: */	    NETXEN_NIC_REG(0x234),	    /* crb_rcv_ring_size */	    NETXEN_NIC_REG(0x238),	    },	    /* Jumbo frames */	    {	    /* crb_rcv_producer_offset: */ 	    NETXEN_NIC_REG(0x23c),	    /* crb_rcv_consumer_offset: */	    NETXEN_NIC_REG(0x240),	    /* crb_gloablrcv_ring: */	    NETXEN_NIC_REG(0x244),	    /* crb_rcv_ring_size */	    NETXEN_NIC_REG(0x248),	    },	    /* LRO */	    {	    /* crb_rcv_producer_offset: */	    NETXEN_NIC_REG(0x24c),	    /* crb_rcv_consumer_offset: */	    NETXEN_NIC_REG(0x250),	    /* crb_gloablrcv_ring: */	    NETXEN_NIC_REG(0x254),	    /* crb_rcv_ring_size */	    NETXEN_NIC_REG(0x258),	    }	  },	  /* crb_rcvstatus_ring: */	  NETXEN_NIC_REG(0x25c),	  /* crb_rcv_status_producer: */	  NETXEN_NIC_REG(0x260),	  /* crb_rcv_status_consumer: */	  NETXEN_NIC_REG(0x264),	  /* crb_rcvpeg_state: */	  NETXEN_NIC_REG(0x268),	  /* crb_status_ring_size */	  NETXEN_NIC_REG(0x26c),	},};u64 ctx_addr_sig_regs[][3] = {	{NETXEN_NIC_REG(0x188), NETXEN_NIC_REG(0x18c), NETXEN_NIC_REG(0x1c0)},	{NETXEN_NIC_REG(0x190), NETXEN_NIC_REG(0x194), NETXEN_NIC_REG(0x1c4)},	{NETXEN_NIC_REG(0x198), NETXEN_NIC_REG(0x19c), NETXEN_NIC_REG(0x1c8)},	{NETXEN_NIC_REG(0x1a0), NETXEN_NIC_REG(0x1a4), NETXEN_NIC_REG(0x1cc)}};/*  PCI Windowing for DDR regions.  */#define ADDR_IN_RANGE(addr, low, high)	\	(((addr) <= (high)) && ((addr) >= (low)))#define NETXEN_FLASH_BASE	(NETXEN_BOOTLD_START)#define NETXEN_PHANTOM_MEM_BASE	(NETXEN_FLASH_BASE)#define NETXEN_MAX_MTU		8000 + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE#define NETXEN_MIN_MTU		64#define NETXEN_ETH_FCS_SIZE     4#define NETXEN_ENET_HEADER_SIZE 14#define NETXEN_WINDOW_ONE 	0x2000000	/*CRB Window: bit 25 of CRB address */#define NETXEN_FIRMWARE_LEN 	((16 * 1024) / 4)#define NETXEN_NIU_HDRSIZE	(0x1 << 6)#define NETXEN_NIU_TLRSIZE	(0x1 << 5)#define lower32(x)		((u32)((x) & 0xffffffff))#define upper32(x)			\	((u32)(((unsigned long long)(x) >> 32) & 0xffffffff))#define NETXEN_NIC_ZERO_PAUSE_ADDR     0ULL#define NETXEN_NIC_UNIT_PAUSE_ADDR     0x200ULL#define NETXEN_NIC_EPG_PAUSE_ADDR1     0x2200010000c28001ULL#define NETXEN_NIC_EPG_PAUSE_ADDR2     0x0100088866554433ULL#define NETXEN_NIC_WINDOW_MARGIN 0x100000unsigned long netxen_nic_pci_set_window(struct netxen_adapter *adapter,					unsigned long long addr);void netxen_free_hw_resources(struct netxen_adapter *adapter);int netxen_nic_set_mac(struct net_device *netdev, void *p){	struct netxen_adapter *adapter = netdev_priv(netdev);	struct sockaddr *addr = p;	if (netif_running(netdev))		return -EBUSY;	if (!is_valid_ether_addr(addr->sa_data))		return -EADDRNOTAVAIL;	DPRINTK(INFO, "valid ether addr\n");	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);	if (adapter->macaddr_set)		adapter->macaddr_set(adapter, addr->sa_data);	return 0;}/* * netxen_nic_set_multi - Multicast */void netxen_nic_set_multi(struct net_device *netdev){	struct netxen_adapter *adapter = netdev_priv(netdev);	struct dev_mc_list *mc_ptr;	mc_ptr = netdev->mc_list;	if (netdev->flags & IFF_PROMISC) {		if (adapter->set_promisc)			adapter->set_promisc(adapter,					     NETXEN_NIU_PROMISC_MODE);	} else {		if (adapter->unset_promisc)			adapter->unset_promisc(adapter,					       NETXEN_NIU_NON_PROMISC_MODE);	}}/* * netxen_nic_change_mtu - Change the Maximum Transfer Unit * @returns 0 on success, negative on failure */int netxen_nic_change_mtu(struct net_device *netdev, int mtu){	struct netxen_adapter *adapter = netdev_priv(netdev);	int eff_mtu = mtu + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE;	if ((eff_mtu > NETXEN_MAX_MTU) || (eff_mtu < NETXEN_MIN_MTU)) {		printk(KERN_ERR "%s: %s %d is not supported.\n",		       netxen_nic_driver_name, netdev->name, mtu);		return -EINVAL;	}	if (adapter->set_mtu)		adapter->set_mtu(adapter, mtu);	netdev->mtu = mtu;	return 0;}/* * check if the firmware has been downloaded and ready to run  and * setup the address for the descriptors in the adapter */int netxen_nic_hw_resources(struct netxen_adapter *adapter){	struct netxen_hardware_context *hw = &adapter->ahw;	u32 state = 0;	void *addr;	int loops = 0, err = 0;	int ctx, ring;	struct netxen_recv_context *recv_ctx;	struct netxen_rcv_desc_ctx *rcv_desc;	int func_id = adapter->portnum;	DPRINTK(INFO, "crb_base: %lx %x", NETXEN_PCI_CRBSPACE,		PCI_OFFSET_SECOND_RANGE(adapter, NETXEN_PCI_CRBSPACE));	DPRINTK(INFO, "cam base: %lx %x", NETXEN_CRB_CAM,		pci_base_offset(adapter, NETXEN_CRB_CAM));	DPRINTK(INFO, "cam RAM: %lx %x", NETXEN_CAM_RAM_BASE,		pci_base_offset(adapter, NETXEN_CAM_RAM_BASE));	for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {		DPRINTK(INFO, "Command Peg ready..waiting for rcv peg\n");		loops = 0;		state = 0;		/* Window 1 call */		state = readl(NETXEN_CRB_NORMALIZE(adapter,						   recv_crb_registers[ctx].						   crb_rcvpeg_state));		while (state != PHAN_PEG_RCV_INITIALIZED && loops < 20) {			msleep(1);			/* Window 1 call */			state = readl(NETXEN_CRB_NORMALIZE(adapter,							   recv_crb_registers							   [ctx].							   crb_rcvpeg_state));			loops++;		}		if (loops >= 20) {			printk(KERN_ERR "Rcv Peg initialization not complete:"			       "%x.\n", state);			err = -EIO;			return err;		}	}	adapter->intr_scheme = readl(		NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_FW));	printk(KERN_NOTICE "%s: FW capabilities:0x%x\n", netxen_nic_driver_name,			adapter->intr_scheme);	DPRINTK(INFO, "Receive Peg ready too. starting stuff\n");	addr = netxen_alloc(adapter->ahw.pdev,

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?