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

📄 3c527.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* 3c527.c: 3Com Etherlink/MC32 driver for Linux * *	(c) Copyright 1998 Red Hat Software Inc *	Written by Alan Cox. *	Further debugging by Carl Drougge. * *	Based on skeleton.c written 1993-94 by Donald Becker and ne2.c *	(for the MCA stuff) written by Wim Dumon. * *	Thanks to 3Com for making this possible by providing me with the *	documentation. * *	This software may be used and distributed according to the terms *	of the GNU Public License, incorporated herein by reference. * */static const char *version =	"3c527.c:v0.08 2000/02/22 Alan Cox (alan@redhat.com)\n";/** * DOC: Traps for the unwary * *	The diagram (Figure 1-1) and the POS summary disagree with the *	"Interrupt Level" section in the manual. * *	The documentation in places seems to miss things. In actual fact *	I've always eventually found everything is documented, it just *	requires careful study. * * DOC: Theory Of Operation * *	The 3com 3c527 is a 32bit MCA bus mastering adapter with a large *	amount of on board intelligence that housekeeps a somewhat dumber *	Intel NIC. For performance we want to keep the transmit queue deep *	as the card can transmit packets while fetching others from main *	memory by bus master DMA. Transmission and reception are driven by *	ring buffers. When updating the ring we are required to do some *	housekeeping work using the mailboxes and the command register. * *	The mailboxes provide a method for sending control requests to the *	card. The transmit mail box is used to update the transmit ring  *	pointers and the receive mail box to update the receive ring *	pointers. The exec mailbox allows a variety of commands to be *	executed. Each command must complete before the next is executed. *	Primarily we use the exec mailbox for controlling the multicast lists. *	We have to do a certain amount of interesting hoop jumping as the  *	multicast list changes can occur in interrupt state when the card *	has an exec command pending. We defer such events until the command *	completion interrupt. * *	The control register is used to pass status information. It tells us *	the transmit and receive status for packets and allows us to control *	the card operation mode. You must stop the card when emptying the *	receive ring, or you will race with the ring buffer and lose packets. */#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/fcntl.h>#include <linux/interrupt.h>#include <linux/ptrace.h>#include <linux/mca.h>#include <linux/ioport.h>#include <linux/in.h>#include <linux/malloc.h>#include <linux/string.h>#include <asm/system.h>#include <asm/bitops.h>#include <asm/io.h>#include <asm/dma.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include "3c527.h"/* * The name of the card. Is used for messages and in the requests for * io regions, irqs and dma channels */static const char* cardname = "3c527";/* use 0 for production, 1 for verification, >2 for debug */#ifndef NET_DEBUG#define NET_DEBUG 2#endifstatic unsigned int mc32_debug = NET_DEBUG;/* The number of low I/O ports used by the ethercard. */#define NETCARD_IO_EXTENT	8struct mc32_mailbox{	u16	mbox __attribute((packed));	u16	data[1] __attribute((packed));};/* Information that need to be kept for each board. */#define TX_RING_MAX	16	/* Typically the card supports 37 */#define RX_RING_MAX	32	/*        "     "       "         */struct mc32_local {	struct net_device_stats net_stats;	int slot;	volatile struct mc32_mailbox *rx_box;	volatile struct mc32_mailbox *tx_box;	volatile struct mc32_mailbox *exec_box;	volatile u16 *stats;	u16 tx_chain;	u16 rx_chain;	u16 tx_len;	u16 rx_len;	u32 base;	u16 rx_halted;	u16 tx_halted;	u16 rx_pending;	u16 exec_pending;	u16 mc_reload_wait;	/* a multicast load request is pending */	atomic_t tx_count;		/* buffers left */	wait_queue_head_t event;	struct sk_buff *tx_skb[TX_RING_MAX];	/* Transmit ring */	u16 tx_skb_top;	u16 tx_skb_end;	struct sk_buff *rx_skb[RX_RING_MAX];	/* Receive ring */	void *rx_ptr[RX_RING_MAX];		/* Data pointers */	u32 mc_list_valid;			/* True when the mclist is set */};/* The station (ethernet) address prefix, used for a sanity check. */#define SA_ADDR0 0x02#define SA_ADDR1 0x60#define SA_ADDR2 0xACstruct mca_adapters_t {	unsigned int	id;	char		*name;};static struct mca_adapters_t mc32_adapters[] __initdata = {	{ 0x0041, "3COM EtherLink MC/32" },	{ 0x8EF5, "IBM High Performance Lan Adapter" },	{ 0x0000, NULL }};/* Index to functions, as function prototypes. */extern int mc32_probe(struct net_device *dev);static int	mc32_probe1(struct net_device *dev, int ioaddr);static int	mc32_open(struct net_device *dev);static void	mc32_timeout(struct net_device *dev);static int	mc32_send_packet(struct sk_buff *skb, struct net_device *dev);static void	mc32_interrupt(int irq, void *dev_id, struct pt_regs *regs);static int	mc32_close(struct net_device *dev);static struct	net_device_stats *mc32_get_stats(struct net_device *dev);static void	mc32_set_multicast_list(struct net_device *dev);static void	mc32_reset_multicast_list(struct net_device *dev);/** * mc32_probe: * @dev: device to probe * * Because MCA bus is a real bus and we can scan for cards we could do a * single scan for all boards here. Right now we use the passed in device * structure and scan for only one board. This needs fixing for modules * in paticular. */int __init mc32_probe(struct net_device *dev){	static int current_mca_slot = -1;	int i;	int adapter_found = 0;	SET_MODULE_OWNER(dev);	/* Do not check any supplied i/o locations. 	   POS registers usually don't fail :) */	/* MCA cards have POS registers.  	   Autodetecting MCA cards is extremely simple. 	   Just search for the card. */	for(i = 0; (mc32_adapters[i].name != NULL) && !adapter_found; i++) {		current_mca_slot = 			mca_find_unused_adapter(mc32_adapters[i].id, 0);		if((current_mca_slot != MCA_NOTFOUND) && !adapter_found) {			if(!mc32_probe1(dev, current_mca_slot))			{				mca_set_adapter_name(current_mca_slot, 						mc32_adapters[i].name);				mca_mark_as_used(current_mca_slot);				return 0;			}					}	}	return -ENODEV;}/** * mc32_probe1: * @dev:  Device structure to fill in * @slot: The MCA bus slot being used by this card * * Decode the slot data and configure the card structures. Having done this we * can reset the card and configure it. The card does a full self test cycle * in firmware so we have to wait for it to return and post us either a  * failure case or some addresses we use to find the board internals. */ static int __init mc32_probe1(struct net_device *dev, int slot){	static unsigned version_printed = 0;	int i;	u8 POS;	u32 base;	struct mc32_local *lp;	static u16 mca_io_bases[]={		0x7280,0x7290,		0x7680,0x7690,		0x7A80,0x7A90,		0x7E80,0x7E90	};	static u32 mca_mem_bases[]={		0x00C0000,		0x00C4000,		0x00C8000,		0x00CC000,		0x00D0000,		0x00D4000,		0x00D8000,		0x00DC000	};	static char *failures[]={		"Processor instruction",		"Processor data bus",		"Processor data bus",		"Processor data bus",		"Adapter bus",		"ROM checksum",		"Base RAM",		"Extended RAM",		"82586 internal loopback",		"82586 initialisation failure",		"Adapter list configuration error"	};		/* Time to play MCA games */	if (mc32_debug  &&  version_printed++ == 0)		printk(KERN_DEBUG "%s", version);	printk(KERN_INFO "%s: %s found in slot %d:", dev->name, cardname, slot);	POS = mca_read_stored_pos(slot, 2);		if(!(POS&1))	{		printk(" disabled.\n");		return -ENODEV;	}	/* Fill in the 'dev' fields. */	dev->base_addr = mca_io_bases[(POS>>1)&7];	dev->mem_start = mca_mem_bases[(POS>>4)&7];		POS = mca_read_stored_pos(slot, 4);	if(!(POS&1))	{		printk("memory window disabled.\n");		return -ENODEV;	}	POS = mca_read_stored_pos(slot, 5);		i=(POS>>4)&3;	if(i==3)	{		printk("invalid memory window.\n");		return -ENODEV;	}		i*=16384;	i+=16384;		dev->mem_end=dev->mem_start + i;		dev->irq = ((POS>>2)&3)+9;		printk("io 0x%3lX irq %d mem 0x%lX (%dK)\n",		dev->base_addr, dev->irq, dev->mem_start, i/1024);			/* We ought to set the cache line size here.. */			/*	 *	Go PROM browsing	 */	 	printk("%s: Address ", dev->name);	 	/* Retrieve and print the ethernet address. */	for (i = 0; i < 6; i++)	{		mca_write_pos(slot, 6, i+12);		mca_write_pos(slot, 7, 0);			printk(" %2.2x", dev->dev_addr[i] = mca_read_pos(slot,3));	}	mca_write_pos(slot, 6, 0);	mca_write_pos(slot, 7, 0);	POS = mca_read_stored_pos(slot, 4);		if(POS&2)		printk(" : BNC port selected.\n");	else 		printk(" : AUI port selected.\n");			POS=inb(dev->base_addr+HOST_CTRL);	POS|=HOST_CTRL_ATTN|HOST_CTRL_RESET;	POS&=~HOST_CTRL_INTE;	outb(POS, dev->base_addr+HOST_CTRL);	/* Reset adapter */	udelay(100);	/* Reset off */	POS&=~(HOST_CTRL_ATTN|HOST_CTRL_RESET);	outb(POS, dev->base_addr+HOST_CTRL);		udelay(300);		/*	 *	Grab the IRQ	 */	i = request_irq(dev->irq, &mc32_interrupt, 0, dev->name, dev);	if (i) {		printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq);		return i;	}	/* Initialize the device structure. */	dev->priv = kmalloc(sizeof(struct mc32_local), GFP_KERNEL);	if (dev->priv == NULL)	{		free_irq(dev->irq, dev);		return -ENOMEM;	}	memset(dev->priv, 0, sizeof(struct mc32_local));	lp = dev->priv;	lp->slot = slot;	i=0;	base = inb(dev->base_addr);		while(base==0xFF)	{		i++;		if(i==1000)		{			printk("%s: failed to boot adapter.\n", dev->name);			free_irq(dev->irq, dev);			return -ENODEV;		}		udelay(1000);		if(inb(dev->base_addr+2)&(1<<5))			base = inb(dev->base_addr);	}	if(base>0)	{		if(base < 0x0C)			printk("%s: %s%s.\n", dev->name, failures[base-1],				base<0x0A?" test failure":"");		else			printk("%s: unknown failure %d.\n", dev->name, base);		free_irq(dev->irq, dev);		return -ENODEV;	}		base=0;	for(i=0;i<4;i++)	{		int n=0;			while(!(inb(dev->base_addr+2)&(1<<5)))		{			n++;			udelay(50);			if(n>100)			{				printk(KERN_ERR "%s: mailbox read fail (%d).\n", dev->name, i);				free_irq(dev->irq, dev);				return -ENODEV;			}		}		base|=(inb(dev->base_addr)<<(8*i));	}		lp->exec_box=bus_to_virt(dev->mem_start+base);		base=lp->exec_box->data[1]<<16|lp->exec_box->data[0];		lp->base = dev->mem_start+base;		lp->rx_box=bus_to_virt(lp->base + lp->exec_box->data[2]);	lp->tx_box=bus_to_virt(lp->base + lp->exec_box->data[3]);		lp->stats = bus_to_virt(lp->base + lp->exec_box->data[5]);	/*	 *	Descriptor chains (card relative)	 */	 	lp->tx_chain 		= lp->exec_box->data[8];	lp->rx_chain 		= lp->exec_box->data[10];	lp->tx_len 		= lp->exec_box->data[9];	lp->rx_len 		= lp->exec_box->data[11];	init_waitqueue_head(&lp->event);		printk("%s: %d RX buffers, %d TX buffers. Base of 0x%08X.\n",		dev->name, lp->rx_len, lp->tx_len, lp->base);			if(lp->tx_len > TX_RING_MAX)		lp->tx_len = TX_RING_MAX;		dev->open		= mc32_open;	dev->stop		= mc32_close;	dev->hard_start_xmit	= mc32_send_packet;	dev->get_stats		= mc32_get_stats;	dev->set_multicast_list = mc32_set_multicast_list;	dev->tx_timeout		= mc32_timeout;	dev->watchdog_timeo	= HZ*5;	/* Board does all the work */		lp->rx_halted		= 1;	lp->tx_halted		= 1;	lp->rx_pending		= 0;	/* Fill in the fields of the device structure with ethernet values. */	ether_setup(dev);	return 0;}/** *	mc32_ring_poll: *	@dev:	The device to wait for *	 *	Wait until a command we issues to the control register is completed. *	This actually takes very little time at all, which is fortunate as *	we often have to busy wait it. */ static void mc32_ring_poll(struct net_device *dev){	int ioaddr = dev->base_addr;	while(!(inb(ioaddr+HOST_STATUS)&HOST_STATUS_CRR));}/** *	mc32_command_nowait: *	@dev: The 3c527 to issue the command to *	@cmd: The command word to write to the mailbox *	@data: A data block if the command expects one *	@len: Length of the data block * *	Send a command from interrupt state. If there is a command currently *	being executed then we return an error of -1. It simply isnt viable *	to wait around as commands may be slow. Providing we get in then *	we send the command and busy wait for the board to acknowledge that *	a command request is pending. We do not wait for the command to  *	complete, just for the card to admit to noticing it.   */static int mc32_command_nowait(struct net_device *dev, u16 cmd, void *data, int len){	struct mc32_local *lp = (struct mc32_local *)dev->priv;	int ioaddr = dev->base_addr;	

⌨️ 快捷键说明

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