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

📄 sunlance.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
	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? */	/* For a firewall its a good idea - AC */	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) & TX_RING_MOD_MASK;	/* 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;	/* Read back CSR to invalidate the E-Cache.	 * This is needed, because DMA_DSBL_WR_INV is set. */	if (lp->ledma)		flush = ll->rdp;	restore_flags(flags);	return 0;}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);	}}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;	}	/* This CANNOT be correct. Chip is running	   and dev->tbusy may change any moment.	   It is useless to set it.	   Generally, usage of dev->tbusy in this driver is completely	   wrong.	   I protected calls to this function	   with start_bh_atomic, so that set_multicast_list	   and hard_start_xmit are serialized now by top level. --ANK	   The same is true about a2065.	 */	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(static int sparc_lance_init (struct device *dev, struct linux_sbus_device *sdev,		  struct Linux_SBus_DMA *ledma,		  struct linux_sbus_device *lebuffer)){	static unsigned version_printed = 0;	int    i;	struct lance_private *lp;	volatile struct lance_regs *ll;	if (dev == NULL) {		dev = init_etherdev (0, sizeof (struct lance_private) + 8);	} else {		dev->priv = kmalloc (sizeof (struct lance_private) + 8,				     GFP_KERNEL);		if (dev->priv == NULL)			return -ENOMEM;		memset(dev->priv, 0, sizeof (struct lance_private) + 8);	}	if (sparc_lance_debug && version_printed++ == 0)		printk (version);	printk ("%s: LANCE ", dev->name);	/* Fill the dev fields */	dev->base_addr = (long) sdev;	/* Copy the IDPROM ethernet address to the device structure, later we	 * will copy the address in the device structure to the lance	 * initialization block.	 */	for (i = 0; i < 6; i++)		printk ("%2.2x%c", dev->dev_addr[i] = idprom->id_ethaddr[i],			i == 5 ? ' ': ':');	printk("\n");	/* Get the IO region */	prom_apply_sbus_ranges (sdev->my_bus, &sdev->reg_addrs [0],				sdev->num_registers, sdev);	ll = sparc_alloc_io (sdev->reg_addrs [0].phys_addr, 0,			     sizeof (struct lance_regs), lancestr,			     sdev->reg_addrs[0].which_io, 0x0);	/* Make certain the data structures used by the LANCE are aligned. */	dev->priv = (void *)(((unsigned long)dev->priv + 7) & ~7);	lp = (struct lance_private *) dev->priv;	lp->sbus = sdev->my_bus;	if (lebuffer){		prom_apply_sbus_ranges (lebuffer->my_bus,					&lebuffer->reg_addrs [0],					lebuffer->num_registers,					lebuffer);		lp->init_block = (void *)			sparc_alloc_io (lebuffer->reg_addrs [0].phys_addr, 0,				sizeof (struct lance_init_block), "lebuffer", 				lebuffer->reg_addrs [0].which_io, 0);		lp->init_block_dvma = 0;		lp->pio_buffer = 1;	} else {		lp->init_block = (void *)			sparc_dvma_malloc (sizeof (struct lance_init_block),					   lancedma, &lp->init_block_dvma);		lp->pio_buffer = 0;	}	lp->busmaster_regval = prom_getintdefault(sdev->prom_node,						  "busmaster-regval",						  (LE_C3_BSWP | LE_C3_ACON |						   LE_C3_BCON));	lp->ll = ll;	lp->name = lancestr;	lp->ledma = ledma;	lp->burst_sizes = 0;	if (lp->ledma) {		char prop[6];		unsigned int sbmask;		/* Find burst-size property for ledma */		lp->burst_sizes = prom_getintdefault(ledma->SBus_dev->prom_node,						     "burst-sizes", 0);		/* ledma may be capable of fast bursts, but sbus may not. */		sbmask = prom_getintdefault(ledma->SBus_dev->my_bus->prom_node,					    "burst-sizes", DMA_BURSTBITS);		lp->burst_sizes &= sbmask;		/* Get the cable-selection property */		memset(prop, 0, sizeof(prop));		prom_getstring(ledma->SBus_dev->prom_node, "cable-selection",			       prop, sizeof(prop));		if (prop[0] == 0) {			int topnd, nd;			printk("%s: using auto-carrier-detection.\n",			       dev->name);			/* Is this found at /options .attributes in all			 * Prom versions? XXX			 */			topnd = prom_getchild(prom_root_node);			nd = prom_searchsiblings(topnd, "options");			if (!nd)				goto no_link_test;			if (!prom_node_has_property(nd, "tpe-link-test?"))				goto no_link_test;			memset(prop, 0, sizeof(prop));			prom_getstring(nd, "tpe-link-test?", prop,				       sizeof(prop));			if (strcmp(prop, "true")) {				printk("%s: warning: overriding option "				       "'tpe-link-test?'\n", dev->name);				printk("%s: warning: mail any problems "				       "to ecd@skynet.be\n", dev->name);				set_auxio(AUXIO_LINK_TEST, 0);			}no_link_test:			lp->auto_select = 1;			lp->tpe = 0;		} else if (!strcmp(prop, "aui")) {			lp->auto_select = 0;			lp->tpe = 0;		} else {			lp->auto_select = 0;			lp->tpe = 1;		}		/* Reset ledma */		lp->ledma->regs->cond_reg |= DMA_RST_ENET;		udelay (200);		lp->ledma->regs->cond_reg &= ~DMA_RST_ENET;	}	/* This should never happen. */	if ((unsigned long)(lp->init_block->brx_ring) & 0x07) {		printk("%s: ERROR: Rx and Tx rings not on even boundary.\n",		       dev->name);		return ENODEV;	}	lp->dev = dev;	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->irq = sdev->irqs[0];	dev->dma = 0;	ether_setup (dev);	/* We cannot sleep if the chip is busy during a	 * multicast list update event, because such events	 * can occur from interrupts (ex. IPv6).  So we	 * use a timer to try again later when necessary. -DaveM	 */	init_timer(&lp->multicast_timer);	lp->multicast_timer.data = (unsigned long) dev;	lp->multicast_timer.function =		(void (*)(unsigned long)) &lance_set_multicast;#ifdef MODULE	dev->ifindex = dev_new_index();	lp->next_module = root_lance_dev;	root_lance_dev = lp;#endif	return 0;}/* On 4m, find the associated dma for the lance chip */static inline struct Linux_SBus_DMA *find_ledma (struct linux_sbus_device *dev){	struct Linux_SBus_DMA *p;	for_each_dvma(p)		if (p->SBus_dev == dev)			return p;	return 0;}#ifdef CONFIG_SUN4#include <asm/sun4paddr.h>/* Find all the lance cards on the system and initialize them */__initfunc(int sparc_lance_probe (struct device *dev)){	static struct linux_sbus_device sdev;	static int called = 0;	if(called)		return ENODEV;	called++;	if ((idprom->id_machtype == (SM_SUN4|SM_4_330)) ||	    (idprom->id_machtype == (SM_SUN4|SM_4_470))) {		memset (&sdev, 0, sizeof(sdev));		sdev.reg_addrs[0].phys_addr = sun4_eth_physaddr;		sdev.irqs[0] = 6;		return sparc_lance_init(dev, &sdev, 0, 0);	}	return ENODEV;}#else /* !CONFIG_SUN4 *//* Find all the lance cards on the system and initialize them */__initfunc(int sparc_lance_probe (struct device *dev)){	struct linux_sbus *bus;	struct linux_sbus_device *sdev = 0;	struct Linux_SBus_DMA *ledma = 0;	static int called = 0;	int cards = 0, v;	if(called)		return ENODEV;	called++;	for_each_sbus (bus) {		for_each_sbusdev (sdev, bus) {			if (cards) dev = NULL;			if (strcmp (sdev->prom_name, "le") == 0) {				cards++;				if ((v = sparc_lance_init(dev, sdev, 0, 0)))					return v;				continue;			}			if (strcmp (sdev->prom_name, "ledma") == 0) {				cards++;				ledma = find_ledma (sdev);				if ((v = sparc_lance_init(dev, sdev->child,							  ledma, 0)))					return v;				continue;			}			if (strcmp (sdev->prom_name, "lebuffer") == 0){				cards++;				if ((v = sparc_lance_init(dev, sdev->child,							  0, sdev)))					return v;				continue;			}		} /* for each sbusdev */	} /* for each sbus */	if (!cards)		return ENODEV;	return 0;}#endif /* !CONFIG_SUN4 */#ifdef MODULEintinit_module(void){	root_lance_dev = NULL;	return sparc_lance_probe(NULL);}voidcleanup_module(void){	struct lance_private *lp;	while (root_lance_dev) {		lp = root_lance_dev->next_module;		unregister_netdev(root_lance_dev->dev);		kfree(root_lance_dev->dev);		root_lance_dev = lp;	}}#endif /* MODULE */

⌨️ 快捷键说明

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