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

📄 xircom_cb.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * xircom_cb: A driver for the (tulip-like) Xircom Cardbus ethernet cards  * * This software is (C) by the respective authors, and licensed under the GPL * License. * * Written by Arjan van de Ven for Red Hat, Inc. * Based on work by Jeff Garzik, Doug Ledford and Donald Becker  * *  	This software may be used and distributed according to the terms *      of the GNU General Public License, incorporated herein by reference. * * * 	$Id: xircom_cb.c,v 1.33 2001/03/19 14:02:07 arjanv Exp $ */#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/pci.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <linux/delay.h>#include <linux/init.h>#include <linux/ethtool.h>#include <linux/bitops.h>#include <asm/uaccess.h>#include <asm/io.h>#ifdef DEBUG#define enter(x)   printk("Enter: %s, %s line %i\n",x,__FILE__,__LINE__)#define leave(x)   printk("Leave: %s, %s line %i\n",x,__FILE__,__LINE__)#else#define enter(x)   do {} while (0)#define leave(x)   do {} while (0)#endifMODULE_DESCRIPTION("Xircom Cardbus ethernet driver");MODULE_AUTHOR("Arjan van de Ven <arjanv@redhat.com>");MODULE_LICENSE("GPL");/* IO registers on the card, offsets */#define CSR0	0x00#define CSR1	0x08#define CSR2	0x10#define CSR3	0x18#define CSR4	0x20#define CSR5	0x28#define CSR6	0x30#define CSR7	0x38#define CSR8	0x40#define CSR9	0x48#define CSR10	0x50#define CSR11	0x58#define CSR12	0x60#define CSR13	0x68#define CSR14	0x70#define CSR15	0x78#define CSR16	0x80/* PCI registers */#define PCI_POWERMGMT 	0x40/* Offsets of the buffers within the descriptor pages, in bytes */#define NUMDESCRIPTORS 4static int bufferoffsets[NUMDESCRIPTORS] = {128,2048,4096,6144};struct xircom_private {	/* Send and receive buffers, kernel-addressable and dma addressable forms */	unsigned int *rx_buffer;	unsigned int *tx_buffer;	dma_addr_t rx_dma_handle;	dma_addr_t tx_dma_handle;	struct sk_buff *tx_skb[4];	unsigned long io_port;	int open;		/* transmit_used is the rotating counter that indicates which transmit	   descriptor has to be used next */	int transmit_used;	/* Spinlock to serialize register operations.	   It must be helt while manipulating the following registers:	   CSR0, CSR6, CSR7, CSR9, CSR10, CSR15	 */	spinlock_t lock;	struct pci_dev *pdev;	struct net_device *dev;	struct net_device_stats stats;};/* Function prototypes */static int xircom_probe(struct pci_dev *pdev, const struct pci_device_id *id);static void xircom_remove(struct pci_dev *pdev);static irqreturn_t xircom_interrupt(int irq, void *dev_instance, struct pt_regs *regs);static int xircom_start_xmit(struct sk_buff *skb, struct net_device *dev);static int xircom_open(struct net_device *dev);static int xircom_close(struct net_device *dev);static void xircom_up(struct xircom_private *card);static struct net_device_stats *xircom_get_stats(struct net_device *dev);#ifdef CONFIG_NET_POLL_CONTROLLERstatic void xircom_poll_controller(struct net_device *dev);#endifstatic void investigate_read_descriptor(struct net_device *dev,struct xircom_private *card, int descnr, unsigned int bufferoffset);static void investigate_write_descriptor(struct net_device *dev, struct xircom_private *card, int descnr, unsigned int bufferoffset);static void read_mac_address(struct xircom_private *card);static void transceiver_voodoo(struct xircom_private *card);static void initialize_card(struct xircom_private *card);static void trigger_transmit(struct xircom_private *card);static void trigger_receive(struct xircom_private *card);static void setup_descriptors(struct xircom_private *card);static void remove_descriptors(struct xircom_private *card);static int link_status_changed(struct xircom_private *card);static void activate_receiver(struct xircom_private *card);static void deactivate_receiver(struct xircom_private *card);static void activate_transmitter(struct xircom_private *card);static void deactivate_transmitter(struct xircom_private *card);static void enable_transmit_interrupt(struct xircom_private *card);static void enable_receive_interrupt(struct xircom_private *card);static void enable_link_interrupt(struct xircom_private *card);static void disable_all_interrupts(struct xircom_private *card);static int link_status(struct xircom_private *card);static struct pci_device_id xircom_pci_table[] = {	{0x115D, 0x0003, PCI_ANY_ID, PCI_ANY_ID,},	{0,},};MODULE_DEVICE_TABLE(pci, xircom_pci_table);static struct pci_driver xircom_ops = {	.name		= "xircom_cb", 	.id_table	= xircom_pci_table, 	.probe		= xircom_probe, 	.remove		= xircom_remove, 	.suspend =NULL,	.resume =NULL};#ifdef DEBUGstatic void print_binary(unsigned int number){	int i,i2;	char buffer[64];	memset(buffer,0,64);	i2=0;	for (i=31;i>=0;i--) {		if (number & (1<<i))			buffer[i2++]='1';		else			buffer[i2++]='0';		if ((i&3)==0) 			buffer[i2++]=' ';	}	printk("%s\n",buffer);}#endifstatic void netdev_get_drvinfo(struct net_device *dev,			       struct ethtool_drvinfo *info){	struct xircom_private *private = netdev_priv(dev);	strcpy(info->driver, "xircom_cb");	strcpy(info->bus_info, pci_name(private->pdev));}static struct ethtool_ops netdev_ethtool_ops = {	.get_drvinfo		= netdev_get_drvinfo,};/* xircom_probe is the code that gets called on device insertion.   it sets up the hardware and registers the device to the networklayer.      TODO: Send 1 or 2 "dummy" packets here as the card seems to discard the         first two packets that get send, and pump hates that.          */static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_id *id){	struct net_device *dev = NULL;	struct xircom_private *private;	unsigned char chip_rev;	unsigned long flags;	unsigned short tmp16;	enter("xircom_probe");		/* First do the PCI initialisation */	if (pci_enable_device(pdev))		return -ENODEV;	/* disable all powermanagement */	pci_write_config_dword(pdev, PCI_POWERMGMT, 0x0000);		pci_set_master(pdev); /* Why isn't this done by pci_enable_device ?*/	/* clear PCI status, if any */ 	pci_read_config_word (pdev,PCI_STATUS, &tmp16); 	pci_write_config_word (pdev, PCI_STATUS,tmp16);		pci_read_config_byte(pdev, PCI_REVISION_ID, &chip_rev);		if (!request_region(pci_resource_start(pdev, 0), 128, "xircom_cb")) {		printk(KERN_ERR "xircom_probe: failed to allocate io-region\n");		return -ENODEV;	}	/* 	   Before changing the hardware, allocate the memory.	   This way, we can fail gracefully if not enough memory	   is available. 	 */	dev = alloc_etherdev(sizeof(struct xircom_private));	if (!dev) {		printk(KERN_ERR "xircom_probe: failed to allocate etherdev\n");		goto device_fail;	}	private = netdev_priv(dev);		/* Allocate the send/receive buffers */	private->rx_buffer = pci_alloc_consistent(pdev,8192,&private->rx_dma_handle);	if (private->rx_buffer == NULL) { 		printk(KERN_ERR "xircom_probe: no memory for rx buffer \n");		goto rx_buf_fail;	}		private->tx_buffer = pci_alloc_consistent(pdev,8192,&private->tx_dma_handle);	if (private->tx_buffer == NULL) {		printk(KERN_ERR "xircom_probe: no memory for tx buffer \n");		goto tx_buf_fail;	}	SET_MODULE_OWNER(dev);	SET_NETDEV_DEV(dev, &pdev->dev);	private->dev = dev;	private->pdev = pdev;	private->io_port = pci_resource_start(pdev, 0);	spin_lock_init(&private->lock);	dev->irq = pdev->irq;	dev->base_addr = private->io_port;		initialize_card(private);	read_mac_address(private);	setup_descriptors(private);		dev->open = &xircom_open;	dev->hard_start_xmit = &xircom_start_xmit;	dev->stop = &xircom_close;	dev->get_stats = &xircom_get_stats;	dev->priv = private;#ifdef CONFIG_NET_POLL_CONTROLLER	dev->poll_controller = &xircom_poll_controller;#endif	SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);	pci_set_drvdata(pdev, dev);	if (register_netdev(dev)) {		printk(KERN_ERR "xircom_probe: netdevice registration failed.\n");		goto reg_fail;	}			printk(KERN_INFO "%s: Xircom cardbus revision %i at irq %i \n", dev->name, chip_rev, pdev->irq);	/* start the transmitter to get a heartbeat */	/* TODO: send 2 dummy packets here */	transceiver_voodoo(private);		spin_lock_irqsave(&private->lock,flags);	activate_transmitter(private);	activate_receiver(private);	spin_unlock_irqrestore(&private->lock,flags);		trigger_receive(private);		leave("xircom_probe");	return 0;reg_fail:	kfree(private->tx_buffer);tx_buf_fail:	kfree(private->rx_buffer);rx_buf_fail:	free_netdev(dev);device_fail:	return -ENODEV;}/* xircom_remove is called on module-unload or on device-eject. it unregisters the irq, io-region and network device. Interrupts and such are already stopped in the "ifconfig ethX down" code. */static void __devexit xircom_remove(struct pci_dev *pdev){	struct net_device *dev = pci_get_drvdata(pdev);	struct xircom_private *card = netdev_priv(dev);	enter("xircom_remove");	pci_free_consistent(pdev,8192,card->rx_buffer,card->rx_dma_handle);	pci_free_consistent(pdev,8192,card->tx_buffer,card->tx_dma_handle);	release_region(dev->base_addr, 128);	unregister_netdev(dev);	free_netdev(dev);	pci_set_drvdata(pdev, NULL);	leave("xircom_remove");} static irqreturn_t xircom_interrupt(int irq, void *dev_instance, struct pt_regs *regs){	struct net_device *dev = (struct net_device *) dev_instance;	struct xircom_private *card = netdev_priv(dev);	unsigned int status;	int i;	enter("xircom_interrupt\n");	spin_lock(&card->lock);	status = inl(card->io_port+CSR5);#ifdef DEBUG		print_binary(status);	printk("tx status 0x%08x 0x%08x \n",card->tx_buffer[0],card->tx_buffer[4]);	printk("rx status 0x%08x 0x%08x \n",card->rx_buffer[0],card->rx_buffer[4]);#endif		/* Handle shared irq and hotplug */	if (status == 0 || status == 0xffffffff) {		spin_unlock(&card->lock);		return IRQ_NONE;	}	if (link_status_changed(card)) {		int newlink;		printk(KERN_DEBUG "xircom_cb: Link status has changed \n");		newlink = link_status(card);		printk(KERN_INFO  "xircom_cb: Link is %i mbit \n",newlink);		if (newlink)			netif_carrier_on(dev);		else			netif_carrier_off(dev);			}	/* Clear all remaining interrupts */		status |= 0xffffffff; /* FIXME: make this clear only the				        real existing bits */	outl(status,card->io_port+CSR5);		for (i=0;i<NUMDESCRIPTORS;i++) 		investigate_write_descriptor(dev,card,i,bufferoffsets[i]);	for (i=0;i<NUMDESCRIPTORS;i++) 		investigate_read_descriptor(dev,card,i,bufferoffsets[i]);		spin_unlock(&card->lock);	leave("xircom_interrupt");	return IRQ_HANDLED;}static int xircom_start_xmit(struct sk_buff *skb, struct net_device *dev){	struct xircom_private *card;	unsigned long flags;	int nextdescriptor;	int desc;	enter("xircom_start_xmit");		card = netdev_priv(dev);	spin_lock_irqsave(&card->lock,flags);		/* First see if we can free some descriptors */	for (desc=0;desc<NUMDESCRIPTORS;desc++) 		investigate_write_descriptor(dev,card,desc,bufferoffsets[desc]);			nextdescriptor = (card->transmit_used +1) % (NUMDESCRIPTORS);	desc = card->transmit_used;		/* only send the packet if the descriptor is free */	if (card->tx_buffer[4*desc]==0) {			/* Copy the packet data; zero the memory first as the card			   sometimes sends more than you ask it to. */						memset(&card->tx_buffer[bufferoffsets[desc]/4],0,1536);			memcpy(&(card->tx_buffer[bufferoffsets[desc]/4]),skb->data,skb->len);					/* FIXME: The specification tells us that the length we send HAS to be a multiple of			   4 bytes. */			   			card->tx_buffer[4*desc+1] = skb->len;			if (desc == NUMDESCRIPTORS-1)				card->tx_buffer[4*desc+1] |= (1<<25);  /* bit 25: last descriptor of the ring */			card->tx_buffer[4*desc+1] |= 0xF0000000;						 /* 0xF0... means want interrupts*/ 			card->tx_skb[desc] = skb;						wmb();			/* This gives the descriptor to the card */

⌨️ 快捷键说明

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