⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 epic_cb.c

📁 pcmcia source code
💻 C
📖 第 1 页 / 共 3 页
字号:
/* epic100.c: A SMC 83c170 EPIC/100 Fast Ethernet driver for Linux. *//*	Written/copyright 1997-1999 by Donald Becker.	This software may be used and distributed according to the terms	of the GNU General Public License, incorporated herein by reference.	All other rights reserved.	This driver is for the SMC83c170/175 "EPIC" series, as used on the	SMC EtherPower II 9432 PCI adapter, and several CardBus cards.	The author may be reached as becker@scyld.com, or C/O	Scyld Computing Corporation	410 Severn Ave., Suite 210	Annapolis MD 21403	Information and updates available at	http://www.scyld.com/network/epic100.html*/static const char *version ="epic100.c:v1.07h 8/18/99 Donald Becker http://www.scyld.com/network/epic100.html\n";/* User-tunable values. */static int debug = 1;#define epic_debug debug/* Used to pass the full-duplex flag, etc. */#define MAX_UNITS 8static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};/* Set the copy breakpoint for the copy-only-tiny-frames scheme.   Setting to > 1518 effectively disables this feature. */static int rx_copybreak = 200;/* Maximum events (Rx packets, etc.) to handle at each interrupt. */static int max_interrupt_work = 32;/* Operational parameters that usually are not changed. *//* Keep the ring sizes a power of two for efficiency.   Making the Tx ring too large decreases the effectiveness of channel   bonding and packet priority.   There are no ill effects from too-large receive rings. */#define TX_RING_SIZE	16#define RX_RING_SIZE	32/* Time in jiffies before concluding the transmitter is hung. */#define TX_TIMEOUT  (2*HZ)#define PKT_BUF_SZ		1536			/* Size of each temporary Rx buffer.*//* Bytes transferred to chip before transmission starts. *//* Initial threshold, increased on underflow, rounded down to 4 byte units. */#define TX_FIFO_THRESH 256#define RX_FIFO_THRESH 1		/* 0-3, 0==32, 64,96, or 3==128 bytes  */#include <linux/version.h>		/* Evil, but neccessary */#ifdef MODULE#ifdef MODVERSIONS#include <linux/modversions.h>#endif#include <linux/module.h>#else#define MOD_INC_USE_COUNT#define MOD_DEC_USE_COUNT#endif#include <linux/kernel.h>#include <linux/string.h>#include <linux/timer.h>#include <linux/errno.h>#include <linux/ioport.h>#include <linux/slab.h>#include <linux/interrupt.h>#include <linux/pci.h>#include <linux/delay.h>#include <asm/processor.h>		/* Processor type for cache alignment. */#include <asm/bitops.h>#include <asm/io.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>/* Kernel compatibility defines, common to David Hind's PCMCIA package.   This is only in the support-all-kernels source code. */#if ! defined (LINUX_VERSION_CODE) || LINUX_VERSION_CODE < 0x20000#warning This driver version is only for kernel versions 2.0.0 and later.#endifMODULE_AUTHOR("Donald Becker <becker@scyld.com>");MODULE_DESCRIPTION("SMC 83c170 EPIC series Ethernet driver");MODULE_LICENSE("GPL");MODULE_PARM(debug, "i");MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");MODULE_PARM(rx_copybreak, "i");MODULE_PARM(max_interrupt_work, "i");#if LINUX_VERSION_CODE < 0x20123#define test_and_set_bit(val, addr) set_bit(val, addr)typedef long spinlock_t;#define SPIN_LOCK_UNLOCKED 0#define spin_lock(lock)#define spin_unlock(lock)#define spin_lock_irqsave(lock, flags)	save_flags(flags); cli();#define spin_unlock_irqrestore(lock, flags) restore_flags(flags);#endif#if LINUX_VERSION_CODE >= 0x20155#define PCI_SUPPORT_VER2#endif#if LINUX_VERSION_CODE < 0x20159#define dev_free_skb(skb) dev_kfree_skb(skb, FREE_WRITE);#else  /* Grrr, unneeded incompatible change. */#define dev_free_skb(skb) dev_kfree_skb(skb);#endif#if ! defined(CAP_NET_ADMIN)#define capable(CAP_XXX) (suser())#endif/* The I/O extent. */#define EPIC_TOTAL_SIZE 0x100/*				Theory of OperationI. Board CompatibilityThis device driver is designed for the SMC "EPIC/100", the SMCsingle-chip Ethernet controllers for PCI.  This chip is used onthe SMC EtherPower II boards.II. Board-specific settingsPCI bus devices are configured by the system at boot time, so no jumpersneed to be set on the board.  The system BIOS will assign thePCI INTA signal to a (preferably otherwise unused) system IRQ line.Note: Kernel versions earlier than 1.3.73 do not support shared PCIinterrupt lines.III. Driver operationIIIa. Ring buffersIVb. Referenceshttp://www.smsc.com/main/datasheets/83c171.pdfhttp://www.smsc.com/main/datasheets/83c175.pdfhttp://www.scyld.com/expert/NWay.htmlhttp://www.national.com/pf/DP/DP83840A.htmlIVc. Errata*//* The rest of these values should never change. */static struct net_device *epic_probe1(int pci_bus, int pci_devfn,								  struct net_device *dev, long ioaddr, int irq,								  int chip_id, int card_idx);/* For 2.2 resource management we are kind of stuck with this */#define USE_IO								  #ifdef USE_IO#define EPIC_USE_IO#define EPIC_IOTYPE PCI_USES_MASTER|PCI_USES_IO|PCI_ADDR0#else#define EPIC_IOTYPE PCI_USES_MASTER|PCI_USES_MEM|PCI_ADDR1#endifenum pci_flags_bit {	PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,	PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,};struct chip_info {	const char *name;	u16	vendor_id, device_id, device_id_mask, pci_flags;	int io_size, min_latency;	struct net_device *(*probe1)(int pci_bus, int pci_devfn, struct net_device *dev,							 long ioaddr, int irq, int chip_idx, int fnd_cnt);} static chip_tbl[] = {	{"SMSC EPIC/100 83c170", 0x10B8, 0x0005, 0x7fff,	 EPIC_IOTYPE, EPIC_TOTAL_SIZE, 32, epic_probe1},	{"SMSC EPIC/C 83c175", 0x10B8, 0x0006, 0x7fff,	 EPIC_IOTYPE, EPIC_TOTAL_SIZE, 32, epic_probe1},	{0,},};/* This matches the table above. */static enum { MII_PWRDWN=1, TYPE2_INTR=2 } chip_features[] ={	TYPE2_INTR, TYPE2_INTR | MII_PWRDWN, };/* Offsets to registers, using the (ugh) SMC names. */enum epic_registers {  COMMAND=0, INTSTAT=4, INTMASK=8, GENCTL=0x0C, NVCTL=0x10, EECTL=0x14,  PCIBurstCnt=0x18,  TEST1=0x1C, CRCCNT=0x20, ALICNT=0x24, MPCNT=0x28,	/* Rx error counters. */  MIICtrl=0x30, MIIData=0x34, MIICfg=0x38,  LAN0=64,						/* MAC address. */  MC0=80,						/* Multicast filter table. */  RxCtrl=96, TxCtrl=112, TxSTAT=0x74,  PRxCDAR=0x84, RxSTAT=0xA4, EarlyRx=0xB0, PTxCDAR=0xC4, TxThresh=0xDC,};/* Interrupt register bits, using my own meaningful names. */enum IntrStatus {	TxIdle=0x40000, RxIdle=0x20000, IntrSummary=0x010000,	PCIBusErr170=0x7000, PCIBusErr175=0x1000, PhyEvent175=0x8000,	RxStarted=0x0800, RxEarlyWarn=0x0400, CntFull=0x0200, TxUnderrun=0x0100,	TxEmpty=0x0080, TxDone=0x0020, RxError=0x0010,	RxOverflow=0x0008, RxFull=0x0004, RxHeader=0x0002, RxDone=0x0001,};enum CommandBits {	StopRx=1, StartRx=2, TxQueued=4, RxQueued=8,	StopTxDMA=0x20, StopRxDMA=0x40, RestartTx=0x80,};static u16 media2miictl[16] = {	0, 0x0C00, 0x0C00, 0x2000,  0x0100, 0x2100, 0, 0,	0, 0, 0, 0,  0, 0, 0, 0 };/* The EPIC100 Rx and Tx buffer descriptors. */struct epic_tx_desc {	s16 status;	u16 txlength;	u32 bufaddr;	u16 buflength;	u16 control;	u32 next;};struct epic_rx_desc {	s16 status;	u16 rxlength;	u32 bufaddr;	u32 buflength;	u32 next;};struct epic_private {	char devname[8];			/* Used only for kernel debugging. */	const char *product_name;	struct net_device *next_module;	/* Tx and Rx rings here so that they remain paragraph aligned. */	struct epic_rx_desc rx_ring[RX_RING_SIZE];	struct epic_tx_desc tx_ring[TX_RING_SIZE];	/* The saved address of a sent-in-place packet/buffer, for skfree(). */	struct sk_buff* tx_skbuff[TX_RING_SIZE];	/* The addresses of receive-in-place skbuffs. */	struct sk_buff* rx_skbuff[RX_RING_SIZE];	/* Ring pointers. */	spinlock_t lock;				/* Group with Tx control cache line. */	unsigned int cur_tx, dirty_tx;	struct descriptor  *last_tx_desc;	unsigned int cur_rx, dirty_rx;	struct descriptor  *last_rx_desc;	long last_rx_time;				/* Last Rx, in jiffies. */	u8 pci_bus, pci_dev_fn;				/* PCI bus location. */	u16 chip_flags;	struct net_device_stats stats;	struct timer_list timer;			/* Media selection timer. */	int tx_threshold;	unsigned char mc_filter[8];	signed char phys[4];				/* MII device addresses. */	int mii_phy_cnt;	unsigned int tx_full:1;				/* The Tx queue is full. */	unsigned int full_duplex:1;			/* Current duplex setting. */	unsigned int force_fd:1;			/* Full-duplex operation requested. */	unsigned int default_port:4;		/* Last dev->if_port value. */	unsigned int media2:4;				/* Secondary monitored media port. */	unsigned int medialock:1;			/* Don't sense media type. */	unsigned int mediasense:1;			/* Media sensing in progress. */	int pad0, pad1;						/* Used for 8-byte alignment */};static int epic_open(struct net_device *dev);static int read_eeprom(long ioaddr, int location);static int mdio_read(long ioaddr, int phy_id, int location);static void mdio_write(long ioaddr, int phy_id, int location, int value);static void epic_restart(struct net_device *dev);static void epic_timer(unsigned long data);static void epic_tx_timeout(struct net_device *dev);static void epic_init_ring(struct net_device *dev);static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev);static int epic_rx(struct net_device *dev);static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs);static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);static int epic_close(struct net_device *dev);static struct net_device_stats *epic_get_stats(struct net_device *dev);static void set_rx_mode(struct net_device *dev);/* A list of all installed EPIC devices, for removing the driver module. */static struct net_device *root_epic_dev = NULL;#ifndef CARDBUSint epic100_probe(struct net_device *dev){	int cards_found = 0;	int chip_idx, irq;	u16 pci_command, new_command;	unsigned char pci_bus, pci_device_fn;#ifdef PCI_SUPPORT_VER2	struct pci_dev *pcidev = NULL;	while ((pcidev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pcidev))			!= NULL) {		long pci_ioaddr = pcidev->base_address[0] & ~3;		int vendor = pcidev->vendor;		int device = pcidev->device;		for (chip_idx = 0; chip_tbl[chip_idx].vendor_id; chip_idx++)			if (vendor == chip_tbl[chip_idx].vendor_id				&& (device & chip_tbl[chip_idx].device_id_mask) ==				chip_tbl[chip_idx].device_id)				break;		if (chip_tbl[chip_idx].vendor_id == 0)		/* Compiled out! */			continue;		pci_bus = pcidev->bus->number;		pci_device_fn = pcidev->devfn;		irq = pcidev->irq;#else	int pci_index;	if ( ! pcibios_present())		return -ENODEV;	for (pci_index = 0; pci_index < 0xff; pci_index++) {		u8 pci_irq_line;		u16 vendor, device;		u32 pci_ioaddr;		if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,								pci_index, &pci_bus, &pci_device_fn)			!= PCIBIOS_SUCCESSFUL)			break;		pcibios_read_config_word(pci_bus, pci_device_fn,								 PCI_VENDOR_ID, &vendor);		pcibios_read_config_word(pci_bus, pci_device_fn,								 PCI_DEVICE_ID, &device);		for (chip_idx = 0; chip_tbl[chip_idx].vendor_id; chip_idx++)			if (vendor == chip_tbl[chip_idx].vendor_id				&& (device & chip_tbl[chip_idx].device_id_mask) ==				chip_tbl[chip_idx].device_id)				break;		if (chip_tbl[chip_idx].vendor_id == 0) 		/* Compiled out! */			continue;		pcibios_read_config_dword(pci_bus, pci_device_fn,								  PCI_BASE_ADDRESS_0, &pci_ioaddr);		pcibios_read_config_byte(pci_bus, pci_device_fn,								 PCI_INTERRUPT_LINE, &pci_irq_line);		/* Remove I/O space marker in bit 0. */		pci_ioaddr &= ~3;		irq = pci_irq_line;		if (check_region(pci_ioaddr, chip_tbl[chip_idx].io_size))			continue;#endif		/* EPIC-specific code: Soft-reset the chip ere setting as master. */		outl(0x0001, pci_ioaddr + GENCTL);		/* Activate the card: fix for brain-damaged Win98 BIOSes. */		pcibios_read_config_word(pci_bus, pci_device_fn,								 PCI_COMMAND, &pci_command);		new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;		if (pci_command != new_command) {			printk(KERN_INFO "  The PCI BIOS has not enabled Ethernet"				   " device %4.4x-%4.4x."				   "  Updating PCI command %4.4x->%4.4x.\n",				   vendor, device, pci_command, new_command);			pcibios_write_config_word(pci_bus, pci_device_fn,									  PCI_COMMAND, new_command);		}		dev = chip_tbl[chip_idx].probe1(pci_bus, pci_device_fn, dev, pci_ioaddr,									   irq, chip_idx, cards_found);		/* Check the latency timer. */		if (dev) {			u8 pci_latency;			pcibios_read_config_byte(pci_bus, pci_device_fn,									 PCI_LATENCY_TIMER, &pci_latency);			if (pci_latency < chip_tbl[chip_idx].min_latency) {				printk(KERN_INFO "  PCI latency timer (CFLT) value of %d is "					   "unreasonably low, setting to %d.\n", pci_latency,					   chip_tbl[chip_idx].min_latency);				pcibios_write_config_byte(pci_bus, pci_device_fn,										  PCI_LATENCY_TIMER,										  chip_tbl[chip_idx].min_latency);			}			dev = 0;			cards_found++;		}	}	return cards_found ? 0 : -ENODEV;}#endif  /* not CARDBUS */static struct net_device *epic_probe1(int pci_bus, int pci_devfn,								  struct net_device *dev, long ioaddr, int irq,								  int chip_idx, int card_idx){	struct epic_private *ep;	int i, option = 0, duplex = 0;	if (dev && dev->mem_start) {		option = dev->mem_start;		duplex = (dev->mem_start & 16) ? 1 : 0;	} else if (card_idx >= 0  &&  card_idx < MAX_UNITS) {		if (options[card_idx] >= 0)			option = options[card_idx];		if (full_duplex[card_idx] >= 0)			duplex = full_duplex[card_idx];	}	dev = init_etherdev(dev, 0);	dev->base_addr = ioaddr;	dev->irq = irq;	printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ",		   dev->name, chip_tbl[chip_idx].name, ioaddr, dev->irq);	/* Bring the chip out of low-power mode. */	outl(0x4200, ioaddr + GENCTL);	/* Magic?!  If we don't set this bit the MII interface won't work. */	outl(0x0008, ioaddr + TEST1);	/* Turn on the MII transceiver. */	outl(0x12, ioaddr + MIICfg);	if (chip_idx == 1)		outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);	outl(0x0200, ioaddr + GENCTL);	/* This could also be read from the EEPROM. */	for (i = 0; i < 3; i++)		((u16 *)dev->dev_addr)[i] = le16_to_cpu(inw(ioaddr + LAN0 + i*4));	for (i = 0; i < 5; i++)		printk("%2.2x:", dev->dev_addr[i]);	printk("%2.2x.\n", dev->dev_addr[i]);	if (epic_debug > 2) {		printk(KERN_DEBUG "%s: EEPROM contents\n", dev->name);		for (i = 0; i < 64; i++)			printk(" %4.4x%s", read_eeprom(ioaddr, i),				   i % 16 == 15 ? "\n" : "");	}	/* We do a request_region() to register /proc/ioports info. */	request_region(ioaddr, EPIC_TOTAL_SIZE, dev->name);	/* The data structures must be quadword aligned. */	ep = kmalloc(sizeof(*ep), GFP_KERNEL | GFP_DMA);	memset(ep, 0, sizeof(*ep));	dev->priv = ep;	ep->next_module = root_epic_dev;	root_epic_dev = dev;	ep->pci_bus = pci_bus;	ep->pci_dev_fn = pci_devfn;	ep->chip_flags = chip_features[chip_idx];	/* Find the connected MII xcvrs.	   Doing this in open() would allow detecting external xcvrs later, but	   takes too much time. */	{		int phy, phy_idx;		for (phy = 1, phy_idx = 0; phy < 32 && phy_idx < sizeof(ep->phys);			 phy++) {			int mii_status = mdio_read(ioaddr, phy, 1);			if (mii_status != 0xffff  && mii_status != 0x0000) {				ep->phys[phy_idx++] = phy;				printk(KERN_INFO "%s: MII transceiver #%d control "					   "%4.4x status %4.4x.\n"					   KERN_INFO "%s:  Autonegotiation advertising %4.4x "					   "link partner %4.4x.\n",					   dev->name, phy, mdio_read(ioaddr, phy, 0), mii_status,					   dev->name, mdio_read(ioaddr, phy, 4),

⌨️ 快捷键说明

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