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

📄 3c527.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 3c527.c: 3Com Etherlink/MC32 driver for Linux * *	(c) Copyright 1998 Red Hat Software Inc *	Written by Alan Cox. * *	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.04 1999/03/16 Alan Cox (alan@redhat.com)\n";/* *	Things you need *	o	The databook. * *	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. */#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 exec_pending;	u16 mc_reload_wait;	/* a multicast load request is pending */	atomic_t tx_count;		/* buffers left */	struct wait_queue *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 */};/* 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;};const struct mca_adapters_t mc32_adapters[] = {	{ 0x0041, "3COM EtherLink MC/32" },	{ 0x8EF5, "IBM High Performance Lan Adapter" },	{ 0x0000, NULL }};/* Index to functions, as function prototypes. */extern int mc32_probe(struct device *dev);static int	mc32_probe1(struct device *dev, int ioaddr);static int	mc32_open(struct device *dev);static int	mc32_send_packet(struct sk_buff *skb, struct device *dev);static void	mc32_interrupt(int irq, void *dev_id, struct pt_regs *regs);static int	mc32_close(struct device *dev);static struct	net_device_stats *mc32_get_stats(struct device *dev);static void	mc32_set_multicast_list(struct device *dev);/* * Check for a network adaptor of this type, and return '0' iff one exists. * If dev->base_addr == 0, probe all likely locations. * If dev->base_addr == 1, always return failure. * If dev->base_addr == 2, allocate space for the device and return success * (detachable devices only). */__initfunc(int mc32_probe(struct device *dev)){	static int current_mca_slot = -1;	int i;	int adapter_found = 0;	/* 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;}/* * This is the real probe routine. Linux has a history of friendly device * probes on the ISA bus. A good device probes avoids doing writes, and * verifies that the correct device exists and functions. */__initfunc(static int mc32_probe1(struct 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;	}	/* Allocate a new 'dev' if needed. */	if (dev == NULL) {		/*		 * Don't allocate the private data here, it is done later		 * This makes it easier to free the memory when this driver		 * is used as a module.		 */		dev = init_etherdev(0, 0);		if (dev == NULL)			return -ENOMEM;	}	/* 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	 */	if(request_irq(dev->irq, &mc32_interrupt, 0, cardname, dev))	{		printk("%s: unable to get IRQ %d.\n",				   dev->name, dev->irq);		return -EAGAIN;	}	/* Initialize the device structure. */	if (dev->priv == NULL) {		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 = (struct mc32_local *)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];		printk("%s: %d RX buffers, %d TX buffers. Base of 0x%08X.\n",		dev->name, lp->rx_len, lp->tx_len, lp->base);		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;		lp->rx_halted		= 1;	lp->tx_halted		= 1;	/* Fill in the fields of the device structure with ethernet values. */	ether_setup(dev);	return 0;}/* *	Polled command stuff  */ static void mc32_ring_poll(struct device *dev){	int ioaddr = dev->base_addr;	while(!(inb(ioaddr+HOST_STATUS)&HOST_STATUS_CRR));}/* *	Send exec commands */ static int mc32_command(struct device *dev, u16 cmd, void *data, int len){	struct mc32_local *lp = (struct mc32_local *)dev->priv;	int ioaddr = dev->base_addr;	unsigned long flags;		while(lp->exec_pending)		sleep_on(&lp->event);			lp->exec_pending=1;	lp->exec_box->mbox=0;	lp->exec_box->mbox=cmd;	memcpy((void *)lp->exec_box->data, data, len);	barrier();	/* the memcpy forgot the volatile so be sure */	/* Send the command */	while(!(inb(ioaddr+HOST_STATUS)&HOST_STATUS_CRR));	outb(1<<6, ioaddr+HOST_CMD);			save_flags(flags);	cli();	while(lp->exec_pending!=2)		sleep_on(&lp->event);	lp->exec_pending=0;	restore_flags(flags);		/*	 *	A multicast set got blocked - do it now	 */	 	if(lp->mc_reload_wait)		mc32_set_multicast_list(dev);	if(lp->exec_box->data[0]&(1<<13))		return -1;	return 0;}/* *	RX abort */ static void mc32_rx_abort(struct device *dev){	struct mc32_local *lp = (struct mc32_local *)dev->priv;	int ioaddr = dev->base_addr;	while(!(inb(ioaddr+HOST_STATUS)&HOST_STATUS_CRR));		lp->rx_box->mbox=0;	outb(3<<3, ioaddr+HOST_CMD);	/* Suspend reception */} /* *	RX enable */ static void mc32_rx_begin(struct device *dev){	struct mc32_local *lp = (struct mc32_local *)dev->priv;	int ioaddr = dev->base_addr;		while(!(inb(ioaddr+HOST_STATUS)&HOST_STATUS_CRR));		lp->rx_box->mbox=0;	outb(1<<3, ioaddr+HOST_CMD);	/* GO */	mc32_ring_poll(dev);			lp->rx_halted=0;}static void mc32_tx_abort(struct device *dev){	struct mc32_local *lp = (struct mc32_local *)dev->priv;	int ioaddr = dev->base_addr;		while(!(inb(ioaddr+HOST_STATUS)&HOST_STATUS_CRR));		lp->tx_box->mbox=0;	outb(3, ioaddr+HOST_CMD);	/* Suspend */		/* Ring empty */		atomic_set(&lp->tx_count, lp->tx_len);		/* Flush */	if(lp->tx_skb_top!=lp->tx_skb_end)	{		int i;		if(lp->tx_skb_top<=lp->tx_skb_end)		{			for(i=lp->tx_skb_top;i<lp->tx_skb_end;i++)			{				dev_kfree_skb(lp->tx_skb[i]);				lp->tx_skb[i]=NULL;			}		}		else		{			for(i=lp->tx_skb_end;i<TX_RING_MAX;i++)			{				dev_kfree_skb(lp->tx_skb[i]);				lp->tx_skb[i]=NULL;			}			for(i=0;i<lp->tx_skb_top;i++)			{				dev_kfree_skb(lp->tx_skb[i]);				lp->tx_skb[i]=NULL;			}		}	}	lp->tx_skb_top=lp->tx_skb_end=0;}/* *	TX enable */ static void mc32_tx_begin(struct device *dev){	struct mc32_local *lp = (struct mc32_local *)dev->priv;	int ioaddr = dev->base_addr;		while(!(inb(ioaddr+HOST_STATUS)&HOST_STATUS_CRR));		lp->tx_box->mbox=0;#if 0		outb(5, ioaddr+HOST_CMD);	/* GO */	printk("TX=>5\n");

⌨️ 快捷键说明

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