hp100.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,162 行 · 第 1/5 页

C
2,162
字号
/*** hp100.c ** HP CASCADE Architecture Driver for 100VG-AnyLan Network Adapters**** $Id: hp100.c,v 1.58 2001/09/24 18:03:01 perex Exp perex $**** Based on the HP100 driver written by Jaroslav Kysela <perex@jcu.cz>** Extended for new busmaster capable chipsets by ** Siegfried "Frieder" Loeffler (dg1sek) <floeff@mathematik.uni-stuttgart.de>**** Maintained by: Jaroslav Kysela <perex@suse.cz>** ** This driver has only been tested with** -- HP J2585B 10/100 Mbit/s PCI Busmaster** -- HP J2585A 10/100 Mbit/s PCI ** -- HP J2970  10 Mbit/s PCI Combo 10base-T/BNC** -- HP J2973  10 Mbit/s PCI 10base-T** -- HP J2573  10/100 ISA** -- Compex ReadyLink ENET100-VG4  10/100 Mbit/s PCI / EISA** -- Compex FreedomLine 100/VG  10/100 Mbit/s ISA / EISA / PCI** ** but it should also work with the other CASCADE based adapters.**** TODO:**       -  J2573 seems to hang sometimes when in shared memory mode.**       -  Mode for Priority TX**       -  Check PCI registers, performance might be improved?**       -  To reduce interrupt load in busmaster, one could switch off**          the interrupts that are used to refill the queues whenever the**          queues are filled up to more than a certain threshold.**       -  some updates for EISA version of card******   This code 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 code 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., 675 Mass Ave, Cambridge, MA 02139, USA.**** 1.57c -> 1.58**   - used indent to change coding-style**   - added KTI DP-200 EISA ID**   - ioremap is also used for low (<1MB) memory (multi-architecture support)**** 1.57b -> 1.57c - Arnaldo Carvalho de Melo <acme@conectiva.com.br>**   - release resources on failure in init_module**** 1.57 -> 1.57b - Jean II**   - fix spinlocks, SMP is now working !**** 1.56 -> 1.57**   - updates for new PCI interface for 2.1 kernels**** 1.55 -> 1.56**   - removed printk in misc. interrupt and update statistics to allow**     monitoring of card status**   - timing changes in xmit routines, relogin to 100VG hub added when**     driver does reset**   - included fix for Compex FreedomLine PCI adapter** ** 1.54 -> 1.55**   - fixed bad initialization in init_module**   - added Compex FreedomLine adapter**   - some fixes in card initialization**** 1.53 -> 1.54**   - added hardware multicast filter support (doesn't work)**   - little changes in hp100_sense_lan routine **     - added support for Coax and AUI (J2970)**   - fix for multiple cards and hp100_mode parameter (insmod)**   - fix for shared IRQ **** 1.52 -> 1.53**   - fixed bug in multicast support***/#define HP100_DEFAULT_PRIORITY_TX 0#undef HP100_DEBUG#undef HP100_DEBUG_B		/* Trace  */#undef HP100_DEBUG_BM		/* Debug busmaster code (PDL stuff) */#undef HP100_DEBUG_TRAINING	/* Debug login-to-hub procedure */#undef HP100_DEBUG_TX#undef HP100_DEBUG_IRQ#undef HP100_DEBUG_RX#undef HP100_MULTICAST_FILTER	/* Need to be debugged... */#include <linux/version.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/string.h>#include <linux/errno.h>#include <linux/ioport.h>#include <linux/slab.h>#include <linux/interrupt.h>#include <linux/eisa.h>#include <linux/pci.h>#include <linux/spinlock.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <linux/types.h>#include <linux/config.h>	/* for CONFIG_PCI */#include <linux/delay.h>#include <linux/init.h>#include <asm/bitops.h>#include <asm/io.h>#include "hp100.h"/* *  defines */#define HP100_BUS_ISA     0#define HP100_BUS_EISA    1#define HP100_BUS_PCI     2#define HP100_REGION_SIZE	0x20	/* for ioports */#define HP100_SIG_LEN		8	/* same as EISA_SIG_LEN */#define HP100_MAX_PACKET_SIZE	(1536+4)#define HP100_MIN_PACKET_SIZE	60#ifndef HP100_DEFAULT_RX_RATIO/* default - 75% onboard memory on the card are used for RX packets */#define HP100_DEFAULT_RX_RATIO	75#endif#ifndef HP100_DEFAULT_PRIORITY_TX/* default - don't enable transmit outgoing packets as priority */#define HP100_DEFAULT_PRIORITY_TX 0#endif/* *  structures */struct hp100_private {	spinlock_t lock;	char id[HP100_SIG_LEN];	u_short chip;	u_short soft_model;	u_int memory_size;	u_int virt_memory_size;	u_short rx_ratio;	/* 1 - 99 */	u_short priority_tx;	/* != 0 - priority tx */	u_short mode;		/* PIO, Shared Mem or Busmaster */	u_char bus;	struct pci_dev *pci_dev;	short mem_mapped;	/* memory mapped access */	void *mem_ptr_virt;	/* virtual memory mapped area, maybe NULL */	unsigned long mem_ptr_phys;	/* physical memory mapped area */	short lan_type;		/* 10Mb/s, 100Mb/s or -1 (error) */	int hub_status;		/* was login to hub successful? */	u_char mac1_mode;	u_char mac2_mode;	u_char hash_bytes[8];	struct net_device_stats stats;	/* Rings for busmaster mode: */	hp100_ring_t *rxrhead;	/* Head (oldest) index into rxring */	hp100_ring_t *rxrtail;	/* Tail (newest) index into rxring */	hp100_ring_t *txrhead;	/* Head (oldest) index into txring */	hp100_ring_t *txrtail;	/* Tail (newest) index into txring */	hp100_ring_t rxring[MAX_RX_PDL];	hp100_ring_t txring[MAX_TX_PDL];	u_int *page_vaddr_algn;	/* Aligned virtual address of allocated page */	u_long whatever_offset;	/* Offset to bus/phys/dma address */	int rxrcommit;		/* # Rx PDLs commited to adapter */	int txrcommit;		/* # Tx PDLs commited to adapter */};/* *  variables */static const char *hp100_isa_tbl[] = {	"HWPF150", /* HP J2573 rev A */	"HWP1950", /* HP J2573 */};#ifdef CONFIG_EISAstatic struct eisa_device_id hp100_eisa_tbl[] = {	{ "HWPF180" }, /* HP J2577 rev A */	{ "HWP1920" }, /* HP 27248B */	{ "HWP1940" }, /* HP J2577 */	{ "HWP1990" }, /* HP J2577 */	{ "CPX0301" }, /* ReadyLink ENET100-VG4 */	{ "CPX0401" }, /* FreedomLine 100/VG */	{ "" }	       /* Mandatory final entry ! */};MODULE_DEVICE_TABLE(eisa, hp100_eisa_tbl);#endif#ifdef CONFIG_PCIstatic struct pci_device_id hp100_pci_tbl[] = {	{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585A, PCI_ANY_ID, PCI_ANY_ID,},	{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585B, PCI_ANY_ID, PCI_ANY_ID,},	{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2970A, PCI_ANY_ID, PCI_ANY_ID,},	{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2973A, PCI_ANY_ID, PCI_ANY_ID,},	{PCI_VENDOR_ID_COMPEX, PCI_DEVICE_ID_COMPEX_ENET100VG4, PCI_ANY_ID, PCI_ANY_ID,},	{PCI_VENDOR_ID_COMPEX2, PCI_DEVICE_ID_COMPEX2_100VG, PCI_ANY_ID, PCI_ANY_ID,},/*	{PCI_VENDOR_ID_KTI, PCI_DEVICE_ID_KTI_DP200, PCI_ANY_ID, PCI_ANY_ID }, */	{}			/* Terminating entry */};MODULE_DEVICE_TABLE(pci, hp100_pci_tbl);#endifstatic int hp100_rx_ratio = HP100_DEFAULT_RX_RATIO;static int hp100_priority_tx = HP100_DEFAULT_PRIORITY_TX;static int hp100_mode = 1;MODULE_PARM(hp100_rx_ratio, "1i");MODULE_PARM(hp100_priority_tx, "1i");MODULE_PARM(hp100_mode, "1i");/* *  prototypes */static int hp100_probe1(struct net_device *dev, int ioaddr, u_char bus,			struct pci_dev *pci_dev);static int hp100_open(struct net_device *dev);static int hp100_close(struct net_device *dev);static int hp100_start_xmit(struct sk_buff *skb, struct net_device *dev);static int hp100_start_xmit_bm(struct sk_buff *skb,			       struct net_device *dev);static void hp100_rx(struct net_device *dev);static struct net_device_stats *hp100_get_stats(struct net_device *dev);static void hp100_misc_interrupt(struct net_device *dev);static void hp100_update_stats(struct net_device *dev);static void hp100_clear_stats(struct hp100_private *lp, int ioaddr);static void hp100_set_multicast_list(struct net_device *dev);static irqreturn_t hp100_interrupt(int irq, void *dev_id, struct pt_regs *regs);static void hp100_start_interface(struct net_device *dev);static void hp100_stop_interface(struct net_device *dev);static void hp100_load_eeprom(struct net_device *dev, u_short ioaddr);static int hp100_sense_lan(struct net_device *dev);static int hp100_login_to_vg_hub(struct net_device *dev,				 u_short force_relogin);static int hp100_down_vg_link(struct net_device *dev);static void hp100_cascade_reset(struct net_device *dev, u_short enable);static void hp100_BM_shutdown(struct net_device *dev);static void hp100_mmuinit(struct net_device *dev);static void hp100_init_pdls(struct net_device *dev);static int hp100_init_rxpdl(struct net_device *dev,			    register hp100_ring_t * ringptr,			    register u_int * pdlptr);static int hp100_init_txpdl(struct net_device *dev,			    register hp100_ring_t * ringptr,			    register u_int * pdlptr);static void hp100_rxfill(struct net_device *dev);static void hp100_hwinit(struct net_device *dev);static void hp100_clean_txring(struct net_device *dev);#ifdef HP100_DEBUGstatic void hp100_RegisterDump(struct net_device *dev);#endif/* Conversion to new PCI API : * Convert an address in a kernel buffer to a bus/phys/dma address. * This work *only* for memory fragments part of lp->page_vaddr, * because it was properly DMA allocated via pci_alloc_consistent(), * so we just need to "retreive" the original mapping to bus/phys/dma * address - Jean II */static inline dma_addr_t virt_to_whatever(struct net_device *dev, u32 * ptr){	return ((u_long) ptr) +		((struct hp100_private *) (dev->priv))->whatever_offset;}/* TODO: This function should not really be needed in a good design... */static void wait(void){	mdelay(1);}/* *  probe functions *  These functions should - if possible - avoid doing write operations *  since this could cause problems when the card is not installed. *//* * Read board id and convert to string. * Effectively same code as decode_eisa_sig */static __init const char *hp100_read_id(int ioaddr){	int i;	static char str[HP100_SIG_LEN];	unsigned char sig[4], sum;        unsigned short rev;	hp100_page(ID_MAC_ADDR);	sum = 0;	for (i = 0; i < 4; i++) {		sig[i] = hp100_inb(BOARD_ID + i);		sum += sig[i];	}	sum += hp100_inb(BOARD_ID + i);	if (sum != 0xff)		return NULL;	/* bad checksum */        str[0] = ((sig[0] >> 2) & 0x1f) + ('A' - 1);        str[1] = (((sig[0] & 3) << 3) | (sig[1] >> 5)) + ('A' - 1);        str[2] = (sig[1] & 0x1f) + ('A' - 1);        rev = (sig[2] << 8) | sig[3];        sprintf(str + 3, "%04X", rev);	return str;}static __init int hp100_isa_probe1(struct net_device *dev, int ioaddr){	const char *sig;	int i;	if (!request_region(ioaddr, HP100_REGION_SIZE, "hp100"))		goto err;	if (hp100_inw(HW_ID) != HP100_HW_ID_CASCADE) {		release_region(ioaddr, HP100_REGION_SIZE);		goto err;	}	sig = hp100_read_id(ioaddr);	release_region(ioaddr, HP100_REGION_SIZE);	if (sig == NULL)		goto err;	for (i = 0; i < ARRAY_SIZE(hp100_isa_tbl); i++) {		if (!strcmp(hp100_isa_tbl[i], sig)) 			break;	}	if (i < ARRAY_SIZE(hp100_isa_tbl))		return hp100_probe1(dev, ioaddr, HP100_BUS_ISA, NULL); err:	return -ENODEV;}/* * Probe for ISA board. * EISA and PCI are handled by device infrastructure. */static int  __init hp100_isa_probe(struct net_device *dev, int addr){	int err = -ENODEV;	/* Probe for a specific ISA address */			if (addr > 0xff && addr < 0x400)		err = hp100_isa_probe1(dev, addr);	else if (addr != 0) 		err = -ENXIO;	else {		/* Probe all ISA possible port regions */		for (addr = 0x100; addr < 0x400; addr += 0x20) {			err = hp100_isa_probe1(dev, addr);			if (!err)				break;		}	}	return err;}#ifndef MODULEstruct net_device * __init hp100_probe(int unit){	struct net_device *dev = alloc_etherdev(sizeof(struct hp100_private));	int err;	if (!dev)		return ERR_PTR(-ENODEV);	SET_MODULE_OWNER(dev);#ifdef HP100_DEBUG_B	hp100_outw(0x4200, TRACE);	printk("hp100: %s: probe\n", dev->name);#endif	if (unit >= 0) {		sprintf(dev->name, "eth%d", unit);		netdev_boot_setup_check(dev);	}	err = hp100_isa_probe(dev, dev->base_addr);	if (err)		goto out;	err = register_netdev(dev);	if (err)		goto out1;	return dev; out1:	release_region(dev->base_addr, HP100_REGION_SIZE); out:	free_netdev(dev);	return ERR_PTR(err);}#endifstatic int __init hp100_probe1(struct net_device *dev, int ioaddr,			       u_char bus, struct pci_dev *pci_dev){	int i;	int err = -ENODEV;	const char *eid;	u_int chip;	u_char uc;

⌨️ 快捷键说明

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