Re: [PATCH 1/1] atl1: Attansic L1 Gigabit Ethernet driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Oh boy, another vendor driver to shred.

On Wed, 27 Sep 2006 08:23:45 -0500
Jay Cliburn <[email protected]> wrote:

> Full patch for the Attansic L1 gigabit ethernet driver.
> 
> Signed-off-by: Jay Cliburn <[email protected]>
> 
>  drivers/net/Kconfig     |    9 
>  drivers/net/Makefile    |    1 
>  drivers/net/atl1.c      | 5519 +++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/net/atl1.h      | 1598 ++++++++++++++
>  include/linux/pci_ids.h |    3 
>  5 files changed, 7130 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index 6315477..b735b68 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -2248,6 +2248,15 @@ config SPIDER_NET
>  	  This driver supports the Gigabit Ethernet chips present on the
>  	  Cell Processor-Based Blades from IBM.
>  
> +config ATTANSIC_L1
> +        tristate "Attansic L1 gigabit ethernet support"
> +        depends on PCI
> +        help
> +          This driver supports the Attansic L1 gigabit Ethernet device.
> +
> +          To compile this driver as a module, choose M here: the module
> +          will be called atl1.  This is recommended.
> +
>  config GIANFAR
>  	tristate "Gianfar Ethernet"
>  	depends on 85xx || 83xx || PPC_86xx
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index f270bc4..e1fcb86 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -69,6 +69,7 @@ obj-$(CONFIG_VIA_RHINE) += via-rhine.o
>  obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
>  obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
>  obj-$(CONFIG_RIONET) += rionet.o
> +obj-$(CONFIG_ATTANSIC_L1) += atl1.o
>  
>  #
>  # end link order section
> diff --git a/drivers/net/atl1.c b/drivers/net/atl1.c
> new file mode 100644
> index 0000000..ab87071
> --- /dev/null
> +++ b/drivers/net/atl1.c
> @@ -0,0 +1,5519 @@
> +/*
> + * atl1.c: Attansic L1 gigabit ethernet driver.
> + *
> + * This code is derived from the Attansic reference driver (copyright message
> + * below) provided to Jay Cliburn for addition to the Linux kernel.
> + *
> + * The code has been merged into one source file and cleaned up to follow
> + * Linux coding style.
> + *
> + * The changes are (c) Copyright 2006, Jay Cliburn ([email protected])
> + *
> + * This source has not been verified for use in safety critical systems.
> + *
> + * Please direct inquiries about the revamped driver to the linux-kernel
> + * mail list, not to Attansic.
> + *
> + * Original code:
> + *
> + * Copyright (c) 1999-2005 Attansic Corporation ([email protected])
> + *
> + * 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.
> + *
> + * Author: Xiong Huang
> + *
> + * MODULE_LICENSE("GPL");


Why bury this in a comment?
> + *
> + */
> +
> +
> +#include <linux/module.h>
> +#include <linux/types.h>
> +#include <linux/init.h>
> +#include <linux/mm.h>
> +#include <linux/errno.h>
> +#include <linux/ioport.h>
> +#include <linux/pci.h>
> +#include <linux/kernel.h>
> +#include <linux/netdevice.h>
> +#include <linux/etherdevice.h>
> +#include <linux/skbuff.h>
> +#include <linux/delay.h>
> +#include <linux/timer.h>
> +#include <linux/slab.h>
> +#include <linux/interrupt.h>
> +#include <linux/string.h>
> +#include <asm/io.h>
> +#include <linux/reboot.h>
> +#include <linux/ethtool.h>
> +#include <linux/mii.h>
> +#include <linux/in.h>
> +#include <linux/ip.h>
> +#include <linux/tcp.h>
> +#include <linux/udp.h>
> +#include <linux/version.h>
> +
> +
> +/* The following header files were provided in the original
> + * source code, but apparently weren't needed for compilation.
> + * They're left here for posterity.
> + */
> +/* #include <linux/sched.h> */
> +/* #include <linux/pagemap.h> */
> +/* #include <linux/list.h> */
> +/* #include <linux/stddef.h> */
> +/* #include <linux/config.h> */
> +/* #include <linux/vmalloc.h> */
> +/* #include <linux/capability.h> */
> +/* #include <asm/byteorder.h> */
> +/* #include <asm/bitops.h> */
> +/* #include <asm/irq.h> */
> +/* #include <net/pkt_sched.h> */
> +
> +#include "atl1.h"
> +
> +#define RUN_REALTIME 0
> +#define DRV_VERSION "0.1.40.6"
> +
> +char at_driver_name[] = "atl1";
> +char at_driver_string[] = "Attansic L1 Ethernet Network Driver";
> +char at_driver_version[] = DRV_VERSION;
> +char at_copyright[] = "Copyright (C) 1999-2005 Attansic Corporation.";

static const char...

> +
> +MODULE_AUTHOR("Attansic Corporation");
> +MODULE_DESCRIPTION("Attansic L1 1000M Ethernet Network Driver");
> +MODULE_LICENSE("GPL");
> +MODULE_VERSION(DRV_VERSION);
> +
> +static struct pci_device_id at_pci_tbl[] = {
> +	{ PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1,
> +	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
> +	{0,}
> +};

use PCI_DEVICE macro

> +
> +MODULE_DEVICE_TABLE(pci, at_pci_tbl);
> +
> +/* This is the only thing that needs to be changed to adjust the
> + * maximum number of ports that the driver can manage.
> + */
> +
> +#define AT_MAX_NIC 32
> +#define OPTION_UNSET    -1
> +#define OPTION_DISABLED 0
> +#define OPTION_ENABLED  1
> +
> +/* All parameters are treated the same, as an integer array of values.
> + * This macro just reduces the need to repeat the same declaration code
> + * over and over (plus this helps to avoid typo bugs).
> + */
> +#define AT_PARAM_INIT { [0 ... AT_MAX_NIC] = OPTION_UNSET }
> +#ifndef module_param_array
> +
> +/* Module Parameters are always initialized to -1, so that the driver
> + * can tell the difference between no user specified value or the
> + * user asking for the default value.
> + * The true default values are loaded in when e1000_check_options is called.
> + *
> + * This is a GCC extension to ANSI C.
> + * See the item "Labeled Elements in Initializers" in the section
> + * "Extensions to the C Language Family" of the GCC documentation.
> + */
> +
> +#define AT_PARAM(X, desc) \
> +	static const int __devinitdata X[AT_MAX_NIC+1] = AT_PARAM_INIT; \
> +	MODULE_PARM(X, "1-" __MODULE_STRING(AT_MAX_NIC) "i"); \
> +	MODULE_PARM_DESC(X, desc);
> +#else
> +#define AT_PARAM(X, desc) \
> +	static int __devinitdata X[AT_MAX_NIC+1] = AT_PARAM_INIT; \
> +	static int num_##X = 0; \
> +	module_param_array_named(X, X, int, &num_##X, 0); \
> +	MODULE_PARM_DESC(X, desc);
> +#endif

moduleparam is always in 2.6. So this macro can be eliminated and
just code directly.


> +
> +/* Transmit Descriptor Count
> + *
> + * Valid Range: 64-2048
> + *
> + * Default Value: 128
> + */
> +AT_PARAM(TxDescriptors, "Number of transmit descriptors");
> +
> +/* Receive Descriptor Count
> + *
> + * Valid Range: 64-4096
> + *
> + * Default Value: 256
> + */
> +AT_PARAM(RxDescriptors, "Number of receive descriptors");
> +
> +/* User Specified MediaType Override
> + *
> + * Valid Range: 0-5
> + *  - 0    - auto-negotiate at all supported speeds
> + *  - 1    - only link at 1000Mbps Full Duplex
> + *  - 2    - only link at 100Mbps Full Duplex
> + *  - 3    - only link at 100Mbps Half Duplex
> + *  - 4    - only link at 10Mbps Full Duplex
> + *  - 5    - only link at 10Mbps Half Duplex
> + * Default Value: 0
> + */
> +AT_PARAM(MediaType, "MediaType Select");
> +
> +/* Interrupt Moderate Timer in units of 2 us
> + *
> + * Valid Range: 10-65535
> + *
> + * Default Value: 45000(90ms)
> + */
> +AT_PARAM(IntModTimer, "Interrupt Moderator Timer");
> +
> +/* FlashVendor
> + * Valid Range: 0-2
> + * 0 - Atmel
> + * 1 - SST
> + * 2 - ST
> + */
> +AT_PARAM(FlashVendor, "SPI Flash Vendor");
> +
> +#define AUTONEG_ADV_DEFAULT  0x2F
> +#define AUTONEG_ADV_MASK     0x2F
> +#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
> +
> +#define DEFAULT_INT_MOD_CNT             100 // 200us
> +#define MAX_INT_MOD_CNT                 65000
> +#define MIN_INT_MOD_CNT                 50
> +
> +#define FLASH_VENDOR_DEFAULT    0
> +#define FLASH_VENDOR_MIN        0
> +#define FLASH_VENDOR_MAX        2
> +
> +/* function prototypes */
> +
> +int32_t at_reset_hw(struct at_hw* hw);

Need to make all local functions private (static).
Don't use C99 types, in kernel (int32_t) instead use kernel types:
	u32, s32, ...

I suspect most of these int32_t should just be int.


> +int32_t at_read_mac_addr(struct at_hw* hw);
> +int32_t at_init_hw(struct at_hw* hw);
> +int32_t at_phy_setup_autoneg_adv(struct at_hw *hw);
> +int32_t at_phy_reset(struct at_hw *hw);
> +int32_t at_get_speed_and_duplex(struct at_hw *hw, uint16_t *speed, uint16_t *duplex);
> +int32_t at_set_speed_and_duplex(struct at_hw *hw, uint16_t speed, uint16_t duplex);
> +uint32_t at_auto_get_fc(struct at_adapter* adapter, uint16_t duplex);
> +uint32_t at_hash_mc_addr(struct at_hw *hw, uint8_t *mc_addr);
> +void at_hash_set(struct at_hw *hw, uint32_t hash_value);
> +int32_t at_read_phy_reg(struct at_hw *hw, uint16_t reg_addr, uint16_t *phy_data);
> +int32_t at_write_phy_reg(struct at_hw *hw, uint32_t reg_addr, uint16_t phy_data);
> +void at_read_pci_cfg(struct at_hw*  hw, uint32_t reg, uint16_t *value);
> +void at_write_pci_cfg(struct at_hw* hw, uint32_t reg, uint16_t *value);
> +int32_t at_validate_mdi_setting(struct at_hw* hw);
> +int32_t at_setup_link(struct at_hw* hw);
> +void set_mac_addr(struct at_hw* hw);
> +int get_permanent_address(struct at_hw* hw);
> +boolean_t read_eeprom(struct at_hw* hw, uint32_t Offset, uint32_t* pValue);
> +void init_flash_opcode(struct at_hw* hw);
> +boolean_t spi_read(struct at_hw* hw, uint32_t addr, uint32_t* buf);
> +int32_t at_phy_enter_power_saving(struct at_hw* hw);
> +int32_t at_phy_leave_power_saving(struct at_hw* hw);
> +int32_t at_up(struct at_adapter* adapter);
> +void at_down(struct at_adapter* adapter);
> +int at_reset(struct at_adapter* adapter);
> +int32_t at_setup_ring_resources(struct at_adapter* adapter);
> +void at_free_ring_resources(struct at_adapter* adapter);
> +char at_driver_name[];
> +char at_driver_version[];


Get rid of having lots of forward declarations, by just
reordering the code, it's simpler.

> +
> +#ifdef SIOCGMIIPHY
> +int at_set_spd_dplx(struct at_adapter* adapter,uint16_t spddplx);
> +#endif
> +
> +static int at_init_module(void);
> +static void at_exit_module(void);
> +static int at_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
> +static void __devexit at_remove(struct pci_dev *pdev);
> +static int at_sw_init(struct at_adapter *adapter);
> +static int at_open(struct net_device *netdev);
> +static int at_close(struct net_device *netdev);
> +static int at_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
> +static struct net_device_stats * at_get_stats(struct net_device *netdev);
> +static int at_change_mtu(struct net_device *netdev, int new_mtu);
> +static void at_set_multi(struct net_device *netdev);
> +static int at_set_mac(struct net_device *netdev, void *p);
> +static int at_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
> +static void at_tx_timeout(struct net_device *dev);
> +static irqreturn_t at_intr(int irq, void *data, struct pt_regs *regs);
> +static void at_inc_smb(struct at_adapter * adapter);
> +static void at_intr_rx(struct at_adapter* adapter);
> +static void at_intr_tx(struct at_adapter* adapter);
> +static void at_watchdog(unsigned long data);
> +static void at_phy_config(unsigned long data);
> +static void at_tx_timeout_task(struct net_device *netdev);
> +static void at_check_for_link(struct at_adapter* adapter);
> +static void at_link_chg_task(struct net_device* netdev);
> +static uint32_t at_check_link(struct at_adapter* adapter);
> +static void at_clean_tx_ring(struct at_adapter *adapter);
> +static uint16_t at_alloc_rx_buffers(struct at_adapter *adapter);
> +static uint32_t at_configure(struct at_adapter *adapter);
> +static void at_pcie_patch(struct at_adapter *adapter);
> +
> +#ifdef SIOCGMIIPHY
> +static int at_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
> +#endif
> +
> +#ifdef NETIF_F_HW_VLAN_TX
> +static void at_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp);
> +static void at_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
> +static void at_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
> +static void at_restore_vlan(struct at_adapter *adapter);
> +#endif
> +
> +static int at_notify_reboot(struct notifier_block *nb, unsigned long event, void *p);
> +//static int at_suspend(struct pci_dev *pdev, uint32_t state);
> +static int at_suspend(struct pci_dev *pdev, pm_message_t state);
> +
> +#ifdef CONFIG_PM
> +static int at_resume(struct pci_dev *pdev);
> +#endif
> +
> +static void at_via_workaround(struct at_adapter * adapter);
> +
> +struct notifier_block at_notifier_reboot = {
> +    .notifier_call  = at_notify_reboot,
> +    .next       = NULL,
> +    .priority   = 0
> +};

Don't initialize fields that can just be zero.
Do you really need a reboot notifier at all?


> +void at_check_options(struct at_adapter *adapter);
> +int at_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr);
> +
> +#ifdef SIOCDEVPRIVATE
> +int at_priv_ioctl(struct net_device* netdev, struct ifreq* ifr);
> +#endif
> +
> +struct at_option {
> +	enum { enable_option, range_option, list_option } type;
> +	char *name;
> +	char *err;
> +	int  def;
> +	union {
> +		struct { /* range_option info */
> +			int min;
> +			int max;
> +		} r;
> +		struct { /* list_option info */
> +			int nr;
> +			struct at_opt_list { int i; char *str; } *p;
> +		} l;
> +	} arg;
> +};
> +
> +static int __devinit at_validate_option(int *value, struct at_option *opt)
> +{
> +	if(*value == OPTION_UNSET) {
> +		*value = opt->def;
> +		return 0;
> +	}
> +
> +	switch (opt->type) {
> +	case enable_option:
> +		switch (*value) {
> +		case OPTION_ENABLED:
> +			printk(KERN_INFO "%s Enabled\n", opt->name);
> +			return 0;
> +		case OPTION_DISABLED:
> +			printk(KERN_INFO "%s Disabled\n", opt->name);
> +			return 0;
> +		}
> +		break;

Indentation does not match kernel style,
run through scripts/Lindent.

> +	case range_option:
> +		if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
> +			printk(KERN_INFO "%s set to %i\n", opt->name, *value);
> +			return 0;
> +		}
> +		break;
> +
> +	case list_option: {
> +		int i;
> +		struct at_opt_list *ent;
> +
> +		for (i = 0; i < opt->arg.l.nr; i++) {
> +			ent = &opt->arg.l.p[i];
> +			if (*value == ent->i) {
> +				if (ent->str[0] != '\0')
> +					printk(KERN_INFO "%s\n", ent->str);
> +				return 0;
> +			}
> +		}
> +		break;
> +	}
> +
> +	default:
> +		BUG();
> +	}
> +
> +	printk(KERN_INFO "Invalid %s specified (%i) %s\n",
> +	       opt->name, *value, opt->err);
> +	*value = opt->def;
> +	return -1;
> +}
> +
> +/**
> + * at_check_options - Range Checking for Command Line Parameters
> + * @adapter: board private structure
> + *
> + * This routine checks all command line parameters for valid user
> + * input.  If an invalid value is given, or if no user specified
> + * value exists, a default value is used.  The final value is stored
> + * in a variable in the adapter structure.
> + **/
> +
> +void __devinit at_check_options(struct at_adapter *adapter)
> +{
> +	int bd = adapter->bd_number;
> +	if (bd >= AT_MAX_NIC) {
> +		printk(KERN_NOTICE
> +		       "Warning: no configuration for board #%i\n", bd);
> +		printk(KERN_NOTICE "Using defaults for all values\n");
> +#ifndef module_param_array
> +		bd = AT_MAX_NIC;
> +#endif
> +	}
> +
> +	{ /* Transmit Descriptor Count */
> +		struct at_option opt = {
> +			.type = range_option,
> +			.name = "Transmit Descriptors",
> +			.err  = "using default of "
> +				__MODULE_STRING(AT_DEFAULT_TPD),
> +			.def  = AT_DEFAULT_TPD,
> +			.arg  = { .r = { .min = AT_MIN_TPD, .max = AT_MAX_TPD }}
> +		};
> +		struct at_tpd_ring *tpd_ring = &adapter->tpd_ring;
> +		int val;
> +#ifdef module_param_array
> +		if (num_TxDescriptors > bd) {
> +#endif
> +			val = TxDescriptors[bd];
> +			at_validate_option(&val, &opt);
> +			tpd_ring->count = ((uint16_t) val)&~1;
> +#ifdef module_param_array
> +		} else {
> +			tpd_ring->count = (uint16_t)opt.def;
> +		}
> +#endif
> +	}
> +
> +	{ /* Receive Descriptor Count */
> +		struct at_option opt = {
> +			.type = range_option,
> +			.name = "Receive Descriptors",
> +			.err  = "using default of "
> +				__MODULE_STRING(AT_DEFAULT_RFD),
> +			.def  = AT_DEFAULT_RFD,
> +			.arg  = { .r = { .min = AT_MIN_RFD, .max = AT_MAX_RFD }}
> +		};
> +		struct at_rfd_ring *rfd_ring = &adapter->rfd_ring;
> +        	struct at_rrd_ring * rrd_ring = &adapter->rrd_ring;
> +		int val;
> +#ifdef module_param_array
> +		if (num_RxDescriptors > bd) {
> +#endif
> +			val = RxDescriptors[bd];
> +			at_validate_option(&val, &opt);
> +			rrd_ring->count = rfd_ring->count = ((uint16_t)val)&~1;
> +				// even number
> +#ifdef module_param_array
> +		} else {
> +			rfd_ring->count = rrd_ring->count = (uint16_t)opt.def;
> +		}
> +#endif
> +	}
> +
> +	{ /* Interrupt Moderate Timer */
> +	    struct at_option opt = {
> +	        .type = range_option,
> +	        .name = "Interrupt Moderate Timer",
> +	        .err  = "using default of " __MODULE_STRING(DEFAULT_INT_MOD_CNT),
> +	        .def  = DEFAULT_INT_MOD_CNT,
> +	        .arg  = { .r = { .min = MIN_INT_MOD_CNT, .max = MAX_INT_MOD_CNT }}
> +	    } ;
> +        int val;
> +#ifdef module_param_array
> +		if (num_IntModTimer > bd) {
> +#endif
> +			val = IntModTimer[bd];
> +			at_validate_option(&val, &opt);
> +			adapter->imt = (uint16_t) val;
> +#ifdef module_param_array
> +		} else {
> +			adapter->imt = (uint16_t)(opt.def);
> +		}
> +#endif
> +	}
> +
> +	{ /* Flash Vendor */
> +	    struct at_option opt = {
> +	        .type = range_option,
> +	        .name = "SPI Flash Vendor",
> +	        .err  = "using default of " __MODULE_STRING(FLASH_VENDOR_DEFAULT),
> +	        .def  = DEFAULT_INT_MOD_CNT,
> +	        .arg  = { .r = { .min = FLASH_VENDOR_MIN, .max = FLASH_VENDOR_MAX }}
> +	    } ;
> +        int val;
> +#ifdef module_param_array
> +		if (num_FlashVendor > bd) {
> +#endif
> +			val = FlashVendor[bd];
> +			at_validate_option(&val, &opt);
> +			adapter->hw.flash_vendor = (uint8_t) val;
> +#ifdef module_param_array
> +		} else {
> +			adapter->hw.flash_vendor = (uint8_t)(opt.def);
> +		}
> +#endif
> +	}
> +
> +	{ /* MediaType */
> +	    struct at_option opt = {
> +	        .type = range_option,
> +	        .name = "Speed/Duplex Selection",
> +	        .err  = "using default of " __MODULE_STRING(MEDIA_TYPE_AUTO_SENSOR),
> +	        .def  = MEDIA_TYPE_AUTO_SENSOR,
> +	        .arg  = { .r = { .min = MEDIA_TYPE_AUTO_SENSOR, .max = MEDIA_TYPE_10M_HALF }}
> +	    } ;
> +        int val;
> +#ifdef module_param_array
> +		if (num_MediaType > bd) {
> +#endif
> +			val = MediaType[bd];
> +			at_validate_option(&val, &opt);
> +			adapter->hw.MediaType = (uint16_t) val;
> +#ifdef module_param_array
> +		} else {
> +			adapter->hw.MediaType = (uint16_t)(opt.def);
> +		}
> +#endif
> +	}
> +}
> +

This complexity is an argument for not using lots of module
options, and just use ethtool to change stuff.

> +
> +#ifdef SIOCDEVPRIVATE
> +#include <asm/uaccess.h>
> +
> +// set rfd buffer size. do not support !

/* C style comments are preferred */


..
> +int at_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
> +{
> +	struct at_adapter *adapter = netdev->priv;
> +	void *addr = ifr->ifr_data;
> +	uint32_t cmd;
> +
> +	if (get_user(cmd, (uint32_t *) addr))
> +		return -EFAULT;
> +

Do not do your own ethtool ioctl processing, to easy to get
wrong. Use ethtool_ops instead.


> +/* Removed large chunk of kcompat stuff -- JKC 09/2006 */
> +
> +/**
> + * at_probe - Device Initialization Routine
> + * @pdev: PCI device information struct
> + * @ent: entry in at_pci_tbl
> + *
> + * Returns 0 on success, negative on failure
> + *
> + * at_probe initializes an adapter identified by a pci_dev structure.
> + * The OS initialization, configuring of the adapter private structure,
> + * and a hardware reset occur.
> + **/
> +
> +static int __devinit
> +at_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
> +{
> +	struct net_device *netdev;
> +	struct at_adapter *adapter;
> +	static int cards_found = 0;
> +	unsigned long mmio_start;
> +	int mmio_len;
> +	boolean_t pci_using_64 = TRUE;
> +	int err;
> +//	uint16_t eeprom_data;
> +
> +	DEBUGFUNC("at_probe !");
> +
> +	if ((err = pci_enable_device(pdev)))
> +		return err;
> +
> +	if ((err = pci_set_dma_mask(pdev, PCI_DMA_64BIT))) {
> +		if ((err = pci_set_dma_mask(pdev, PCI_DMA_32BIT))) {
> +			AT_ERR("No usable DMA configuration, aborting\n");
> +			return err;
> +		}
> +		pci_using_64 = FALSE;
> +	}
> +
> +
> +	// Mark all PCI regions associated with PCI device
> +	// pdev as being reserved by owner at_driver_name
> +	if ((err = pci_request_regions(pdev, at_driver_name)))
> +		return err;
> +
> +	// Enables bus-mastering on the device and calls
> +	// pcibios_set_master to do the needed arch specific settings
> +	pci_set_master(pdev);
> +
> +	netdev = alloc_etherdev(sizeof(struct at_adapter));
> +	if (!netdev) {
> +		err = -ENOMEM;
> +		goto err_alloc_etherdev;
> +	}
> +
> +	SET_MODULE_OWNER(netdev);
> +	SET_NETDEV_DEV(netdev, &pdev->dev);
> +
> +	pci_set_drvdata(pdev, netdev);
> +	adapter = netdev_priv(netdev);
> +	adapter->netdev = netdev;
> +	adapter->pdev = pdev;
> +	adapter->hw.back = adapter;
> +
> +	mmio_start = pci_resource_start(pdev, BAR_0);
> +	mmio_len = pci_resource_len(pdev, BAR_0);
> +
> +	/* AT_DBG("base memory = %lx memory length = %x \n",
> +	mmio_start, mmio_len); FIXME */
> +	adapter->hw.mem_rang = (uint32_t)mmio_len;
> +	adapter->hw.hw_addr = ioremap_nocache(mmio_start, mmio_len);
> +	if (!adapter->hw.hw_addr) {
> +		err = -EIO;
> +		goto err_ioremap;
> +	}
> +	/* get device reversion number */
> +	adapter->hw.dev_rev = AT_READ_REGW(&adapter->hw, (REG_MASTER_CTRL+2));
> +
> +	netdev->open = &at_open;
> +	netdev->stop = &at_close;
> +	netdev->hard_start_xmit = &at_xmit_frame;
> +	netdev->get_stats = &at_get_stats;
> +	netdev->set_multicast_list = &at_set_multi;
> +	netdev->set_mac_address = &at_set_mac;
> +	netdev->change_mtu = &at_change_mtu;
> +	netdev->do_ioctl = &at_ioctl;
> +#ifdef HAVE_TX_TIMEOUT
> +	netdev->tx_timeout = &at_tx_timeout;
> +	netdev->watchdog_timeo = 5 * HZ;
> +#endif
> +#ifdef NETIF_F_HW_VLAN_TX
> +	netdev->vlan_rx_register = at_vlan_rx_register;
> +	netdev->vlan_rx_add_vid = at_vlan_rx_add_vid;
> +	netdev->vlan_rx_kill_vid = at_vlan_rx_kill_vid;
> +#endif
> +
> +	netdev->mem_start = mmio_start;
> +	netdev->mem_end = mmio_start + mmio_len;
> +	//netdev->base_addr = adapter->io_base;
> +	adapter->bd_number = cards_found;
> +	adapter->pci_using_64 = pci_using_64;
> +
> +	/* setup the private structure */
> +
> +	if ((err = at_sw_init(adapter)))
> +		goto err_sw_init;
> +
> +	netdev->features = NETIF_F_HW_CSUM;
> +
> +#ifdef MAX_SKB_FRAGS
> +	netdev->features |= NETIF_F_SG;
> +#endif
> +#ifdef NETIF_F_HW_VLAN_TX
> +	netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
> +#endif
> +#ifdef NETIF_F_TSO
> +	netdev->features |= NETIF_F_TSO;
> +#endif/*NETIF_F_TSO*/
> +
> +	if (pci_using_64) {
> +		netdev->features |= NETIF_F_HIGHDMA;
> +		/* AT_DBG("pci using 64bit address\n"); FIXME */
> +	}
> +#ifdef NETIF_F_LLTX
> +	netdev->features |= NETIF_F_LLTX;
> +#endif
> +
> +	/* patch for some L1 of old version,
> +	 * the final version of L1 may not need these
> +	 * patches
> +	 */
> +	at_pcie_patch(adapter);
> +
> +	/* really reset GPHY core */
> +	AT_WRITE_REGW(&adapter->hw, REG_GPHY_ENABLE, 0);
> +
> +	/* reset the controller to
> +	 * put the device in a known good starting state */
> +
> +	if (at_reset_hw(&adapter->hw)) {
> +		err = -EIO;
> +		goto err_reset;
> +	}
> +
> +	/* copy the MAC address out of the EEPROM */
> +
> +	at_read_mac_addr(&adapter->hw);
> +	memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
> +
> +	if (!is_valid_ether_addr(netdev->dev_addr)) {
> +		err = -EIO;
> +		goto err_eeprom;
> +	}
> +
> +	/*
> +	AT_DBG("mac address : %02x-%02x-%02x-%02x-%02x-%02x\n",
> +		adapter->hw.mac_addr[0],
> +		adapter->hw.mac_addr[1],
> +		adapter->hw.mac_addr[2],
> +		adapter->hw.mac_addr[3],
> +		adapter->hw.mac_addr[4],
> +		adapter->hw.mac_addr[5] );
> +	*/
> +
> +	at_check_options(adapter);
> +
> +	/* pre-init the MAC, and setup link */
> +
> +	if ((err = at_init_hw(&adapter->hw))) {
> +		err = -EIO;
> +		goto err_init_hw;
> +	}
> +
> +	/* assume we have no link for now */
> +
> +	netif_carrier_off(netdev);
> +	netif_stop_queue(netdev);
> +
> +	init_timer(&adapter->watchdog_timer);
> +	adapter->watchdog_timer.function = &at_watchdog;
> +	adapter->watchdog_timer.data = (unsigned long) adapter;
> +
> +	init_timer(&adapter->phy_config_timer);
> +	adapter->phy_config_timer.function = &at_phy_config;
> +	adapter->phy_config_timer.data = (unsigned long) adapter;
> +	adapter->phy_timer_pending = FALSE;
> +
> +	INIT_WORK(&adapter->tx_timeout_task,
> +		 (void (*)(void *))at_tx_timeout_task, netdev);
> +
> +	INIT_WORK(&adapter->link_chg_task,
> +        	 (void (*)(void *))at_link_chg_task, netdev);
> +
> +	INIT_WORK(&adapter->pcie_dma_to_rst_task,
> +        	 (void (*)(void *))at_tx_timeout_task, netdev);
> +
> +	if ((err = register_netdev(netdev)))
> +		goto err_register;
> +
> +    	cards_found++;
> +	at_via_workaround(adapter);
> +
> +	return 0;
> +
> +err_init_hw:
> +err_reset:
> +err_register:
> +err_sw_init:
> +err_eeprom:
> +	iounmap(adapter->hw.hw_addr);
> +err_ioremap:
> +	free_netdev(netdev);
> +err_alloc_etherdev:
> +	pci_release_regions(pdev);
> +	return err;
> +}
...

> diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
> index 6a1e098..1eb6f80 100644
> --- a/include/linux/pci_ids.h
> +++ b/include/linux/pci_ids.h
> @@ -2042,6 +2042,9 @@ #define PCI_VENDOR_ID_TOPSPIN		0x1867
>  #define PCI_VENDOR_ID_TDI               0x192E
>  #define PCI_DEVICE_ID_TDI_EHCI          0x0101
>  
> +#define PCI_VENDOR_ID_ATTANSIC		0x1969
> +#define PCI_DEVICE_ID_ATTANSIC_L1	0x1048
> +
>  #define PCI_VENDOR_ID_JMICRON		0x197B
>  #define PCI_DEVICE_ID_JMICRON_JMB360	0x2360
>  #define PCI_DEVICE_ID_JMICRON_JMB361	0x2361

Don't bother with PCI id's update, for each sub device.
Vendor is probably useful.

-- 
Stephen Hemminger <[email protected]>
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux