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

📄 sk_mca.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	}	dev->irq = priv->realirq;	/* set up the card and LANCE */	InitBoard(dev);	/* set up flags */#if (LINUX_VERSION_CODE >= 0x02032a)	netif_start_queue(dev);#else	dev->interrupt = 0;	dev->tbusy = 0;	dev->start = 0;	MOD_INC_USE_COUNT;#endif	return 0;}/* close driver.  Shut down board and free allocated resources */static int skmca_close(struct SKMCA_NETDEV *dev){	/* turn off board */	DeinitBoard(dev);	/* release resources */	if (dev->irq != 0)		free_irq(dev->irq, dev);	dev->irq = 0;#if (LINUX_VERSION_CODE < 0x02032a)	MOD_DEC_USE_COUNT;#endif	return 0;}/* transmit a block. */static int skmca_tx(struct sk_buff *skb, struct SKMCA_NETDEV *dev){	skmca_priv *priv = (skmca_priv *) dev->priv;	LANCE_TxDescr descr;	unsigned int address;	int tmplen, retval = 0;	unsigned long flags;	/* if we get called with a NULL descriptor, the Ethernet layer thinks 	   our card is stuck an we should reset it.  We'll do this completely: */	if (skb == NULL) {		DeinitBoard(dev);		InitBoard(dev);		return 0;	/* don't try to free the block here ;-) */	}	/* is there space in the Tx queue ? If no, the upper layer gave us a	   packet in spite of us not being ready and is really in trouble.	   We'll do the dropping for him: */	if (priv->txbusy >= TXCOUNT) {		priv->stat.tx_dropped++;		retval = -EIO;		goto tx_done;	}	/* get TX descriptor */	address = RAM_TXBASE + (priv->nexttxput * sizeof(LANCE_TxDescr));	SKMCA_FROMIO(&descr, dev->mem_start + address,		     sizeof(LANCE_TxDescr));	/* enter packet length as 2s complement - assure minimum length */	tmplen = skb->len;	if (tmplen < 60)		tmplen = 60;	descr.Len = 65536 - tmplen;	/* copy filler into RAM - in case we're filling up... 	   we're filling a bit more than necessary, but that doesn't harm	   since the buffer is far larger... */	if (tmplen > skb->len) {		char *fill = "NetBSD is a nice OS too! ";		unsigned int destoffs = 0, l = strlen(fill);		while (destoffs < tmplen) {			SKMCA_TOIO(dev->mem_start + descr.LowAddr +				   destoffs, fill, l);			destoffs += l;		}	}	/* do the real data copying */	SKMCA_TOIO(dev->mem_start + descr.LowAddr, skb->data, skb->len);	/* hand descriptor over to LANCE - this is the first and last chunk */	descr.Flags =	    TXDSCR_FLAGS_OWN | TXDSCR_FLAGS_STP | TXDSCR_FLAGS_ENP;#ifdef DEBUG	PrTime();	printk("Send packet on descr %d len %d\n", priv->nexttxput,	       skb->len);#endif	/* one more descriptor busy */	save_flags(flags);	cli();	priv->nexttxput++;	if (priv->nexttxput >= TXCOUNT)		priv->nexttxput = 0;	priv->txbusy++;	/* are we saturated ? */	if (priv->txbusy >= TXCOUNT)#if (LINUX_VERSION_CODE >= 0x02032a)		netif_stop_queue(dev);#else		dev->tbusy = 1;#endif	/* write descriptor back to RAM */	SKMCA_TOIO(dev->mem_start + address, &descr,		   sizeof(LANCE_TxDescr));	/* if no descriptors were active, give the LANCE a hint to read it	   immediately */	if (priv->txbusy == 0)		SetLANCE(dev, LANCE_CSR0, CSR0_INEA | CSR0_TDMD);	restore_flags(flags);      tx_done:	/* When did that change exactly ? */#if LINUX_VERSION_CODE >= 0x020200	dev_kfree_skb(skb);#else	dev_kfree_skb(skb, FREE_WRITE);#endif	return retval;}/* return pointer to Ethernet statistics */static struct net_device_stats *skmca_stats(struct SKMCA_NETDEV *dev){	skmca_priv *priv = (skmca_priv *) dev->priv;	return &(priv->stat);}/* we don't support runtime reconfiguration, since an MCA card can   be unambigously identified by its POS registers. */static int skmca_config(struct SKMCA_NETDEV *dev, struct ifmap *map){	return 0;}/* switch receiver mode.  We use the LANCE's multicast filter to prefilter   multicast addresses. */static void skmca_set_multicast_list(struct SKMCA_NETDEV *dev){	LANCE_InitBlock block;	/* first stop the LANCE... */	StopLANCE(dev);	/* ...then modify the initialization block... */	SKMCA_FROMIO(&block, dev->mem_start + RAM_INITBASE, sizeof(block));	if (dev->flags & IFF_PROMISC)		block.Mode |= LANCE_INIT_PROM;	else		block.Mode &= ~LANCE_INIT_PROM;	if (dev->flags & IFF_ALLMULTI) {	/* get all multicasts */		memset(block.LAdrF, 8, 0xff);	} else {		/* get selected/no multicasts */		struct dev_mc_list *mptr;		int code;		memset(block.LAdrF, 8, 0x00);		for (mptr = dev->mc_list; mptr != NULL; mptr = mptr->next) {			code = GetHash(mptr->dmi_addr);			block.LAdrF[(code >> 3) & 7] |= 1 << (code & 7);		}	}	SKMCA_TOIO(dev->mem_start + RAM_INITBASE, &block, sizeof(block));	/* ...then reinit LANCE with the correct flags */	InitLANCE(dev);}/* ------------------------------------------------------------------------ * hardware check * ------------------------------------------------------------------------ */static int startslot;		/* counts through slots when probing multiple devices */int skmca_probe(struct SKMCA_NETDEV *dev){	int force_detect = 0;	int junior, slot, i;	int base = 0, irq = 0;	skmca_priv *priv;	skmca_medium medium;	/* can't work without an MCA bus ;-) */	if (MCA_bus == 0)		return -ENODEV;	SET_MODULE_OWNER(dev);	/* start address of 1 --> forced detection */	if (dev->mem_start == 1)		force_detect = 1;	/* search through slots */	if (dev != NULL) {		base = dev->mem_start;		irq = dev->irq;	}	slot = dofind(&junior, startslot);	while (slot != -1) {		/* deduce card addresses */		getaddrs(slot, junior, &base, &irq, &medium);#if LINUX_VERSION_CODE >= 0x020300		/* slot already in use ? */		if (mca_is_adapter_used(slot)) {			slot = dofind(&junior, slot + 1);			continue;		}#endif		/* were we looking for something different ? */		if ((dev->irq != 0) || (dev->mem_start != 0)) {			if ((dev->irq != 0) && (dev->irq != irq)) {				slot = dofind(&junior, slot + 1);				continue;			}			if ((dev->mem_start != 0)			    && (dev->mem_start != base)) {				slot = dofind(&junior, slot + 1);				continue;			}		}		/* found something that matches */		break;	}	/* nothing found ? */	if (slot == -1)		return ((base != 0) || (irq != 0)) ? ENXIO : ENODEV;	/* make procfs entries */	if (junior)		mca_set_adapter_name(slot,				     "SKNET junior MC2 Ethernet Adapter");	else		mca_set_adapter_name(slot, "SKNET MC2+ Ethernet Adapter");	mca_set_adapter_procfn(slot, (MCA_ProcFn) skmca_getinfo, dev);#if LINUX_VERSION_CODE >= 0x020200	mca_mark_as_used(slot);#endif	/* announce success */	printk("%s: SKNet %s adapter found in slot %d\n", dev->name,	       junior ? "Junior MC2" : "MC2+", slot + 1);	/* allocate structure */	priv = dev->priv =	    (skmca_priv *) kmalloc(sizeof(skmca_priv), GFP_KERNEL);	priv->slot = slot;	priv->macbase = base + 0x3fc0;	priv->ioregaddr = base + 0x3ff0;	priv->ctrladdr = base + 0x3ff2;	priv->cmdaddr = base + 0x3ff3;	priv->medium = medium;	memset(&(priv->stat), 0, sizeof(struct net_device_stats));	/* set base + irq for this device (irq not allocated so far) */	dev->irq = 0;	dev->mem_start = base;	dev->mem_end = base + 0x4000;	/* autoprobe ? */	if (irq < 0) {		int nirq;		printk		    ("%s: ambigous POS bit combination, must probe for IRQ...\n",		     dev->name);		nirq = ProbeIRQ(dev);		if (nirq <= 0)			printk("%s: IRQ probe failed, assuming IRQ %d",			       dev->name, priv->realirq = -irq);		else			priv->realirq = nirq;	} else		priv->realirq = irq;	/* set methods */	dev->open = skmca_open;	dev->stop = skmca_close;	dev->set_config = skmca_config;	dev->hard_start_xmit = skmca_tx;	dev->do_ioctl = NULL;	dev->get_stats = skmca_stats;	dev->set_multicast_list = skmca_set_multicast_list;	dev->flags |= IFF_MULTICAST;	/* generic setup */	ether_setup(dev);	/* copy out MAC address */	for (i = 0; i < 6; i++)		dev->dev_addr[i] = SKMCA_READB(priv->macbase + (i << 1));	/* print config */	printk("%s: IRQ %d, memory %#lx-%#lx, "	       "MAC address %02x:%02x:%02x:%02x:%02x:%02x.\n",	       dev->name, priv->realirq, dev->mem_start, dev->mem_end - 1,	       dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],	       dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);	printk("%s: %s medium\n", dev->name, MediaNames[priv->medium]);	/* reset board */	ResetBoard(dev);	startslot = slot + 1;	return 0;}/* ------------------------------------------------------------------------ * modularization support * ------------------------------------------------------------------------ */#ifdef MODULE#define DEVMAX 5#if (LINUX_VERSION_CODE >= 0x020369)static struct SKMCA_NETDEV moddevs[DEVMAX] =    { {"    ", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},{"    ", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},{"    ", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},{"    ", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},{"    ", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe}};#elsestatic char NameSpace[8 * DEVMAX];static struct SKMCA_NETDEV moddevs[DEVMAX] =    { {NameSpace + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},{NameSpace + 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},{NameSpace + 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},{NameSpace + 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},{NameSpace + 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe}};#endifint irq = 0;int io = 0;int init_module(void){	int z, res;	startslot = 0;	for (z = 0; z < DEVMAX; z++) {		strcpy(moddevs[z].name, "     ");		res = register_netdev(moddevs + z);		if (res != 0)			return (z > 0) ? 0 : -EIO;	}	return 0;}void cleanup_module(void){	struct SKMCA_NETDEV *dev;	skmca_priv *priv;	int z;	if (MOD_IN_USE) {		printk("cannot unload, module in use\n");		return;	}	for (z = 0; z < DEVMAX; z++) {		dev = moddevs + z;		if (dev->priv != NULL) {			priv = (skmca_priv *) dev->priv;			DeinitBoard(dev);			if (dev->irq != 0)				free_irq(dev->irq, dev);			dev->irq = 0;			unregister_netdev(dev);#if LINUX_VERSION_CODE >= 0x020200			mca_mark_as_unused(priv->slot);#endif			mca_set_adapter_procfn(priv->slot, NULL, NULL);			kfree(dev->priv);			dev->priv = NULL;		}	}}#endif				/* MODULE */

⌨️ 快捷键说明

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