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

📄 a2065.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
}static void lance_interrupt (int irq, void *dev_id, struct pt_regs *regs){	struct device *dev;	struct lance_private *lp;	volatile struct lance_regs *ll;	int csr0;	dev = (struct device *) dev_id;	lp = (struct lance_private *) dev->priv;	ll = lp->ll;	ll->rap = LE_CSR0;		/* LANCE Controller Status */	csr0 = ll->rdp;	if (!(csr0 & LE_C0_INTR))	/* Check if any interrupt has */		return;			/* been generated by the Lance. */	if (dev->interrupt)		printk ("%s: again", dev->name);	dev->interrupt = 1;	/* Acknowledge all the interrupt sources ASAP */	ll->rdp = csr0 & ~(LE_C0_INEA|LE_C0_TDMD|LE_C0_STOP|LE_C0_STRT|			   LE_C0_INIT);	if ((csr0 & LE_C0_ERR)) {		/* Clear the error condition */		ll->rdp = LE_C0_BABL|LE_C0_ERR|LE_C0_MISS|LE_C0_INEA;	}    	if (csr0 & LE_C0_RINT)		lance_rx (dev);	if (csr0 & LE_C0_TINT)		lance_tx (dev);	/* Log misc errors. */	if (csr0 & LE_C0_BABL)		lp->stats.tx_errors++;       /* Tx babble. */	if (csr0 & LE_C0_MISS)		lp->stats.rx_errors++;       /* Missed a Rx frame. */	if (csr0 & LE_C0_MERR) {		printk("%s: Bus master arbitration failure, status %4.4x.\n", dev->name, csr0);		/* Restart the chip. */		ll->rdp = LE_C0_STRT;	}	if ((TX_BUFFS_AVAIL >= 0) && dev->tbusy) {		dev->tbusy = 0;		mark_bh (NET_BH);	}	ll->rap = LE_CSR0;	ll->rdp = LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_MERR|					LE_C0_IDON|LE_C0_INEA;	dev->interrupt = 0;}struct device *last_dev = 0;static int lance_open (struct device *dev){	struct lance_private *lp = (struct lance_private *)dev->priv;	volatile struct lance_regs *ll = lp->ll;	int status = 0;	last_dev = dev;	/* Install the Interrupt handler */	if (request_irq(IRQ_AMIGA_PORTS, lance_interrupt, 0,			"a2065 Ethernet", dev))		return -EAGAIN;	/* Stop the Lance */	ll->rap = LE_CSR0;	ll->rdp = LE_C0_STOP;	load_csrs (lp);	lance_init_ring (dev);	dev->tbusy = 0;	dev->interrupt = 0;	dev->start = 1;	status = init_restart_lance (lp);	MOD_INC_USE_COUNT;	return status;}static int lance_close (struct device *dev){	struct lance_private *lp = (struct lance_private *) dev->priv;	volatile struct lance_regs *ll = lp->ll;	dev->start = 0;	dev->tbusy = 1;	del_timer(&lp->multicast_timer);	/* Stop the card */	ll->rap = LE_CSR0;	ll->rdp = LE_C0_STOP;	free_irq(IRQ_AMIGA_PORTS, dev);	MOD_DEC_USE_COUNT;	return 0;}static inline int lance_reset (struct device *dev){	struct lance_private *lp = (struct lance_private *)dev->priv;	volatile struct lance_regs *ll = lp->ll;	int status;    	/* Stop the lance */	ll->rap = LE_CSR0;	ll->rdp = LE_C0_STOP;	load_csrs (lp);	lance_init_ring (dev);	dev->trans_start = jiffies;	dev->interrupt = 0;	dev->start = 1;	dev->tbusy = 0;	status = init_restart_lance (lp);#ifdef DEBUG_DRIVER	printk ("Lance restart=%d\n", status);#endif	return status;}static int lance_start_xmit (struct sk_buff *skb, struct device *dev){	struct lance_private *lp = (struct lance_private *)dev->priv;	volatile struct lance_regs *ll = lp->ll;	volatile struct lance_init_block *ib = lp->init_block;	int entry, skblen, len;	int status = 0;	static int outs;	unsigned long flags;	/* Transmitter timeout, serious problems */	if (dev->tbusy) {		int tickssofar = jiffies - dev->trans_start;	    		if (tickssofar < 100) {			status = -1;		} else {			printk ("%s: transmit timed out, status %04x, resetting\n",				dev->name, ll->rdp);			lance_reset (dev);		}		return status;	}	/* Block a timer-based transmit from overlapping. */	if (test_and_set_bit (0, (void *) &dev->tbusy) != 0) {		printk ("Transmitter access conflict.\n");		return -1;	}	skblen = skb->len;	save_flags(flags);	cli();	if (!TX_BUFFS_AVAIL){		restore_flags(flags);		return -1;	}#ifdef DEBUG_DRIVER	/* dump the packet */	{		int i;			for (i = 0; i < 64; i++) {			if ((i % 16) == 0)				printk ("\n");			printk ("%2.2x ", skb->data [i]);		}	}#endif	len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen;	entry = lp->tx_new & lp->tx_ring_mod_mask;	ib->btx_ring [entry].length = (-len) | 0xf000;	ib->btx_ring [entry].misc = 0;    	memcpy ((char *)&ib->tx_buf [entry][0], skb->data, skblen);	/* Clear the slack of the packet, do I need this? */	if (len != skblen)		memset ((char *) &ib->tx_buf [entry][skblen], 0, len - skblen);    	/* Now, give the packet to the lance */	ib->btx_ring [entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN);	lp->tx_new = (lp->tx_new+1) & lp->tx_ring_mod_mask;	outs++;	/* Kick the lance: transmit now */	ll->rdp = LE_C0_INEA | LE_C0_TDMD;	dev->trans_start = jiffies;	dev_kfree_skb (skb);    	if (TX_BUFFS_AVAIL)		dev->tbusy = 0;	restore_flags(flags);	return status;}static struct net_device_stats *lance_get_stats (struct device *dev){	struct lance_private *lp = (struct lance_private *) dev->priv;	return &lp->stats;}/* taken from the depca driver */static void lance_load_multicast (struct device *dev){	struct lance_private *lp = (struct lance_private *) dev->priv;	volatile struct lance_init_block *ib = lp->init_block;	volatile u16 *mcast_table = (u16 *)&ib->filter;	struct dev_mc_list *dmi=dev->mc_list;	char *addrs;	int i, j, bit, byte;	u32 crc, poly = CRC_POLYNOMIAL_LE;		/* set all multicast bits */	if (dev->flags & IFF_ALLMULTI){ 		ib->filter [0] = 0xffffffff;		ib->filter [1] = 0xffffffff;		return;	}	/* clear the multicast filter */	ib->filter [0] = 0;	ib->filter [1] = 0;	/* Add addresses */	for (i = 0; i < dev->mc_count; i++){		addrs = dmi->dmi_addr;		dmi   = dmi->next;		/* multicast address? */		if (!(*addrs & 1))			continue;				crc = 0xffffffff;		for (byte = 0; byte < 6; byte++)			for (bit = *addrs++, j = 0; j < 8; j++, bit>>=1)			{				int test;				test = ((bit ^ crc) & 0x01);				crc >>= 1;				if (test)				{					crc = crc ^ poly;				}			}				crc = crc >> 26;		mcast_table [crc >> 4] |= 1 << (crc & 0xf);	}	return;}static void lance_set_multicast (struct device *dev){	struct lance_private *lp = (struct lance_private *) dev->priv;	volatile struct lance_init_block *ib = lp->init_block;	volatile struct lance_regs *ll = lp->ll;	if (!dev->start)		return;	if (dev->tbusy) {		mod_timer(&lp->multicast_timer, jiffies + 2);		return;	}	set_bit (0, (void *) &dev->tbusy);	if (lp->tx_old != lp->tx_new) {		mod_timer(&lp->multicast_timer, jiffies + 4);		dev->tbusy = 0;		return;	}	ll->rap = LE_CSR0;	ll->rdp = LE_C0_STOP;	lance_init_ring (dev);	if (dev->flags & IFF_PROMISC) {		ib->mode |= LE_MO_PROM;	} else {		ib->mode &= ~LE_MO_PROM;		lance_load_multicast (dev);	}	load_csrs (lp);	init_restart_lance (lp);	dev->tbusy = 0;	mark_bh(NET_BH);}__initfunc(int a2065_probe(struct device *dev)){	unsigned int key, is_cbm;	const struct ConfigDev *cd;	u_long board;	u_long sn;	struct lance_private *priv;	struct A2065Board *a2065;	if ((key = is_cbm = zorro_find(ZORRO_PROD_CBM_A2065_1, 0, 0)) ||	    (key = is_cbm = zorro_find(ZORRO_PROD_CBM_A2065_2, 0, 0)) ||	    (key = zorro_find(ZORRO_PROD_AMERISTAR_A2065, 0, 0))) {		cd = zorro_get_board(key);		if ((board = (u_long)cd->cd_BoardAddr)) {			sn = cd->cd_Rom.er_SerialNumber;			if (is_cbm) {			/* Commodore */				dev->dev_addr[0] = 0x00;				dev->dev_addr[1] = 0x80;				dev->dev_addr[2] = 0x10;			} else {			/* Ameristar */				dev->dev_addr[0] = 0x00;				dev->dev_addr[1] = 0x00;				dev->dev_addr[2] = 0x9f;			}			dev->dev_addr[3] = (sn>>16) & 0xff;			dev->dev_addr[4] = (sn>>8) & 0xff;			dev->dev_addr[5] = sn & 0xff;			printk("%s: A2065 at 0x%08lx, Ethernet Address %02x:%02x:%02x:%02x:%02x:%02x\n",			       dev->name, board, dev->dev_addr[0],			       dev->dev_addr[1], dev->dev_addr[2],			       dev->dev_addr[3], dev->dev_addr[4],			       dev->dev_addr[5]);			init_etherdev(dev, 0);			dev->priv = kmalloc(sizeof(struct						   lance_private),					    GFP_KERNEL);			if (dev->priv == NULL)  				return -ENOMEM;			priv = (struct lance_private *)dev->priv;			memset(priv, 0, sizeof(struct lance_private));			a2065 = (struct A2065Board *)ZTWO_VADDR(board);			priv->ll = &a2065->Lance;			priv->init_block =					(struct lance_init_block *)&a2065->RAM;			priv->lance_init_block = (struct lance_init_block *)					      offsetof(struct A2065Board, RAM);			priv->auto_select = 0;			priv->key = key;			priv->busmaster_regval = LE_C3_BSWP;			priv->lance_log_rx_bufs = LANCE_LOG_RX_BUFFERS;			priv->lance_log_tx_bufs = LANCE_LOG_TX_BUFFERS;			priv->rx_ring_mod_mask = RX_RING_MOD_MASK;			priv->tx_ring_mod_mask = TX_RING_MOD_MASK;			dev->open = &lance_open;			dev->stop = &lance_close;			dev->hard_start_xmit = &lance_start_xmit;			dev->get_stats = &lance_get_stats;			dev->set_multicast_list = &lance_set_multicast;			dev->dma = 0;			ether_setup(dev);			init_timer(&priv->multicast_timer);			priv->multicast_timer.data = (unsigned long) dev;			priv->multicast_timer.function =				(void (*)(unsigned long)) &lance_set_multicast;			zorro_config_board(key, 0);			return(0);		}	}	return(-ENODEV);}#ifdef MODULEstatic char devicename[9] = { 0, };static struct device a2065_dev ={	devicename,			/* filled in by register_netdev() */	0, 0, 0, 0,			/* memory */	0, 0,				/* base, irq */	0, 0, 0, NULL, a2065_probe,};int init_module(void){	int err;	if ((err = register_netdev(&a2065_dev))) {		if (err == -EIO)			printk("No A2065 board found. Module not loaded.\n");		return(err);	}	return(0);}void cleanup_module(void){	struct lance_private *priv = (struct lance_private *)a2065_dev.priv;	unregister_netdev(&a2065_dev);	zorro_unconfig_board(priv->key, 0);	kfree(priv);}#endif /* MODULE */

⌨️ 快捷键说明

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