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

📄 rcpci45.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 2 页
字号:
broadcast_packet (unsigned char *address){	int i;	for (i = 0; i < 6; i++)		if (address[i] != 0xff)			return 0;	return 1;}/* * RCrecv_callback() *  * The receive packet callback routine.  This is called by * RCProcI2OMsgQ() after the adapter posts buffers which have been * filled (one ethernet packet per buffer). */static voidRCrecv_callback (U32 Status,		 U8 PktCount,		 U32 BucketsRemain,		 PU32 PacketDescBlock, struct net_device *dev){	U32 len, count;	PDPA pDpa = dev->priv;	struct sk_buff *skb;	singleTCB tcb;	psingleTCB ptcb = &tcb;	ptcb->bcount = 1;	if ((pDpa->shutdown || pDpa->reboot) && !Status)		printk (KERN_INFO "%s: shutdown||reboot && !Status (%d)\n",				dev->name, PktCount);	if ((Status != I2O_REPLY_STATUS_SUCCESS) || pDpa->shutdown) {		/*		 * Free whatever buffers the adapter returned, but don't		 * pass them to the kernel.		 */		if (!pDpa->shutdown && !pDpa->reboot)			printk (KERN_INFO "%s: recv error status = 0x%x\n",					dev->name, (uint) Status);		else			printk (KERN_DEBUG "%s: Returning %d buffs stat 0x%x\n",					dev->name, PktCount, (uint) Status);		/*		 * TO DO: check the nature of the failure and put the 		 * adapter in failed mode if it's a hard failure.  		 * Send a reset to the adapter and free all outstanding memory.		 */		if (PacketDescBlock) {			while (PktCount--) {				skb = (struct sk_buff *) PacketDescBlock[0];				dev_kfree_skb (skb);				pDpa->numOutRcvBuffers--;				/* point to next context field */				PacketDescBlock += BD_SIZE;			}		}		return;	} else {		while (PktCount--) {			skb = (struct sk_buff *) PacketDescBlock[0];			len = PacketDescBlock[2];			skb->dev = dev;			skb_put (skb, len);	/* adjust length and tail */			skb->protocol = eth_type_trans (skb, dev);			netif_rx (skb);	/* send the packet to the kernel */			dev->last_rx = jiffies;			pDpa->numOutRcvBuffers--;				/* point to next context field */			PacketDescBlock += BD_SIZE;		}	}	/*	 * Replenish the posted receive buffers. 	 * DO NOT replenish buffers if the driver has already	 * initiated a reboot or shutdown!	 */	if (!pDpa->shutdown && !pDpa->reboot) {		count = RC_allocate_and_post_buffers (dev,						      MAX_NMBR_RCV_BUFFERS -						      pDpa->numOutRcvBuffers);		pDpa->numOutRcvBuffers += count;	}}/* * RCinterrupt() *  * Interrupt handler.  * This routine sets up a couple of pointers and calls * RCProcI2OMsgQ(), which in turn process the message and * calls one of our callback functions. */static voidRCinterrupt (int irq, void *dev_id, struct pt_regs *regs){	PDPA pDpa;	struct net_device *dev = dev_id;	pDpa = dev->priv;	if (pDpa->shutdown)		printk (KERN_DEBUG "%s: shutdown, service irq\n",				dev->name);	RCProcI2OMsgQ (dev);}#define REBOOT_REINIT_RETRY_LIMIT 4static voidrc_timer (unsigned long data){	struct net_device *dev = (struct net_device *) data;	PDPA pDpa = dev->priv;	int init_status;	static int retry;	int post_buffers = MAX_NMBR_RCV_BUFFERS;	int count = 0;	int requested = 0;	if (pDpa->reboot) {		init_status =		    RCInitI2OMsgLayer (dev, (PFNTXCALLBACK) RCxmit_callback,				       (PFNRXCALLBACK) RCrecv_callback,				       (PFNCALLBACK) RCreboot_callback);		switch (init_status) {		case RC_RTN_NO_ERROR:			pDpa->reboot = 0;			pDpa->shutdown = 0;	/* just in case */			RCReportDriverCapability (dev, DriverControlWord);			RCEnableI2OInterrupts (dev);			if (!(dev->flags & IFF_UP)) {				retry = 0;				return;			}			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);				post_buffers -= count;				if (count < requested)					break;			}			pDpa->numOutRcvBuffers =			    MAX_NMBR_RCV_BUFFERS - post_buffers;			printk ("Initialization done.\n");			netif_wake_queue (dev);			retry = 0;			return;		case RC_RTN_FREE_Q_EMPTY:			retry++;			printk (KERN_WARNING "%s inbound free q empty\n",					dev->name);			break;		default:			retry++;			printk (KERN_WARNING "%s bad stat after reboot: %d\n",					dev->name, init_status);			break;		}		if (retry > REBOOT_REINIT_RETRY_LIMIT) {			printk (KERN_WARNING "%s unable to reinitialize adapter after reboot\n", dev->name);			printk (KERN_WARNING "%s decrementing driver and closing interface\n", dev->name);			RCDisableI2OInterrupts (dev);			dev->flags &= ~IFF_UP;			MOD_DEC_USE_COUNT;		} else {			printk (KERN_INFO "%s: rescheduling timer...\n",					dev->name);			init_timer (&pDpa->timer);			pDpa->timer.expires = RUN_AT ((40 * HZ) / 10);			pDpa->timer.data = (unsigned long) dev;			pDpa->timer.function = &rc_timer;			add_timer (&pDpa->timer);		}	} else		printk (KERN_WARNING "%s: unexpected timer irq\n", dev->name);}static intRCclose (struct net_device *dev){	PDPA pDpa = dev->priv;	printk("RCclose\n");	netif_stop_queue (dev);	if (pDpa->reboot) {		printk (KERN_INFO "%s skipping reset -- adapter already in reboot mode\n", dev->name);		dev->flags &= ~IFF_UP;		pDpa->shutdown = 1;		MOD_DEC_USE_COUNT;		return 0;	}	pDpa->shutdown = 1;	/*	 * We can't allow the driver to be unloaded until the adapter returns	 * all posted receive buffers.  It doesn't hurt to tell the adapter	 * to return all posted receive buffers and outstanding xmit buffers,	 * even if there are none.	 */	RCShutdownLANCard (dev, RC_RESOURCE_RETURN_POSTED_RX_BUCKETS |			   RC_RESOURCE_RETURN_PEND_TX_BUFFERS, 0,			   (PFNCALLBACK) RCreset_callback);	dev->flags &= ~IFF_UP;	MOD_DEC_USE_COUNT;	return 0;}static struct net_device_stats *RCget_stats (struct net_device *dev){	RCLINKSTATS RCstats;	PDPA pDpa = dev->priv;	if (!pDpa) {		return 0;	} else if (!(dev->flags & IFF_UP)) {		return 0;	}	memset (&RCstats, 0, sizeof (RCLINKSTATS));	if ((RCGetLinkStatistics (dev, &RCstats, (void *) 0)) ==	    RC_RTN_NO_ERROR) {		/* total packets received    */		pDpa->stats.rx_packets = RCstats.Rcv_good		/* total packets transmitted    */;		pDpa->stats.tx_packets = RCstats.TX_good;		pDpa->stats.rx_errors = RCstats.Rcv_CRCerr + 			RCstats.Rcv_alignerr + RCstats.Rcv_reserr + 			RCstats.Rcv_orun + RCstats.Rcv_cdt + RCstats.Rcv_runt;		pDpa->stats.tx_errors = RCstats.TX_urun + RCstats.TX_crs + 			RCstats.TX_def + RCstats.TX_totcol;		/*		 * This needs improvement.		 */		pDpa->stats.rx_dropped = 0; /* no space in linux buffers   */		pDpa->stats.tx_dropped = 0; /* no space available in linux */		pDpa->stats.multicast = 0;  /* multicast packets received  */		pDpa->stats.collisions = RCstats.TX_totcol;		/* detailed rx_errors: */		pDpa->stats.rx_length_errors = 0;		pDpa->stats.rx_over_errors = RCstats.Rcv_orun;		pDpa->stats.rx_crc_errors = RCstats.Rcv_CRCerr;		pDpa->stats.rx_frame_errors = 0;		pDpa->stats.rx_fifo_errors = 0;			pDpa->stats.rx_missed_errors = 0;		/* detailed tx_errors */		pDpa->stats.tx_aborted_errors = 0;		pDpa->stats.tx_carrier_errors = 0;		pDpa->stats.tx_fifo_errors = 0;		pDpa->stats.tx_heartbeat_errors = 0;		pDpa->stats.tx_window_errors = 0;		return ((struct net_device_stats *) &(pDpa->stats));	}	return 0;}static intRCioctl (struct net_device *dev, struct ifreq *rq, int cmd){	RCuser_struct RCuser;	PDPA pDpa = dev->priv;	if (!capable (CAP_NET_ADMIN))		return -EPERM;	switch (cmd) {	case RCU_PROTOCOL_REV:		/*		 * Assign user protocol revision, to tell user-level		 * controller program whether or not it's in sync.		 */		rq->ifr_ifru.ifru_data = (caddr_t) USER_PROTOCOL_REV;		break;	case RCU_COMMAND:		{			if (copy_from_user			    (&RCuser, rq->ifr_data, sizeof (RCuser)))				return -EFAULT;			dprintk ("RCioctl: RCuser_cmd = 0x%x\n", RCuser.cmd);			switch (RCuser.cmd) {			case RCUC_GETFWVER:				RCUD_GETFWVER = &RCuser.RCUS_GETFWVER;				RCGetFirmwareVer (dev,						  (PU8) & RCUD_GETFWVER->						  FirmString, NULL);				break;			case RCUC_GETINFO:				RCUD_GETINFO = &RCuser.RCUS_GETINFO;				RCUD_GETINFO->mem_start = dev->base_addr;				RCUD_GETINFO->mem_end =				    dev->base_addr + pDpa->pci_addr_len;				RCUD_GETINFO->base_addr = pDpa->pci_addr;				RCUD_GETINFO->irq = dev->irq;				break;			case RCUC_GETIPANDMASK:				RCUD_GETIPANDMASK = &RCuser.RCUS_GETIPANDMASK;				RCGetRavlinIPandMask (dev,						      (PU32) &						      RCUD_GETIPANDMASK->IpAddr,						      (PU32) &						      RCUD_GETIPANDMASK->						      NetMask, NULL);				break;			case RCUC_GETLINKSTATISTICS:				RCUD_GETLINKSTATISTICS =				    &RCuser.RCUS_GETLINKSTATISTICS;				RCGetLinkStatistics (dev,						     (P_RCLINKSTATS) &						     RCUD_GETLINKSTATISTICS->						     StatsReturn, NULL);				break;			case RCUC_GETLINKSTATUS:				RCUD_GETLINKSTATUS = &RCuser.RCUS_GETLINKSTATUS;				RCGetLinkStatus (dev,						 (PU32) & RCUD_GETLINKSTATUS->						 ReturnStatus, NULL);				break;			case RCUC_GETMAC:				RCUD_GETMAC = &RCuser.RCUS_GETMAC;				RCGetMAC (dev, NULL);				memcpy(RCUD_GETMAC, dev->dev_addr, 8);				break;			case RCUC_GETPROM:				RCUD_GETPROM = &RCuser.RCUS_GETPROM;				RCGetPromiscuousMode (dev,						      (PU32) & RCUD_GETPROM->						      PromMode, NULL);				break;			case RCUC_GETBROADCAST:				RCUD_GETBROADCAST = &RCuser.RCUS_GETBROADCAST;				RCGetBroadcastMode (dev,						    (PU32) & RCUD_GETBROADCAST->						    BroadcastMode, NULL);				break;			case RCUC_GETSPEED:				if (!(dev->flags & IFF_UP)) {					return -ENODATA;				}				RCUD_GETSPEED = &RCuser.RCUS_GETSPEED;				RCGetLinkSpeed (dev,						(PU32) & RCUD_GETSPEED->						LinkSpeedCode, NULL);				break;			case RCUC_SETIPANDMASK:				RCUD_SETIPANDMASK = &RCuser.RCUS_SETIPANDMASK;				RCSetRavlinIPandMask (dev,						      (U32) RCUD_SETIPANDMASK->						      IpAddr,						      (U32) RCUD_SETIPANDMASK->						      NetMask);				break;			case RCUC_SETMAC:				RCSetMAC (dev, (PU8) & RCUD_SETMAC->mac);				break;			case RCUC_SETSPEED:				RCUD_SETSPEED = &RCuser.RCUS_SETSPEED;				RCSetLinkSpeed (dev,						(U16) RCUD_SETSPEED->						LinkSpeedCode);				break;			case RCUC_SETPROM:				RCUD_SETPROM = &RCuser.RCUS_SETPROM;				RCSetPromiscuousMode (dev,						      (U16) RCUD_SETPROM->						      PromMode);				break;			case RCUC_SETBROADCAST:				RCUD_SETBROADCAST = &RCuser.RCUS_SETBROADCAST;				RCSetBroadcastMode (dev,						    (U16) RCUD_SETBROADCAST->						    BroadcastMode);				break;			default:				RCUD_DEFAULT = &RCuser.RCUS_DEFAULT;				RCUD_DEFAULT->rc = 0x11223344;				break;			}			if (copy_to_user (rq->ifr_data, &RCuser, 						sizeof (RCuser)))				return -EFAULT;			break;		}		/* RCU_COMMAND */	default:		rq->ifr_ifru.ifru_data = (caddr_t) 0x12345678;		return -EINVAL;	}	return 0;}static intRCconfig (struct net_device *dev, struct ifmap *map){	/*	 * To be completed ...	 */	return 0;	if (dev->flags & IFF_UP)	/* can't act on a running interface */		return -EBUSY;	/* Don't allow changing the I/O address */	if (map->base_addr != dev->base_addr) {		printk (KERN_WARNING "%s Change I/O address not implemented\n",				dev->name);		return -EOPNOTSUPP;	}	return 0;}static void __exitrcpci_cleanup_module (void){	pci_unregister_driver (&rcpci45_driver);}module_init (rcpci_init_module);module_exit (rcpci_cleanup_module);static intRC_allocate_and_post_buffers (struct net_device *dev, int numBuffers){	int i;	PU32 p;	psingleB pB;	struct sk_buff *skb;	RC_RETURN status;	U32 res;	if (!numBuffers)		return 0;	else if (numBuffers > MAX_NMBR_POST_BUFFERS_PER_MSG) {		printk (KERN_ERR "%s: Too many buffers requested!\n",				dev->name);		numBuffers = 32;	}	p = (PU32) kmalloc (sizeof (U32) + numBuffers * sizeof (singleB),			    GFP_DMA|GFP_ATOMIC|GFP_KERNEL);	if (!p) {		printk (KERN_WARNING "%s unable to allocate TCB\n",				dev->name);		return 0;	}	p[0] = 0;		/* Buffer Count */	pB = (psingleB) ((U32) p + sizeof (U32));/* point to the first buffer */	for (i = 0; i < numBuffers; i++) {		skb = dev_alloc_skb (MAX_ETHER_SIZE + 2);		if (!skb) {			printk (KERN_WARNING 					"%s: unable to allocate enough skbs!\n",					dev->name);			if (*p != 0) {	/* did we allocate any buffers */				break;			} else {				kfree (p);	/* Free the TCB */				return 0;			}		}		skb_reserve (skb, 2);	/* Align IP on 16 byte boundaries */		pB->context = (U32) skb;		pB->scount = 1;	/* segment count */		pB->size = MAX_ETHER_SIZE;		pB->addr = virt_to_bus ((void *) skb->data);		p[0]++;		pB++;	}	if ((status = RCPostRecvBuffers (dev, (PRCTCB) p)) != RC_RTN_NO_ERROR) {		printk (KERN_WARNING "%s: Post buffer failed, error 0x%x\n",				dev->name, status);		/* point to the first buffer */		pB = (psingleB) ((U32) p + sizeof (U32));		while (p[0]) {			skb = (struct sk_buff *) pB->context;			dev_kfree_skb (skb);			p[0]--;			pB++;		}	}	res = p[0];	kfree (p);	return (res);		/* return the number of posted buffers */}

⌨️ 快捷键说明

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