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

📄 a2065.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
				lp->stats.collisions += 2;			lp->stats.tx_packets++;		}			j = (j + 1) & lp->tx_ring_mod_mask;	}	lp->tx_old = j;	ll->rdp = LE_C0_TINT | LE_C0_INEA;	return 0;}static void lance_interrupt (int irq, void *dev_id, struct pt_regs *regs){	struct net_device *dev;	struct lance_private *lp;	volatile struct lance_regs *ll;	int csr0;	dev = (struct net_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. */	/* 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 (netif_queue_stopped(dev) && TX_BUFFS_AVAIL > 0)		netif_wake_queue(dev);	ll->rap = LE_CSR0;	ll->rdp = LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_MERR|					LE_C0_IDON|LE_C0_INEA;}struct net_device *last_dev = 0;static int lance_open (struct net_device *dev){	struct lance_private *lp = (struct lance_private *)dev->priv;	volatile struct lance_regs *ll = lp->ll;	int ret;	last_dev = dev;	/* Install the Interrupt handler */	ret = request_irq(IRQ_AMIGA_PORTS, lance_interrupt, SA_SHIRQ,			  dev->name, dev);	if (ret) return ret;	/* Stop the Lance */	ll->rap = LE_CSR0;	ll->rdp = LE_C0_STOP;	load_csrs (lp);	lance_init_ring (dev);	netif_start_queue(dev);	return init_restart_lance (lp);}static int lance_close (struct net_device *dev){	struct lance_private *lp = (struct lance_private *) dev->priv;	volatile struct lance_regs *ll = lp->ll;	netif_stop_queue(dev);	del_timer_sync(&lp->multicast_timer);	/* Stop the card */	ll->rap = LE_CSR0;	ll->rdp = LE_C0_STOP;	free_irq(IRQ_AMIGA_PORTS, dev);	return 0;}static inline int lance_reset (struct net_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;	netif_start_queue(dev);	status = init_restart_lance (lp);#ifdef DEBUG_DRIVER	printk ("Lance restart=%d\n", status);#endif	return status;}static void lance_tx_timeout(struct net_device *dev){	struct lance_private *lp = (struct lance_private *) dev->priv;	volatile struct lance_regs *ll = lp->ll;	printk(KERN_ERR "%s: transmit timed out, status %04x, reset\n",	       dev->name, ll->rdp);	lance_reset(dev);	netif_wake_queue(dev);}static int lance_start_xmit (struct sk_buff *skb, struct net_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;	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++;	if (TX_BUFFS_AVAIL <= 0)		netif_stop_queue(dev);	/* Kick the lance: transmit now */	ll->rdp = LE_C0_INEA | LE_C0_TDMD;	dev->trans_start = jiffies;	dev_kfree_skb (skb);    	restore_flags(flags);	return status;}static struct net_device_stats *lance_get_stats (struct net_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 net_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 net_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 (!netif_running(dev))		return;	if (lp->tx_old != lp->tx_new) {		mod_timer(&lp->multicast_timer, jiffies + 4);		netif_wake_queue(dev);		return;	}	netif_stop_queue(dev);	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);	netif_wake_queue(dev);}static int __init a2065_probe(void){	struct zorro_dev *z = NULL;	struct net_device *dev;	struct lance_private *priv;	int res = -ENODEV;	while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {		unsigned long board, base_addr, mem_start;		struct resource *r1, *r2;		int is_cbm;		if (z->id == ZORRO_PROD_CBM_A2065_1 ||		    z->id == ZORRO_PROD_CBM_A2065_2)			is_cbm = 1;		else if (z->id == ZORRO_PROD_AMERISTAR_A2065)			is_cbm = 0;		else			continue;		board = z->resource.start;		base_addr = board+A2065_LANCE;		mem_start = board+A2065_RAM;		r1 = request_mem_region(base_addr, sizeof(struct lance_regs),					"Am7990");		if (!r1) continue;		r2 = request_mem_region(mem_start, A2065_RAM_SIZE, "RAM");		if (!r2) {			release_resource(r1);			continue;		}		dev = init_etherdev(NULL, sizeof(struct lance_private));		if (dev == NULL) {			release_resource(r1);			release_resource(r2);			return -ENOMEM;		}		SET_MODULE_OWNER(dev);		priv = dev->priv;		r1->name = dev->name;		r2->name = dev->name;		priv->dev = dev;		dev->dev_addr[0] = 0x00;		if (is_cbm) {				/* Commodore */			dev->dev_addr[1] = 0x80;			dev->dev_addr[2] = 0x10;		} else {				/* Ameristar */			dev->dev_addr[1] = 0x00;			dev->dev_addr[2] = 0x9f;		}		dev->dev_addr[3] = (z->rom.er_SerialNumber>>16) & 0xff;		dev->dev_addr[4] = (z->rom.er_SerialNumber>>8) & 0xff;		dev->dev_addr[5] = z->rom.er_SerialNumber & 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]);		dev->base_addr = ZTWO_VADDR(base_addr);		dev->mem_start = ZTWO_VADDR(mem_start);		dev->mem_end = dev->mem_start+A2065_RAM_SIZE;		priv->ll = (volatile struct lance_regs *)dev->base_addr;		priv->init_block = (struct lance_init_block *)dev->mem_start;		priv->lance_init_block = (struct lance_init_block *)A2065_RAM;		priv->auto_select = 0;		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->tx_timeout = &lance_tx_timeout;		dev->watchdog_timeo = 5*HZ;		dev->get_stats = &lance_get_stats;		dev->set_multicast_list = &lance_set_multicast;		dev->dma = 0;#ifdef MODULE		priv->next_module = root_a2065_dev;		root_a2065_dev = priv;#endif		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;		res = 0;	}	return res;}static void __exit a2065_cleanup(void){#ifdef MODULE	struct lance_private *next;	struct net_device *dev;	while (root_a2065_dev) {		next = root_a2065_dev->next_module;		dev = root_a2065_dev->dev;		unregister_netdev(dev);		release_mem_region(ZTWO_PADDR(dev->base_addr),				   sizeof(struct lance_regs));		release_mem_region(ZTWO_PADDR(dev->mem_start), A2065_RAM_SIZE);		kfree(dev);		root_a2065_dev = next;	}#endif}module_init(a2065_probe);module_exit(a2065_cleanup);

⌨️ 快捷键说明

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