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

📄 rcpci45.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ****  RCpci45.c  ********  ---------------------------------------------------------------------**  ---     Copyright (c) 1998, 1999, RedCreek Communications Inc.    ---**  ---                   All rights reserved.                        ---**  ---------------------------------------------------------------------**** Written by Pete Popov and Brian Moyle.**** Known Problems** ** None known at this time.****  This program 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 program 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.****  Pete Popov, Oct 2001: Fixed a few bugs to make the driver functional**  again. Note that this card is not supported or manufactured by **  RedCreek anymore.**   **  Rasmus Andersen, December 2000: Converted to new PCI API and general**  cleanup.****  Pete Popov, January 11,99: Fixed a couple of 2.1.x problems **  (virt_to_bus() not called), tested it under 2.2pre5 (as a module), and **  added a #define(s) to enable the use of the same file for both, the 2.0.x **  kernels as well as the 2.1.x.****  Ported to 2.1.x by Alan Cox 1998/12/9. ****  Sometime in mid 1998, written by Pete Popov and Brian Moyle.*****************************************************************************/#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/string.h>#include <linux/ptrace.h>#include <linux/errno.h>#include <linux/in.h>#include <linux/init.h>#include <linux/ioport.h>#include <linux/slab.h>#include <linux/interrupt.h>#include <linux/pci.h>#include <linux/timer.h>#include <asm/irq.h>		/* For NR_IRQS only. */#include <asm/bitops.h>#include <asm/uaccess.h>static char version[] __initdata =    "RedCreek Communications PCI linux driver version 2.20\n";#define RC_LINUX_MODULE#include "rclanmtl.h"#include "rcif.h"#define RUN_AT(x) (jiffies + (x))#define NEW_MULTICAST/* PCI/45 Configuration space values */#define RC_PCI45_VENDOR_ID  0x4916#define RC_PCI45_DEVICE_ID  0x1960#define MAX_ETHER_SIZE        1520#define MAX_NMBR_RCV_BUFFERS    96#define RC_POSTED_BUFFERS_LOW_MARK MAX_NMBR_RCV_BUFFERS-16#define BD_SIZE 3		/* Bucket Descriptor size */#define BD_LEN_OFFSET 2		/* Bucket Descriptor offset to length field *//* RedCreek LAN device Target ID */#define RC_LAN_TARGET_ID  0x10/* RedCreek's OSM default LAN receive Initiator */#define DEFAULT_RECV_INIT_CONTEXT  0xA17/* minimum msg buffer size needed by the card  * Note that the size of this buffer is hard code in the * ipsec card's firmware. Thus, the size MUST be a minimum * of 16K. Otherwise the card will end up using memory * that does not belong to it. */#define MSG_BUF_SIZE  16384static U32 DriverControlWord;static void rc_timer (unsigned long);static int RCinit (struct net_device *);static int RCopen (struct net_device *);static int RC_xmit_packet (struct sk_buff *, struct net_device *);static void RCinterrupt (int, void *, struct pt_regs *);static int RCclose (struct net_device *dev);static struct net_device_stats *RCget_stats (struct net_device *);static int RCioctl (struct net_device *, struct ifreq *, int);static int RCconfig (struct net_device *, struct ifmap *);static void RCxmit_callback (U32, U16, PU32, struct net_device *);static void RCrecv_callback (U32, U8, U32, PU32, struct net_device *);static void RCreset_callback (U32, U32, U32, struct net_device *);static void RCreboot_callback (U32, U32, U32, struct net_device *);static int RC_allocate_and_post_buffers (struct net_device *, int);static struct pci_device_id rcpci45_pci_table[] __devinitdata = {	{RC_PCI45_VENDOR_ID, RC_PCI45_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},	{}};MODULE_DEVICE_TABLE (pci, rcpci45_pci_table);MODULE_LICENSE("GPL");static void __devexitrcpci45_remove_one (struct pci_dev *pdev){	struct net_device *dev = pci_get_drvdata (pdev);	PDPA pDpa = dev->priv;	if (!dev) {		printk (KERN_ERR "%s: remove non-existent device\n",				dev->name);		return;	}	RCResetIOP (dev);	unregister_netdev (dev);	free_irq (dev->irq, dev);	iounmap ((void *) dev->base_addr);	pci_release_regions (pdev);	if (pDpa->msgbuf)		kfree (pDpa->msgbuf);	if (pDpa->pPab)		kfree (pDpa->pPab);	kfree (dev);	pci_set_drvdata (pdev, NULL);}static intrcpci45_init_one (struct pci_dev *pdev, const struct pci_device_id *ent){	unsigned long *vaddr;	PDPA pDpa;	int error;	static int card_idx = -1;	struct net_device *dev;	unsigned long pci_start, pci_len;	card_idx++;	/* 	 * Allocate and fill new device structure. 	 * We need enough for struct net_device plus DPA plus the LAN 	 * API private area, which requires a minimum of 16KB.  The top 	 * of the allocated area will be assigned to struct net_device; 	 * the next chunk will be assigned to DPA; and finally, the rest 	 * will be assigned to the the LAN API layer.	 */	dev = init_etherdev (NULL, sizeof (*pDpa));	if (!dev) {		printk (KERN_ERR			"(rcpci45 driver:) init_etherdev alloc failed\n");		error = -ENOMEM;		goto err_out;	}	error = pci_enable_device (pdev);	if (error) {		printk (KERN_ERR			"(rcpci45 driver:) %d: pci enable device error\n",			card_idx);		goto err_out;	}	error = -ENOMEM;	pci_start = pci_resource_start (pdev, 0);	pci_len = pci_resource_len (pdev, 0);	printk("pci_start %x pci_len %x\n", pci_start, pci_len);	pci_set_drvdata (pdev, dev);	pDpa = dev->priv;	pDpa->id = card_idx;	pDpa->pci_addr = pci_start;	if (!pci_start || !(pci_resource_flags (pdev, 0) & IORESOURCE_MEM)) {		printk (KERN_ERR			"(rcpci45 driver:) No PCI mem resources! Aborting\n");		error = -EBUSY;		goto err_out_free_dev;	}	/*	 * pDpa->msgbuf is where the card will dma the I2O 	 * messages. Thus, we need contiguous physical pages of	 * memory.	 */	pDpa->msgbuf = kmalloc (MSG_BUF_SIZE, GFP_DMA|GFP_ATOMIC|GFP_KERNEL);	if (!pDpa->msgbuf) {		printk (KERN_ERR "(rcpci45 driver:) \			Could not allocate %d byte memory for the \				private msgbuf!\n", MSG_BUF_SIZE);		goto err_out_free_dev;	}	/*	 * Save the starting address of the LAN API private area.  We'll	 * pass that to RCInitI2OMsgLayer().	 *	 */	pDpa->PLanApiPA = (void *) (((long) pDpa->msgbuf + 0xff) & ~0xff);	/* The adapter is accessible through memory-access read/write, not	 * I/O read/write.  Thus, we need to map it to some virtual address	 * area in order to access the registers as normal memory.	 */	error = pci_request_regions (pdev, dev->name);	if (error)		goto err_out_free_msgbuf;	vaddr = (ulong *) ioremap (pci_start, pci_len);	if (!vaddr) {		printk (KERN_ERR			"(rcpci45 driver:) \			Unable to remap address range from %lu to %lu\n",			pci_start, pci_start + pci_len);		goto err_out_free_region;	}	dev->base_addr = (unsigned long) vaddr;	dev->irq = pdev->irq;	dev->open = &RCopen;	dev->hard_start_xmit = &RC_xmit_packet;	dev->stop = &RCclose;	dev->get_stats = &RCget_stats;	dev->do_ioctl = &RCioctl;	dev->set_config = &RCconfig;	return 0;		/* success */err_out_free_region:	pci_release_regions (pdev);err_out_free_msgbuf:	kfree (pDpa->msgbuf);err_out_free_dev:	unregister_netdev (dev);	kfree (dev);err_out:	card_idx--;	return -ENODEV;}static struct pci_driver rcpci45_driver = {	name:		"rcpci45",	id_table:	rcpci45_pci_table,	probe:		rcpci45_init_one,	remove:		__devexit_p(rcpci45_remove_one),};static int __initrcpci_init_module (void){	int rc = pci_module_init (&rcpci45_driver);	if (!rc)		printk (KERN_ERR "%s", version);	return rc;}static intRCopen (struct net_device *dev){	int post_buffers = MAX_NMBR_RCV_BUFFERS;	PDPA pDpa = dev->priv;	int count = 0;	int requested = 0;	int error;	MOD_INC_USE_COUNT;	if (pDpa->nexus) {		/* This is not the first time RCopen is called.  Thus,		 * the interface was previously opened and later closed		 * by RCclose().  RCclose() does a Shutdown; to wake up		 * the adapter, a reset is mandatory before we can post		 * receive buffers.  However, if the adapter initiated 		 * a reboot while the interface was closed -- and interrupts		 * were turned off -- we need will need to reinitialize		 * the adapter, rather than simply waking it up.  		 */		printk (KERN_INFO "Waking up adapter...\n");		RCResetLANCard (dev, 0, 0, 0);	} else {		pDpa->nexus = 1;		/* 		 * RCInitI2OMsgLayer is done only once, unless the		 * adapter was sent a warm reboot		 */		error = RCInitI2OMsgLayer (dev, (PFNTXCALLBACK) RCxmit_callback,					   (PFNRXCALLBACK) RCrecv_callback,					   (PFNCALLBACK) RCreboot_callback);		if (error) {			printk (KERN_ERR "%s: Unable to init msg layer (%x)\n",					dev->name, error);			goto err_out;		}		if ((error = RCGetMAC (dev, NULL))) {			printk (KERN_ERR "%s: Unable to get adapter MAC\n",					dev->name);			goto err_out;		}	}	/* Request a shared interrupt line. */	error = request_irq (dev->irq, RCinterrupt, SA_SHIRQ, dev->name, dev);	if (error) {		printk (KERN_ERR "%s: unable to get IRQ %d\n", 				dev->name, dev->irq);		goto err_out;	}	DriverControlWord |= WARM_REBOOT_CAPABLE;	RCReportDriverCapability (dev, DriverControlWord);	printk (KERN_INFO "%s: RedCreek Communications IPSEC VPN adapter\n",		dev->name);	RCEnableI2OInterrupts (dev);	while (post_buffers) {		if (post_buffers > MAX_NMBR_POST_BUFFERS_PER_MSG)			requested = MAX_NMBR_POST_BUFFERS_PER_MSG;		else			requested = post_buffers;		count = RC_allocate_and_post_buffers (dev, requested);		if (count < requested) {			/*			 * Check to see if we were able to post 			 * any buffers at all.			 */			if (post_buffers == MAX_NMBR_RCV_BUFFERS) {				printk (KERN_ERR "%s: \					unable to allocate any buffers\n", 						dev->name);				goto err_out_free_irq;			}			printk (KERN_WARNING "%s: \			unable to allocate all requested buffers\n", dev->name);			break;	/* we'll try to post more buffers later */		} else			post_buffers -= count;	}	pDpa->numOutRcvBuffers = MAX_NMBR_RCV_BUFFERS - post_buffers;	pDpa->shutdown = 0;	/* just in case */	netif_start_queue (dev);	return 0;err_out_free_irq:	free_irq (dev->irq, dev);err_out:	MOD_DEC_USE_COUNT;	return error;}static intRC_xmit_packet (struct sk_buff *skb, struct net_device *dev){	PDPA pDpa = dev->priv;	singleTCB tcb;	psingleTCB ptcb = &tcb;	RC_RETURN status = 0;	netif_stop_queue (dev);	if (pDpa->shutdown || pDpa->reboot) {		printk ("RC_xmit_packet: tbusy!\n");		return 1;	}	/*	 * The user is free to reuse the TCB after RCI2OSendPacket() 	 * returns, since the function copies the necessary info into its 	 * own private space.  Thus, our TCB can be a local structure.  	 * The skb, on the other hand, will be freed up in our interrupt 	 * handler.	 */	ptcb->bcount = 1;	/* 	 * we'll get the context when the adapter interrupts us to tell us that	 * the transmission is done. At that time, we can free skb.	 */	ptcb->b.context = (U32) skb;	ptcb->b.scount = 1;	ptcb->b.size = skb->len;	ptcb->b.addr = virt_to_bus ((void *) skb->data);	if ((status = RCI2OSendPacket (dev, (U32) NULL, (PRCTCB) ptcb))	    != RC_RTN_NO_ERROR) {		printk ("%s: send error 0x%x\n", dev->name, (uint) status);		return 1;	} else {		dev->trans_start = jiffies;		netif_wake_queue (dev);	}	/*	 * That's it!	 */	return 0;}/* * RCxmit_callback() * * The transmit callback routine. It's called by RCProcI2OMsgQ() * because the adapter is done with one or more transmit buffers and * it's returning them to us, or we asked the adapter to return the * outstanding transmit buffers by calling RCResetLANCard() with  * RC_RESOURCE_RETURN_PEND_TX_BUFFERS flag.  * All we need to do is free the buffers. */static voidRCxmit_callback (U32 Status,		 U16 PcktCount, PU32 BufferContext, struct net_device *dev){	struct sk_buff *skb;	PDPA pDpa = dev->priv;	if (!pDpa) {		printk (KERN_ERR "%s: Fatal Error in xmit callback, !pDpa\n",				dev->name);		return;	}	if (Status != I2O_REPLY_STATUS_SUCCESS)		printk (KERN_INFO "%s: xmit_callback: Status = 0x%x\n", 				dev->name, (uint) Status);	if (pDpa->shutdown || pDpa->reboot)		printk (KERN_INFO "%s: xmit callback: shutdown||reboot\n",				dev->name);	while (PcktCount--) {		skb = (struct sk_buff *) (BufferContext[0]);		BufferContext++;		dev_kfree_skb_irq (skb);	}	netif_wake_queue (dev);}static voidRCreset_callback (U32 Status, U32 p1, U32 p2, struct net_device *dev){	PDPA pDpa = dev->priv;	printk ("RCreset_callback Status 0x%x\n", (uint) Status);	/*	 * Check to see why we were called.	 */	if (pDpa->shutdown) {		printk (KERN_INFO "%s: shutting down interface\n",				dev->name);		pDpa->shutdown = 0;		pDpa->reboot = 0;	} else if (pDpa->reboot) {		printk (KERN_INFO "%s: reboot, shutdown adapter\n",				dev->name);		/*		 * We don't set any of the flags in RCShutdownLANCard()		 * and we don't pass a callback routine to it.		 * The adapter will have already initiated the reboot by		 * the time the function returns.		 */		RCDisableI2OInterrupts (dev);		RCShutdownLANCard (dev, 0, 0, 0);		printk (KERN_INFO "%s: scheduling timer...\n", dev->name);		init_timer (&pDpa->timer);		pDpa->timer.expires = RUN_AT ((40 * HZ) / 10);	/* 4 sec. */		pDpa->timer.data = (unsigned long) dev;		pDpa->timer.function = &rc_timer;	/* timer handler */		add_timer (&pDpa->timer);	}}static voidRCreboot_callback (U32 Status, U32 p1, U32 p2, struct net_device *dev){	PDPA pDpa = dev->priv;	printk (KERN_INFO "%s: reboot: rcv buffers outstanding = %d\n",		 dev->name, (uint) pDpa->numOutRcvBuffers);	if (pDpa->shutdown) {		printk (KERN_INFO "%s: skip reboot, shutdown initiated\n",				dev->name);		return;	}	pDpa->reboot = 1;	/*	 * OK, we reset the adapter and ask it to return all	 * outstanding transmit buffers as well as the posted	 * receive buffers.  When the adapter is done returning	 * those buffers, it will call our RCreset_callback() 	 * routine.  In that routine, we'll call RCShutdownLANCard()	 * to tell the adapter that it's OK to start the reboot and	 * schedule a timer callback routine to execute 3 seconds 	 * later; this routine will reinitialize the adapter at that time.	 */	RCResetLANCard (dev, RC_RESOURCE_RETURN_POSTED_RX_BUCKETS |			RC_RESOURCE_RETURN_PEND_TX_BUFFERS, 0,			(PFNCALLBACK) RCreset_callback);}int

⌨️ 快捷键说明

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