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

📄 3c527.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 3 页
字号:
			/* Try to save time by avoiding a copy on big frames */			if ((length > RX_COPYBREAK) 			    && ((newskb=dev_alloc_skb(1532)) != NULL)) 			{ 				skb=lp->rx_ring[rx_ring_tail].skb;				skb_put(skb, length);								skb_reserve(newskb,18); 				lp->rx_ring[rx_ring_tail].skb=newskb;  				p->data=virt_to_bus(newskb->data);  			} 			else 			{				skb=dev_alloc_skb(length+2);  				if(skb==NULL) {					lp->net_stats.rx_dropped++; 					goto dropped; 				}				skb_reserve(skb,2);				memcpy(skb_put(skb, length),				       lp->rx_ring[rx_ring_tail].skb->data, length);			}						skb->protocol=eth_type_trans(skb,dev); 			skb->dev=dev; 			dev->last_rx = jiffies; 			lp->net_stats.rx_packets++;  			lp->net_stats.rx_bytes += length; 			netif_rx(skb);		}	dropped:		p->length = 1532; 		p->status = 0;				rx_ring_tail=next_rx(rx_ring_tail); 	}        while(x++<48);  	/* If there was actually a frame to be processed, place the EOL bit */ 	/* at the descriptor prior to the one to be filled next */ 	if (rx_ring_tail != rx_old_tail) 	{ 		lp->rx_ring[prev_rx(rx_ring_tail)].p->control |=  CONTROL_EOL; 		lp->rx_ring[prev_rx(rx_old_tail)].p->control  &= ~CONTROL_EOL; 		lp->rx_ring_tail=rx_ring_tail; 	}}/** *	mc32_tx_ring	-	process completed transmits *	@dev: 3c527 that needs its transmit ring processing * * *	This operates in a similar fashion to mc32_rx_ring. We iterate *	over the transmit ring. For each descriptor which has been *	processed by the card, we free its associated buffer and note *	any errors. This continues until the transmit ring is emptied *	or we reach a descriptor that hasn't yet been processed by the *	card. *  */static void mc32_tx_ring(struct net_device *dev) {	struct mc32_local *lp=(struct mc32_local *)dev->priv;	volatile struct skb_header *np;	/* NB: lp->tx_count=TX_RING_LEN-1 so that tx_ring_head cannot "lap" tail here */	while (lp->tx_ring_tail != lp->tx_ring_head)  	{   		u16 t; 		t=next_tx(lp->tx_ring_tail); 		np=lp->tx_ring[t].p; 		if(!(np->status & (1<<7))) 		{			/* Not COMPLETED */ 			break; 		} 		lp->net_stats.tx_packets++;		if(!(np->status & (1<<6))) /* Not COMPLETED_OK */		{			lp->net_stats.tx_errors++;   			switch(np->status&0x0F)			{				case 1:					lp->net_stats.tx_aborted_errors++;					break; /* Max collisions */ 				case 2:					lp->net_stats.tx_fifo_errors++;					break;				case 3:					lp->net_stats.tx_carrier_errors++;					break;				case 4:					lp->net_stats.tx_window_errors++;					break;  /* CTS Lost */ 				case 5:					lp->net_stats.tx_aborted_errors++;					break; /* Transmit timeout */ 			}		}		/* Packets are sent in order - this is		    basically a FIFO queue of buffers matching		    the card ring */		lp->net_stats.tx_bytes+=lp->tx_ring[t].skb->len;		dev_kfree_skb_irq(lp->tx_ring[t].skb);		lp->tx_ring[t].skb=NULL;		atomic_inc(&lp->tx_count);		netif_wake_queue(dev);		lp->tx_ring_tail=t; 	}} /** *	mc32_interrupt		-	handle an interrupt from a 3c527 *	@irq: Interrupt number *	@dev_id: 3c527 that requires servicing *	@regs: Registers (unused) * * *	An interrupt is raised whenever the 3c527 writes to the command *	register. This register contains the message it wishes to send us *	packed into a single byte field. We keep reading status entries *	until we have processed all the control items, but simply count *	transmit and receive reports. When all reports are in we empty the *	transceiver rings as appropriate. This saves the overhead of *	multiple command requests. * *	Because MCA is level-triggered, we shouldn't miss indications. *	Therefore, we needn't ask the card to suspend interrupts within *	this handler. The card receives an implicit acknowledgment of the *	current interrupt when we read the command register. * */static void mc32_interrupt(int irq, void *dev_id, struct pt_regs * regs){	struct net_device *dev = dev_id;	struct mc32_local *lp;	int ioaddr, status, boguscount = 0;	int rx_event = 0;	int tx_event = 0; 		if (dev == NULL) {		printk(KERN_WARNING "%s: irq %d for unknown device.\n", cardname, irq);		return;	} 	ioaddr = dev->base_addr;	lp = (struct mc32_local *)dev->priv;	/* See whats cooking */	while((inb(ioaddr+HOST_STATUS)&HOST_STATUS_CWR) && boguscount++<2000)	{		status=inb(ioaddr+HOST_CMD);#ifdef DEBUG_IRQ				printk("Status TX%d RX%d EX%d OV%d BC%d\n",			(status&7), (status>>3)&7, (status>>6)&1,			(status>>7)&1, boguscount);#endif					switch(status&7)		{			case 0:				break;			case 6: /* TX fail */			case 2:	/* TX ok */				tx_event = 1; 				break;			case 3: /* Halt */			case 4: /* Abort */				lp->xceiver_state |= TX_HALTED; 				wake_up(&lp->event);				break;			default:				printk("%s: strange tx ack %d\n", dev->name, status&7);		}		status>>=3;		switch(status&7)		{			case 0:				break;			case 2:	/* RX */				rx_event=1; 				break;			case 3: /* Halt */			case 4: /* Abort */				lp->xceiver_state |= RX_HALTED;				wake_up(&lp->event);				break;			case 6:				/* Out of RX buffers stat */				/* Must restart rx */				lp->net_stats.rx_dropped++;				mc32_rx_ring(dev); 				mc32_start_transceiver(dev); 				break;			default:				printk("%s: strange rx ack %d\n", 					dev->name, status&7);					}		status>>=3;		if(status&1)		{			/* 0=no 1=yes 2=replied, get cmd, 3 = wait reply & dump it */						if(lp->exec_pending!=3) {				lp->exec_pending=2;				wake_up(&lp->event);			}			else 			{							  	lp->exec_pending=0;				/* A new multicast set may have been				   blocked while the old one was				   running. If so, do it now. */				   				if (lp->mc_reload_wait) 					mc32_reset_multicast_list(dev);				else 					wake_up(&lp->event);			       			}		}		if(status&2)		{			/*			 *	We get interrupted once per			 *	counter that is about to overflow. 			 */			mc32_update_stats(dev);					}	}	/*	 *	Process the transmit and receive rings          */	if(tx_event) 		mc32_tx_ring(dev);	 	if(rx_event) 		mc32_rx_ring(dev);	return;}/** *	mc32_close	-	user configuring the 3c527 down *	@dev: 3c527 card to shut down * *	The 3c527 is a bus mastering device. We must be careful how we *	shut it down. It may also be running shared interrupt so we have *	to be sure to silence it properly * *	We indicate that the card is closing to the rest of the *	driver.  Otherwise, it is possible that the card may run out *	of receive buffers and restart the transceiver while we're *	trying to close it. *  *	We abort any receive and transmits going on and then wait until *	any pending exec commands have completed in other code threads. *	In theory we can't get here while that is true, in practice I am *	paranoid * *	We turn off the interrupt enable for the board to be sure it can't *	intefere with other devices. */static int mc32_close(struct net_device *dev){	struct mc32_local *lp = (struct mc32_local *)dev->priv;	int ioaddr = dev->base_addr;	u8 regs;	u16 one=1;		lp->desired_state = HALTED;	netif_stop_queue(dev);	/*	 *	Send the indications on command (handy debug check)	 */	mc32_command(dev, 4, &one, 2);	/* Shut down the transceiver */	mc32_halt_transceiver(dev); 		/* Catch any waiting commands */		while(lp->exec_pending==1)		sleep_on(&lp->event);	       	/* Ok the card is now stopping */			regs=inb(ioaddr+HOST_CTRL);	regs&=~HOST_CTRL_INTE;	outb(regs, ioaddr+HOST_CTRL);	mc32_flush_rx_ring(dev);	mc32_flush_tx_ring(dev);			mc32_update_stats(dev); 	return 0;}/** *	mc32_get_stats		-	hand back stats to network layer *	@dev: The 3c527 card to handle * *	We've collected all the stats we can in software already. Now *	it's time to update those kept on-card and return the lot.  *  */static struct net_device_stats *mc32_get_stats(struct net_device *dev){	struct mc32_local *lp;		mc32_update_stats(dev); 	lp = (struct mc32_local *)dev->priv;	return &lp->net_stats;}/** *	do_mc32_set_multicast_list	-	attempt to update multicasts *	@dev: 3c527 device to load the list on *	@retry: indicates this is not the first call.  * * * 	Actually set or clear the multicast filter for this adaptor. The *	locking issues are handled by this routine. We have to track *	state as it may take multiple calls to get the command sequence *	completed. We just keep trying to schedule the loads until we *	manage to process them all. *  *	num_addrs == -1	Promiscuous mode, receive all packets *  *	num_addrs == 0	Normal mode, clear multicast list *  *	num_addrs > 0	Multicast mode, receive normal and MC packets,  *			and do best-effort filtering.  * *	See mc32_update_stats() regards setting the SAV BP bit.  * */static void do_mc32_set_multicast_list(struct net_device *dev, int retry){	struct mc32_local *lp = (struct mc32_local *)dev->priv;	u16 filt = (1<<2); /* Save Bad Packets, for stats purposes */ 	if (dev->flags&IFF_PROMISC)		/* Enable promiscuous mode */		filt |= 1;	else if((dev->flags&IFF_ALLMULTI) || dev->mc_count > 10)	{		dev->flags|=IFF_PROMISC;		filt |= 1;	}	else if(dev->mc_count)	{		unsigned char block[62];		unsigned char *bp;		struct dev_mc_list *dmc=dev->mc_list;				int i;	       		if(retry==0)			lp->mc_list_valid = 0;		if(!lp->mc_list_valid)		{			block[1]=0;			block[0]=dev->mc_count;			bp=block+2;					for(i=0;i<dev->mc_count;i++)			{				memcpy(bp, dmc->dmi_addr, 6);				bp+=6;				dmc=dmc->next;			}			if(mc32_command_nowait(dev, 2, block, 2+6*dev->mc_count)==-1)			{				lp->mc_reload_wait = 1;				return;			}			lp->mc_list_valid=1;		}	}		if(mc32_command_nowait(dev, 0, &filt, 2)==-1) 	{		lp->mc_reload_wait = 1;	} 	else { 		lp->mc_reload_wait = 0;	}}/** *	mc32_set_multicast_list	-	queue multicast list update *	@dev: The 3c527 to use * *	Commence loading the multicast list. This is called when the kernel *	changes the lists. It will override any pending list we are trying to *	load. */static void mc32_set_multicast_list(struct net_device *dev){	do_mc32_set_multicast_list(dev,0);}/** *	mc32_reset_multicast_list	-	reset multicast list *	@dev: The 3c527 to use * *	Attempt the next step in loading the multicast lists. If this attempt *	fails to complete then it will be scheduled and this function called *	again later from elsewhere. */static void mc32_reset_multicast_list(struct net_device *dev){	do_mc32_set_multicast_list(dev,1);}/** * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls * @dev: network interface on which out-of-band action is to be performed * @useraddr: userspace address to which data is to be read and returned * * Process the various commands of the SIOCETHTOOL interface. */static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr){	u32 ethcmd;	/* dev_ioctl() in ../../net/core/dev.c has already checked	   capable(CAP_NET_ADMIN), so don't bother with that here.  */	if (get_user(ethcmd, (u32 *)useraddr))		return -EFAULT;	switch (ethcmd) {	case ETHTOOL_GDRVINFO: {		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };		strcpy (info.driver, DRV_NAME);		strcpy (info.version, DRV_VERSION);		sprintf(info.bus_info, "MCA 0x%lx", dev->base_addr);		if (copy_to_user (useraddr, &info, sizeof (info)))			return -EFAULT;		return 0;	}	/* get message-level */	case ETHTOOL_GMSGLVL: {		struct ethtool_value edata = {ETHTOOL_GMSGLVL};		edata.data = mc32_debug;		if (copy_to_user(useraddr, &edata, sizeof(edata)))			return -EFAULT;		return 0;	}	/* set message-level */	case ETHTOOL_SMSGLVL: {		struct ethtool_value edata;		if (copy_from_user(&edata, useraddr, sizeof(edata)))			return -EFAULT;		mc32_debug = edata.data;		return 0;	}	default:		break;	}	return -EOPNOTSUPP;}/** * netdev_ioctl: Handle network interface ioctls * @dev: network interface on which out-of-band action is to be performed * @rq: user request data * @cmd: command issued by user * * Process the various out-of-band ioctls passed to this driver. */static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd){	int rc = 0;	switch (cmd) {	case SIOCETHTOOL:		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);		break;	default:		rc = -EOPNOTSUPP;		break;	}	return rc;} #ifdef MODULEstatic struct net_device this_device;/** *	init_module		-	entry point * *	Probe and locate a 3c527 card. This really should probe and locate *	all the 3c527 cards in the machine not just one of them. Yes you can *	insmod multiple modules for now but it's a hack. */int init_module(void){	int result;		this_device.init = mc32_probe;	if ((result = register_netdev(&this_device)) != 0)		return result;	return 0;}/** *	cleanup_module	-	free resources for an unload * *	Unloading time. We release the MCA bus resources and the interrupt *	at which point everything is ready to unload. The card must be stopped *	at this point or we would not have been called. When we unload we *	leave the card stopped but not totally shut down. When the card is *	initialized it must be rebooted or the rings reloaded before any *	transmit operations are allowed to start scribbling into memory. */void cleanup_module(void){	int slot;		/* No need to check MOD_IN_USE, as sys_delete_module() checks. */	unregister_netdev(&this_device);	/*	 * If we don't do this, we can't re-insmod it later.	 */	 	if (this_device.priv)	{		struct mc32_local *lp=this_device.priv;		slot = lp->slot;		mca_mark_as_unused(slot);		mca_set_adapter_name(slot, NULL);		kfree(this_device.priv);	}	free_irq(this_device.irq, &this_device);	release_region(this_device.base_addr, MC32_IO_EXTENT);}#endif /* MODULE */

⌨️ 快捷键说明

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