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

📄 3c527.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 3 页
字号:
 *	reply. All well and good. The complication arises because you use *	commands for filter list changes which come in at bh level from things *	like IPV6 group stuff. * *	We have a simple state machine * *	0	- nothing issued * *	1	- command issued, wait reply * *	2	- reply waiting - reader then goes to state 0 * *	3	- command issued, trash reply. In which case the irq *		  takes it back to state 0 * */  static int mc32_command(struct net_device *dev, u16 cmd, void *data, int len){	struct mc32_local *lp = (struct mc32_local *)dev->priv;	int ioaddr = dev->base_addr;	unsigned long flags;	int ret = 0;		/*	 *	Wait for a command	 */	 	save_flags(flags);	cli();	 	while(lp->exec_pending)		sleep_on(&lp->event);			/*	 *	Issue mine	 */	lp->exec_pending=1;		restore_flags(flags);		lp->exec_box->mbox=0;	lp->exec_box->mbox=cmd;	memcpy((void *)lp->exec_box->data, data, len);	barrier();	/* the memcpy forgot the volatile so be sure */	/* Send the command */	while(!(inb(ioaddr+HOST_STATUS)&HOST_STATUS_CRR));	outb(1<<6, ioaddr+HOST_CMD);		save_flags(flags);	cli();	while(lp->exec_pending!=2)		sleep_on(&lp->event);	lp->exec_pending=0;	restore_flags(flags);		if(lp->exec_box->mbox&(1<<13))		ret = -1;	/*	 *	A multicast set got blocked - do it now	 */			if(lp->mc_reload_wait)	{		mc32_reset_multicast_list(dev);	}	return ret;}/** *	mc32_start_transceiver	-	tell board to restart tx/rx *	@dev: The 3c527 card to issue the command to * *	This may be called from the interrupt state, where it is used *	to restart the rx ring if the card runs out of rx buffers.  *	 * 	First, we check if it's ok to start the transceiver. We then show * 	the card where to start in the rx ring and issue the * 	commands to start reception and transmission. We don't wait * 	around for these to complete. */ static void mc32_start_transceiver(struct net_device *dev) {	struct mc32_local *lp = (struct mc32_local *)dev->priv;	int ioaddr = dev->base_addr;	/* Ignore RX overflow on device closure */ 	if (lp->desired_state==HALTED)  		return; 	mc32_ready_poll(dev); 	lp->tx_box->mbox=0;	lp->rx_box->mbox=0;	/* Give the card the offset to the post-EOL-bit RX descriptor */ 	lp->rx_box->data[0]=lp->rx_ring[prev_rx(lp->rx_ring_tail)].p->next; 	outb(HOST_CMD_START_RX, ioaddr+HOST_CMD);      	mc32_ready_poll(dev); 	outb(HOST_CMD_RESTRT_TX, ioaddr+HOST_CMD);   /* card ignores this on RX restart */ 		/* We are not interrupted on start completion */ 	lp->xceiver_state=RUNNING; }/** *	mc32_halt_transceiver	-	tell board to stop tx/rx *	@dev: The 3c527 card to issue the command to * *	We issue the commands to halt the card's transceiver. In fact, *	after some experimenting we now simply tell the card to *	suspend. When issuing aborts occasionally odd things happened. * *	We then sleep until the card has notified us that both rx and *	tx have been suspended. */ static void mc32_halt_transceiver(struct net_device *dev) {	struct mc32_local *lp = (struct mc32_local *)dev->priv;	int ioaddr = dev->base_addr;	unsigned long flags;	mc32_ready_poll(dev);		lp->tx_box->mbox=0;	lp->rx_box->mbox=0;	outb(HOST_CMD_SUSPND_RX, ioaddr+HOST_CMD);				mc32_ready_poll(dev); 	outb(HOST_CMD_SUSPND_TX, ioaddr+HOST_CMD);				save_flags(flags);	cli();			while(lp->xceiver_state!=HALTED) 		sleep_on(&lp->event); 			restore_flags(flags);	} /** *	mc32_load_rx_ring	-	load the ring of receive buffers *	@dev: 3c527 to build the ring for * *	This initalises the on-card and driver datastructures to *	the point where mc32_start_transceiver() can be called. * *	The card sets up the receive ring for us. We are required to use the *	ring it provides although we can change the size of the ring. * * 	We allocate an sk_buff for each ring entry in turn and * 	initalise its house-keeping info. At the same time, we read * 	each 'next' pointer in our rx_ring array. This reduces slow * 	shared-memory reads and makes it easy to access predecessor * 	descriptors. * *	We then set the end-of-list bit for the last entry so that the * 	card will know when it has run out of buffers. */	 static int mc32_load_rx_ring(struct net_device *dev){	struct mc32_local *lp = (struct mc32_local *)dev->priv;	int i;	u16 rx_base;	volatile struct skb_header *p;		rx_base=lp->rx_chain;	for(i=0;i<RX_RING_LEN;i++)	{		lp->rx_ring[i].skb=alloc_skb(1532, GFP_KERNEL);		skb_reserve(lp->rx_ring[i].skb, 18);  		if(lp->rx_ring[i].skb==NULL)		{			for(;i>=0;i--)				kfree_skb(lp->rx_ring[i].skb);			return -ENOBUFS;		}				p=bus_to_virt(lp->base+rx_base);						p->control=0;		p->data=virt_to_bus(lp->rx_ring[i].skb->data);		p->status=0;		p->length=1532;			lp->rx_ring[i].p=p; 		rx_base=p->next; 	}	lp->rx_ring[i-1].p->control |= CONTROL_EOL;	lp->rx_ring_tail=0;	return 0;}	/** *	mc32_flush_rx_ring	-	free the ring of receive buffers *	@lp: Local data of 3c527 to flush the rx ring of * *	Free the buffer for each ring slot. This may be called  *      before mc32_load_rx_ring(), eg. on error in mc32_open(). */static void mc32_flush_rx_ring(struct net_device *dev){	struct mc32_local *lp = (struct mc32_local *)dev->priv;		struct sk_buff *skb;	int i; 	for(i=0; i < RX_RING_LEN; i++) 	{ 		skb = lp->rx_ring[i].skb;		if (skb!=NULL) {			kfree_skb(skb);			skb=NULL; 		}		lp->rx_ring[i].p=NULL; 	} }/** *	mc32_load_tx_ring	-	load transmit ring *	@dev: The 3c527 card to issue the command to * *	This sets up the host transmit data-structures.  * *	First, we obtain from the card it's current postion in the tx *	ring, so that we will know where to begin transmitting *	packets. * 	 * 	Then, we read the 'next' pointers from the on-card tx ring into *  	our tx_ring array to reduce slow shared-mem reads. Finally, we * 	intitalise the tx house keeping variables. *  */ static void mc32_load_tx_ring(struct net_device *dev){ 	struct mc32_local *lp = (struct mc32_local *)dev->priv;	volatile struct skb_header *p;	int i; 	u16 tx_base;	tx_base=lp->tx_box->data[0]; 	for(i=0;i<lp->tx_len;i++) 	{		p=bus_to_virt(lp->base+tx_base);		lp->tx_ring[i].p=p; 		lp->tx_ring[i].skb=NULL;		tx_base=p->next;	}	/* -1 so that tx_ring_head cannot "lap" tx_ring_tail,           */	/* which would be bad news for mc32_tx_ring as cur. implemented */ 	atomic_set(&lp->tx_count, TX_RING_LEN-1); 	lp->tx_ring_head=lp->tx_ring_tail=0; } /** *	mc32_flush_tx_ring 	-	free transmit ring *	@lp: Local data of 3c527 to flush the tx ring of * *	We have to consider two cases here. We want to free the pending *	buffers only. If the ring buffer head is past the start then the *	ring segment we wish to free wraps through zero. The tx ring  *	house-keeping variables are then reset. */static void mc32_flush_tx_ring(struct net_device *dev){	struct mc32_local *lp = (struct mc32_local *)dev->priv;		if(lp->tx_ring_tail!=lp->tx_ring_head)	{		int i;			if(lp->tx_ring_tail < lp->tx_ring_head)		{			for(i=lp->tx_ring_tail;i<lp->tx_ring_head;i++)			{				dev_kfree_skb(lp->tx_ring[i].skb);				lp->tx_ring[i].skb=NULL;				lp->tx_ring[i].p=NULL; 			}		}		else		{			for(i=lp->tx_ring_tail; i<TX_RING_LEN; i++) 			{				dev_kfree_skb(lp->tx_ring[i].skb);				lp->tx_ring[i].skb=NULL;				lp->tx_ring[i].p=NULL; 			}			for(i=0; i<lp->tx_ring_head; i++) 			{				dev_kfree_skb(lp->tx_ring[i].skb);				lp->tx_ring[i].skb=NULL;				lp->tx_ring[i].p=NULL; 			}		}	}		atomic_set(&lp->tx_count, 0); 	lp->tx_ring_tail=lp->tx_ring_head=0;} 	/** *	mc32_open	-	handle 'up' of card *	@dev: device to open * *	The user is trying to bring the card into ready state. This requires *	a brief dialogue with the card. Firstly we enable interrupts and then *	'indications'. Without these enabled the card doesn't bother telling *	us what it has done. This had me puzzled for a week. * *	We configure the number of card descriptors, then load the network *	address and multicast filters. Turn on the workaround mode. This *	works around a bug in the 82586 - it asks the firmware to do *	so. It has a performance (latency) hit but is needed on busy *	[read most] lans. We load the ring with buffers then we kick it *	all off. */static int mc32_open(struct net_device *dev){	int ioaddr = dev->base_addr;	struct mc32_local *lp = (struct mc32_local *)dev->priv;	u8 one=1;	u8 regs;	u16 descnumbuffs[2] = {TX_RING_LEN, RX_RING_LEN};	/*	 *	Interrupts enabled	 */	regs=inb(ioaddr+HOST_CTRL);	regs|=HOST_CTRL_INTE;	outb(regs, ioaddr+HOST_CTRL);		/*	 *	Send the indications on command	 */	mc32_command(dev, 4, &one, 2);	/*	 *	Poke it to make sure it's really dead. 	 */	mc32_halt_transceiver(dev); 	mc32_flush_tx_ring(dev); 	/* 	 *	Ask card to set up on-card descriptors to our spec 	 */ 	if(mc32_command(dev, 8, descnumbuffs, 4)) { 		printk("%s: %s rejected our buffer configuration!\n",	 	       dev->name, cardname);		mc32_close(dev); 		return -ENOBUFS; 	}		/* Report new configuration */ 	mc32_command(dev, 6, NULL, 0); 	lp->tx_chain 		= lp->exec_box->data[8];   /* Transmit list start offset */	lp->rx_chain 		= lp->exec_box->data[10];  /* Receive list start offset */	lp->tx_len 		= lp->exec_box->data[9];   /* Transmit list count */ 	lp->rx_len 		= lp->exec_box->data[11];  /* Receive list count */ 	/* Set Network Address */	mc32_command(dev, 1, dev->dev_addr, 6);		/* Set the filters */	mc32_set_multicast_list(dev);		   	if (WORKAROUND_82586) { 		u16 zero_word=0;		mc32_command(dev, 0x0D, &zero_word, 2);   /* 82586 bug workaround on  */	}	mc32_load_tx_ring(dev);		if(mc32_load_rx_ring(dev)) 	{		mc32_close(dev);		return -ENOBUFS;	}	lp->desired_state = RUNNING; 		/* And finally, set the ball rolling... */	mc32_start_transceiver(dev);	netif_start_queue(dev);	return 0;}/** *	mc32_timeout	-	handle a timeout from the network layer *	@dev: 3c527 that timed out * *	Handle a timeout on transmit from the 3c527. This normally means *	bad things as the hardware handles cable timeouts and mess for *	us. * */static void mc32_timeout(struct net_device *dev){	printk(KERN_WARNING "%s: transmit timed out?\n", dev->name);	/* Try to restart the adaptor. */	netif_wake_queue(dev);}/** *	mc32_send_packet	-	queue a frame for transmit *	@skb: buffer to transmit *	@dev: 3c527 to send it out of * *	Transmit a buffer. This normally means throwing the buffer onto *	the transmit queue as the queue is quite large. If the queue is *	full then we set tx_busy and return. Once the interrupt handler *	gets messages telling it to reclaim transmit queue entries we will *	clear tx_busy and the kernel will start calling this again. * *	We use cli rather than spinlocks. Since I have no access to an SMP *	MCA machine I don't plan to change it. It is probably the top  *	performance hit for this driver on SMP however. */static int mc32_send_packet(struct sk_buff *skb, struct net_device *dev){	struct mc32_local *lp = (struct mc32_local *)dev->priv;	unsigned long flags;	volatile struct skb_header *p, *np;	netif_stop_queue(dev);	save_flags(flags);	cli();			if(atomic_read(&lp->tx_count)==0)	{		restore_flags(flags);		return 1;	}	atomic_dec(&lp->tx_count); 	/* P is the last sending/sent buffer as a pointer */	p=lp->tx_ring[lp->tx_ring_head].p; 			lp->tx_ring_head=next_tx(lp->tx_ring_head); 	/* NP is the buffer we will be loading */	np=lp->tx_ring[lp->tx_ring_head].p; 	/* We will need this to flush the buffer out */	lp->tx_ring[lp->tx_ring_head].skb=skb;   	   	np->length = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len; 				np->data	= virt_to_bus(skb->data);	np->status	= 0;	np->control     = CONTROL_EOP | CONTROL_EOL;     	wmb();			p->control     &= ~CONTROL_EOL;     /* Clear EOL on p */ 		restore_flags(flags);	netif_wake_queue(dev);	return 0;}/** *	mc32_update_stats	-	pull off the on board statistics *	@dev: 3c527 to service * *  *	Query and reset the on-card stats. There's the small possibility *	of a race here, which would result in an underestimation of *	actual errors. As such, we'd prefer to keep all our stats *	collection in software. As a rule, we do. However it can't be *	used for rx errors and collisions as, by default, the card discards *	bad rx packets.  * *	Setting the SAV BP in the rx filter command supposedly *	stops this behaviour. However, testing shows that it only seems to *	enable the collation of on-card rx statistics --- the driver *	never sees an RX descriptor with an error status set. * */static void mc32_update_stats(struct net_device *dev){	struct mc32_local *lp = (struct mc32_local *)dev->priv;	volatile struct mc32_stats *st = lp->stats; 	u32 rx_errors=0;       	rx_errors+=lp->net_stats.rx_crc_errors   +=st->rx_crc_errors;         	                                           st->rx_crc_errors=0;	rx_errors+=lp->net_stats.rx_fifo_errors  +=st->rx_overrun_errors;   	                                           st->rx_overrun_errors=0; 	rx_errors+=lp->net_stats.rx_frame_errors +=st->rx_alignment_errors;  	                                           st->rx_alignment_errors=0;	rx_errors+=lp->net_stats.rx_length_errors+=st->rx_tooshort_errors; 	                                           st->rx_tooshort_errors=0;	rx_errors+=lp->net_stats.rx_missed_errors+=st->rx_outofresource_errors;	                                           st->rx_outofresource_errors=0;         lp->net_stats.rx_errors=rx_errors; 						   	/* Number of packets which saw one collision */	lp->net_stats.collisions+=st->dataC[10];	st->dataC[10]=0; 	/* Number of packets which saw 2--15 collisions */ 	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 neccessary 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=dev->priv;			volatile struct skb_header *p;	u16 rx_ring_tail = lp->rx_ring_tail;	u16 rx_old_tail = rx_ring_tail; 	int x=0;		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; 

⌨️ 快捷键说明

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