3c527.c

来自「linux 内核源代码」· C语言 代码 · 共 1,668 行 · 第 1/3 页

C
1,668
字号
	lp->net_stats.collisions+=st->dataC[11];	st->dataC[11]=0;}/** *	mc32_rx_ring	-	process the receive ring *	@dev: 3c527 that needs its receive ring processing * * *	We have received one or more indications from the card that a *	receive has completed. The buffer ring thus contains dirty *	entries. We walk the ring by iterating over the circular rx_ring *	array, starting at the next dirty buffer (which happens to be the *	one we finished up at last time around). * *	For each completed packet, we will either copy it and pass it up * 	the stack or, if the packet is near MTU sized, we allocate *	another buffer and flip the old one up the stack. * *	We must succeed in keeping a buffer on the ring. If necessary we *	will toss a received packet rather than lose a ring entry. Once *	the first uncompleted descriptor is found, we move the *	End-Of-List bit to include the buffers just processed. * */static void mc32_rx_ring(struct net_device *dev){	struct mc32_local *lp = netdev_priv(dev);	volatile struct skb_header *p;	u16 rx_ring_tail;	u16 rx_old_tail;	int x=0;	rx_old_tail = rx_ring_tail = lp->rx_ring_tail;	do	{		p=lp->rx_ring[rx_ring_tail].p;		if(!(p->status & (1<<7))) { /* Not COMPLETED */			break;		}		if(p->status & (1<<6)) /* COMPLETED_OK */		{			u16 length=p->length;			struct sk_buff *skb;			struct sk_buff *newskb;			/* 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=isa_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);			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 = netdev_priv(dev);	volatile struct skb_header *np;	/*	 * We rely on head==tail to mean 'queue empty'.	 * This is why lp->tx_count=TX_RING_LEN-1: in order to prevent	 * tx_ring_head wrapping to tail and confusing a 'queue empty'	 * condition with 'queue full'	 */	while (lp->tx_ring_tail != atomic_read(&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 irqreturn_t mc32_interrupt(int irq, void *dev_id){	struct net_device *dev = dev_id;	struct mc32_local *lp;	int ioaddr, status, boguscount = 0;	int rx_event = 0;	int tx_event = 0;	ioaddr = dev->base_addr;	lp = netdev_priv(dev);	/* 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 */				complete(&lp->xceiver_cmd);				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 */				complete(&lp->xceiver_cmd);				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)		{			/*			 * No thread is waiting: we need to tidy			 * up ourself.			 */			if (lp->cmd_nonblocking) {				up(&lp->cmd_mutex);				if (lp->mc_reload_wait)					mc32_reset_multicast_list(dev);			}			else complete(&lp->execution_cmd);		}		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 IRQ_HANDLED;}/** *	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 = netdev_priv(dev);	int ioaddr = dev->base_addr;	u8 regs;	u16 one=1;	lp->xceiver_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);	/* Ensure we issue no more commands beyond this point */	down(&lp->cmd_mutex);	/* 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 = netdev_priv(dev);	mc32_update_stats(dev);	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 = netdev_priv(dev);	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);}static void netdev_get_drvinfo(struct net_device *dev,			       struct ethtool_drvinfo *info){	strcpy(info->driver, DRV_NAME);	strcpy(info->version, DRV_VERSION);	sprintf(info->bus_info, "MCA 0x%lx", dev->base_addr);}static u32 netdev_get_msglevel(struct net_device *dev){	return mc32_debug;}static void netdev_set_msglevel(struct net_device *dev, u32 level){	mc32_debug = level;}static const struct ethtool_ops netdev_ethtool_ops = {	.get_drvinfo		= netdev_get_drvinfo,	.get_msglevel		= netdev_get_msglevel,	.set_msglevel		= netdev_set_msglevel,};#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 init_module(void){	this_device = mc32_probe(-1);	if (IS_ERR(this_device))		return PTR_ERR(this_device);	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 __exit cleanup_module(void){	unregister_netdev(this_device);	cleanup_card(this_device);	free_netdev(this_device);}#endif /* MODULE */

⌨️ 快捷键说明

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