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

📄 hydra.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
        {		dev->interrupt = 0;		return;	}	/* acknowledge all interrupts, by clearing the interrupt flag */	WRITE_REG(NIC_ISR, intbits);	if((intbits & ISR_PTX) && !(intbits & ISR_TXE))	{		dev->tbusy = 0;		mark_bh(NET_BH);	}		if((intbits & ISR_PRX) && !(intbits & ISR_RXE))/* packet received OK */		hydra_rx(dev, priv, nicbase);        if(intbits & ISR_TXE)		priv->stats.tx_errors++;        if(intbits & ISR_RXE)		priv->stats.rx_errors++;	if(intbits & ISR_CNT) 	{		/*		 * read the tally counters and (currently) ignore the values		 * might be useful because of bugs of some versions of the 8390 NIC		 */#ifdef HYDRA_DEBUG		printk("hydra_interrupt(): ISR_CNT\n");#endif		(void)READ_REG(NIC_CNTR0);		(void)READ_REG(NIC_CNTR1);		(void)READ_REG(NIC_CNTR2);	}		if(intbits & ISR_OVW)	{#ifdef HYDRA_DEBUG		WRITE_REG(NIC_CR, CR_PAGE1 | CR_START | CR_NODMA);/* another one just too much for me to comprehend - basically this could  *//* only occur because of invalid access to hydra ram, thus invalidating  *//* the interrupt bits read - in average usage these do not occur at all */		printk("hydra_interrupt(): overwrite warning, NIC_ISR %02x, NIC_CURR %02x\n",			intbits, READ_REG(NIC_CURR));		WRITE_REG(NIC_CR, CR_PAGE0 | CR_START | CR_NODMA);#endif	    		/* overwrite warning occurred, stop NIC & check the BOUNDARY pointer */		/* FIXME - real overwrite handling needed !! */		printk("hydra_interrupt(): overwrite warning, resetting NIC\n");		WRITE_REG(NIC_CR, CR_PAGE0 | CR_NODMA | CR_STOP);		while(!(READ_REG(NIC_ISR) & ISR_RST));		/* wait for NIC to reset */		WRITE_REG(NIC_DCR, DCR_WTS | DCR_BOS | DCR_LS | DCR_FT0);		WRITE_REG(NIC_RBCR0, 0);		WRITE_REG(NIC_RBCR1, 0);		WRITE_REG(NIC_RCR, NIC_RCRBITS);		WRITE_REG(NIC_TCR, TCR_LB1);		WRITE_REG(NIC_PSTART, priv->rx_page_start);		WRITE_REG(NIC_PSTOP, priv->rx_page_stop);		WRITE_REG(NIC_BNDRY, priv->rx_page_start);		WRITE_REG(NIC_ISR, 0xff);		WRITE_REG(NIC_IMR, NIC_INTS);		/* currently this _won't_ reset my hydra, even though it is */		/* basically the same code as in the board init - any ideas? */		priv->next_pkt = priv->rx_page_start+1; /* init our s/w variable */		WRITE_REG(NIC_CURR, priv->next_pkt);    /* set the next buf for current */	    		WRITE_REG(NIC_CR, CR_PAGE0 | CR_NODMA | CR_START);		WRITE_REG(NIC_TCR, 0);	}	dev->interrupt = 0;	return;    }/* * packet transmit routine */static int hydra_start_xmit(struct sk_buff *skb, struct device *dev){	struct hydra_private *priv = (struct hydra_private *)dev->priv;	volatile u8 *nicbase = priv->hydra_nic_base;	int len, len1;	/* Transmitter timeout, serious problems. */	if(dev->tbusy)	{		int tickssofar = jiffies - dev->trans_start;		if(tickssofar < 20)			return(1);		WRITE_REG(NIC_CR, CR_STOP);		printk("%s: transmit timed out, status %4.4x, resetting.\n", dev->name, 0);		priv->stats.tx_errors++;		dev->tbusy = 0;		dev->trans_start = jiffies;		return(0);	}	len=skb->len;	/* fill in a tx ring entry */    #ifdef HYDRA_DEBUG	printk("TX pkt type 0x%04x from ", ((u16 *)skb->data)[6]);	{		int i;		u8 *ptr = &((u8 *)skb->data)[6];		for (i = 0; i < 6; i++)			printk("%02x", ptr[i]);	}	printk(" to ");	{		int i;		u8 *ptr = (u8 *)skb->data;		for (i = 0; i < 6; i++)			printk("%02x", ptr[i]);	}	printk(" data 0x%08x len %d\n", (int)skb->data, len);#endif	/*	 * make sure that the packet size is at least the minimum	 * allowed ethernet packet length.	 * (FIXME: Should also clear the unused space...)	 * note: minimum packet length is 64, including CRC	 */	len1 = len;	if(len < (ETHER_MIN_LEN-4))		len = (ETHER_MIN_LEN-1);	/* make sure we've got an even number of bytes to copy to hydra's mem */	if(len & 1) len++;	if((u32)(priv->hydra_base + (priv->tx_page_start << 8)) < 0x80000000)		printk("weirdness: memcpyw(txbuf, skbdata, len): txbuf = 0x%x\n", (u_int)(priv->hydra_base+(priv->tx_page_start<<8)));	/* copy the packet data to the transmit buffer 	   in the ethernet card RAM */	memcpyw((u16 *)(priv->hydra_base + (priv->tx_page_start << 8)),		(u16 *)skb->data, len);	/* clear the unused space */	for(; len1<len; len1++)		(u16)*(priv->hydra_base + (priv->tx_page_start<<8) + len1) = 0;	dev_kfree_skb(skb);	priv->stats.tx_packets++;	cli();	/* make sure we are on the correct page */	WRITE_REG(NIC_CR, CR_PAGE0 | CR_NODMA | CR_START);	/* here we configure the transmit page start register etc */	/* notice that this code is hardwired to one transmit buffer */	WRITE_REG(NIC_TPSR, priv->tx_page_start);	WRITE_REG(NIC_TBCR0, len & 0xff);	WRITE_REG(NIC_TBCR1, len >> 8);	/* commit the packet to the wire */	WRITE_REG(NIC_CR, CR_PAGE0 | CR_START | CR_NODMA | CR_TXP);	sti();	 dev->trans_start = jiffies;	return(0);}static void __inline__ hydra_rx(struct device *dev, struct hydra_private *priv, volatile u8 *nicbase){	volatile u16 *board_ram_ptr;	struct sk_buff *skb;	int hdr_next_pkt, pkt_len, len1, boundary;	/* remove packet(s) from the ring and commit them to TCP layer */	WRITE_REG(NIC_CR, CR_PAGE1 | CR_NODMA | CR_START); /* page 1 */	while(priv->next_pkt != READ_REG(NIC_CURR)) /* should read this only once? */	{		board_ram_ptr = (u16 *)(priv->hydra_base + (priv->next_pkt << 8));	#ifdef HYDRA_DEBUG		printk("next_pkt = 0x%x, board_ram_ptr = 0x%x\n", priv->next_pkt, board_ram_ptr);#endif			/* the following must be done with two steps, or		   GCC optimizes it to a byte access to Hydra memory,		   which doesn't work... */		hdr_next_pkt = board_ram_ptr[0];		hdr_next_pkt >>= 8;			pkt_len = board_ram_ptr[1];		pkt_len = ((pkt_len >> 8) | ((pkt_len & 0xff) << 8));	#ifdef HYDRA_DEBUG		printk("hydra_interrupt(): hdr_next_pkt = 0x%02x, len = %d\n", hdr_next_pkt, pkt_len);#endif			if(pkt_len >= ETHER_MIN_LEN && pkt_len <= ETHER_MAX_LEN)		{			/* note that board_ram_ptr is u16 */			/* CRC is not included in the packet length */					pkt_len -= 4;			skb = dev_alloc_skb(pkt_len+2);			if(skb == NULL)		  	{				printk(KERN_INFO "%s: memory squeeze, dropping packet.\n", dev->name);				priv->stats.rx_dropped++;			}			else			{				skb->dev = dev;				skb_reserve(skb, 2);				if(hdr_next_pkt < priv->next_pkt && hdr_next_pkt != priv->rx_page_start)				{					/* here, the packet is wrapped */					len1 = ((priv->rx_page_stop - priv->next_pkt)<<8)-4;								memcpyw((u16 *)skb_put(skb, len1), (u16 *)(board_ram_ptr+2), len1);					memcpyw((u16 *)skb_put(skb, pkt_len-len1),  (u16 *)(priv->hydra_base+(priv->rx_page_start<<8)), pkt_len-len1);			#ifdef HYDRA_DEBUG					printk("wrapped packet: %d/%d bytes\n", len1, pkt_len-len1);#endif				}  /* ... here, packet is not wrapped */				else					memcpyw((u16 *) skb_put(skb, pkt_len), (u16 *)(board_ram_ptr+2), pkt_len);			}		}		else		{			WRITE_REG(NIC_CR, CR_PAGE1 | CR_START | CR_NODMA);			printk("hydra_interrupt(): invalid packet len: %d, NIC_CURR = %02x\n", pkt_len, READ_REG(NIC_CURR));/*this is the error i kept getting until i switched to 0.9.10. it still doesn'tmean that the bug would have gone away - so be alarmed. the packet is likelybeing fetched from a wrong memory location - but why - dunno   note-for-v2.1: not really problem anymore. hasn't been for a long time.*/					WRITE_REG(NIC_CR, CR_PAGE0 | CR_START | CR_NODMA);			/* should probably reset the NIC here ?? */					hydra_open(dev);  /* FIXME - i shouldn't really be doing this. */			return;		}			/* now, update the next_pkt pointer */		if(hdr_next_pkt < priv->rx_page_stop)			priv->next_pkt = hdr_next_pkt;		else			printk("hydra_interrupt(): invalid next_pkt pointer %d\n", hdr_next_pkt);			/* update the boundary pointer */		boundary = priv->next_pkt - 1;		if(boundary < priv->rx_page_start)			boundary = priv->rx_page_stop - 1;			/* set NIC to page 0 to update the NIC_BNDRY register */		WRITE_REG(NIC_CR, CR_PAGE0 | CR_START | CR_NODMA);		WRITE_REG(NIC_BNDRY, boundary);			/* select page1 to access the NIC_CURR register */		WRITE_REG(NIC_CR, CR_PAGE1 | CR_START | CR_NODMA);				skb->protocol = eth_type_trans(skb, dev);		netif_rx(skb);		priv->stats.rx_packets++;		}	return;}    static struct net_device_stats *hydra_get_stats(struct device *dev){	struct hydra_private *priv = (struct hydra_private *)dev->priv;#if 0	u8 *board = priv->hydra_base; 	short saved_addr;#endif/* currently does nothing :) i'll finish this later */	return(&priv->stats);}#ifdef HAVE_MULTICASTstatic void set_multicast_list(struct device *dev, int num_addrs, void *addrs){	struct hydra_private *priv = (struct hydra_private *)dev->priv;	u8 *board = priv->hydra_base;	/* yes, this code is also waiting for someone to complete.. :) */	/* (personally i don't care about multicasts at all :) */	return;}#endif#ifdef MODULEstatic char devicename[9] = { 0, };static struct device hydra_dev ={	devicename,			/* filled in by register_netdev() */	0, 0, 0, 0,			/* memory */	0, 0,				/* base, irq */	0, 0, 0, NULL, hydra_probe,};int init_module(void){	int err;	if ((err = register_netdev(&hydra_dev))) {		if (err == -EIO)			printk("No Hydra board found. Module not loaded.\n");		return(err);	}	return(0);}void cleanup_module(void){	struct hydra_private *priv = (struct hydra_private *)hydra_dev.priv;	unregister_netdev(&hydra_dev);	zorro_unconfig_board(priv->key, 0);	kfree(priv);}#endif /* MODULE */

⌨️ 快捷键说明

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