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

📄 sk_mca.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	InitDscrs(dev);	/* next RX descriptor to be read is the first one.  Since the LANCE	   will start from the beginning after initialization, we have to 	   reset out pointers too. */	priv->nextrx = 0;	/* no TX descriptors active */	priv->nexttxput = priv->nexttxdone = priv->txbusy = 0;	/* set up the LANCE bus control register - constant for SKnet boards */	SetLANCE(dev, LANCE_CSR3,		 CSR3_BSWAP_OFF | CSR3_ALE_LOW | CSR3_BCON_HOLD);	/* write address of initialization block into LANCE */	SetLANCE(dev, LANCE_CSR1, RAM_INITBASE & 0xffff);	SetLANCE(dev, LANCE_CSR2, (RAM_INITBASE >> 16) & 0xff);	/* we don't get ready until the LANCE has read the init block */#if (LINUX_VERSION_CODE >= 0x02032a)	netif_stop_queue(dev);#else	dev->tbusy = 1;#endif	/* let LANCE read the initialization block.  LANCE is ready	   when we receive the corresponding interrupt. */	SetLANCE(dev, LANCE_CSR0, CSR0_INEA | CSR0_INIT);}/* stop the LANCE so we can reinitialize it */static void StopLANCE(struct SKMCA_NETDEV *dev){	/* can't take frames any more */#if (LINUX_VERSION_CODE >= 0x02032a)	netif_stop_queue(dev);#else	dev->tbusy = 1;#endif	/* disable interrupts, stop it */	SetLANCE(dev, LANCE_CSR0, CSR0_STOP);}/* initialize card and LANCE for proper operation */static void InitBoard(struct SKMCA_NETDEV *dev){	LANCE_InitBlock block;	/* Lay out the shared RAM - first we create the init block for the LANCE.	   We do not overwrite it later because we need it again when we switch	   promiscous mode on/off. */	block.Mode = 0;	if (dev->flags & IFF_PROMISC)		block.Mode |= LANCE_INIT_PROM;	memcpy(block.PAdr, dev->dev_addr, 6);	memset(block.LAdrF, 0, sizeof(block.LAdrF));	block.RdrP = (RAM_RXBASE & 0xffffff) | (LRXCOUNT << 29);	block.TdrP = (RAM_TXBASE & 0xffffff) | (LTXCOUNT << 29);	SKMCA_TOIO(dev->mem_start + RAM_INITBASE, &block, sizeof(block));	/* initialize LANCE. Implicitly sets up other structures in RAM. */	InitLANCE(dev);}/* deinitialize card and LANCE */static void DeinitBoard(struct SKMCA_NETDEV *dev){	/* stop LANCE */	StopLANCE(dev);	/* reset board */	ResetBoard(dev);}/* probe for device's irq */static int ProbeIRQ(struct SKMCA_NETDEV *dev){	unsigned long imaskval, njiffies, irq;	u16 csr0val;	/* enable all interrupts */	imaskval = probe_irq_on();	/* initialize the board. Wait for interrupt 'Initialization done'. */	ResetBoard(dev);	InitBoard(dev);	njiffies = jiffies + 100;	do {		csr0val = GetLANCE(dev, LANCE_CSR0);	}	while (((csr0val & CSR0_IDON) == 0) && (jiffies != njiffies));	/* turn of interrupts again */	irq = probe_irq_off(imaskval);	/* if we found something, ack the interrupt */	if (irq)		SetLANCE(dev, LANCE_CSR0, csr0val | CSR0_IDON);	/* back to idle state */	DeinitBoard(dev);	return irq;}/* ------------------------------------------------------------------------ * interrupt handler(s) * ------------------------------------------------------------------------ *//* LANCE has read initialization block -> start it */static u16 irqstart_handler(struct SKMCA_NETDEV *dev, u16 oldcsr0){	/* now we're ready to transmit */#if (LINUX_VERSION_CODE >= 0x02032a)	netif_wake_queue(dev);#else	dev->tbusy = 0;#endif	/* reset IDON bit, start LANCE */	SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_IDON | CSR0_STRT);	return GetLANCE(dev, LANCE_CSR0);}/* did we loose blocks due to a FIFO overrun ? */static u16 irqmiss_handler(struct SKMCA_NETDEV *dev, u16 oldcsr0){	skmca_priv *priv = (skmca_priv *) dev->priv;	/* update statistics */	priv->stat.rx_fifo_errors++;	/* reset MISS bit */	SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_MISS);	return GetLANCE(dev, LANCE_CSR0);}/* receive interrupt */static u16 irqrx_handler(struct SKMCA_NETDEV *dev, u16 oldcsr0){	skmca_priv *priv = (skmca_priv *) dev->priv;	LANCE_RxDescr descr;	unsigned int descraddr;	/* run through queue until we reach a descriptor we do not own */	descraddr = RAM_RXBASE + (priv->nextrx * sizeof(LANCE_RxDescr));	while (1) {		/* read descriptor */		SKMCA_FROMIO(&descr, dev->mem_start + descraddr,			     sizeof(LANCE_RxDescr));		/* if we reach a descriptor we do not own, we're done */		if ((descr.Flags & RXDSCR_FLAGS_OWN) != 0)			break;#ifdef DEBUG		PrTime();		printk("Receive packet on descr %d len %d\n", priv->nextrx,		       descr.Len);#endif		/* erroneous packet ? */		if ((descr.Flags & RXDSCR_FLAGS_ERR) != 0) {			priv->stat.rx_errors++;			if ((descr.Flags & RXDSCR_FLAGS_CRC) != 0)				priv->stat.rx_crc_errors++;			else if ((descr.Flags & RXDSCR_FLAGS_CRC) != 0)				priv->stat.rx_frame_errors++;			else if ((descr.Flags & RXDSCR_FLAGS_OFLO) != 0)				priv->stat.rx_fifo_errors++;		}		/* good packet ? */		else {			struct sk_buff *skb;			skb = dev_alloc_skb(descr.Len + 2);			if (skb == NULL)				priv->stat.rx_dropped++;			else {				SKMCA_FROMIO(skb_put(skb, descr.Len),					     dev->mem_start +					     descr.LowAddr, descr.Len);				skb->dev = dev;				skb->protocol = eth_type_trans(skb, dev);				skb->ip_summed = CHECKSUM_NONE;				priv->stat.rx_packets++;#if LINUX_VERSION_CODE >= 0x020119	/* byte counters for >= 2.1.25 */				priv->stat.rx_bytes += descr.Len;#endif				netif_rx(skb);			}		}		/* give descriptor back to LANCE */		descr.Len = 0;		descr.Flags |= RXDSCR_FLAGS_OWN;		/* update descriptor in shared RAM */		SKMCA_TOIO(dev->mem_start + descraddr, &descr,			   sizeof(LANCE_RxDescr));		/* go to next descriptor */		priv->nextrx++;		descraddr += sizeof(LANCE_RxDescr);		if (priv->nextrx >= RXCOUNT) {			priv->nextrx = 0;			descraddr = RAM_RXBASE;		}	}	/* reset RINT bit */	SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_RINT);	return GetLANCE(dev, LANCE_CSR0);}/* transmit interrupt */static u16 irqtx_handler(struct SKMCA_NETDEV *dev, u16 oldcsr0){	skmca_priv *priv = (skmca_priv *) dev->priv;	LANCE_TxDescr descr;	unsigned int descraddr;	/* check descriptors at most until no busy one is left */	descraddr =	    RAM_TXBASE + (priv->nexttxdone * sizeof(LANCE_TxDescr));	while (priv->txbusy > 0) {		/* read descriptor */		SKMCA_FROMIO(&descr, dev->mem_start + descraddr,			     sizeof(LANCE_TxDescr));		/* if the LANCE still owns this one, we've worked out all sent packets */		if ((descr.Flags & TXDSCR_FLAGS_OWN) != 0)			break;#ifdef DEBUG		PrTime();		printk("Send packet done on descr %d\n", priv->nexttxdone);#endif		/* update statistics */		if ((descr.Flags & TXDSCR_FLAGS_ERR) == 0) {			priv->stat.tx_packets++;#if LINUX_VERSION_CODE >= 0x020119	/* byte counters for >= 2.1.25 */			priv->stat.tx_bytes++;#endif		} else {			priv->stat.tx_errors++;			if ((descr.Status & TXDSCR_STATUS_UFLO) != 0) {				priv->stat.tx_fifo_errors++;				InitLANCE(dev);			}				else			    if ((descr.Status & TXDSCR_STATUS_LCOL) !=				0) priv->stat.tx_window_errors++;			else if ((descr.Status & TXDSCR_STATUS_LCAR) != 0)				priv->stat.tx_carrier_errors++;			else if ((descr.Status & TXDSCR_STATUS_RTRY) != 0)				priv->stat.tx_aborted_errors++;		}		/* go to next descriptor */		priv->nexttxdone++;		descraddr += sizeof(LANCE_TxDescr);		if (priv->nexttxdone >= TXCOUNT) {			priv->nexttxdone = 0;			descraddr = RAM_TXBASE;		}		priv->txbusy--;	}	/* reset TX interrupt bit */	SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_TINT);	oldcsr0 = GetLANCE(dev, LANCE_CSR0);	/* at least one descriptor is freed.  Therefore we can accept	   a new one */	/* inform upper layers we're in business again */#if (LINUX_VERSION_CODE >= 0x02032a)	netif_wake_queue(dev);#else	dev->tbusy = 0;	mark_bh(NET_BH);#endif	return oldcsr0;}/* general interrupt entry */static void irq_handler(int irq, void *device, struct pt_regs *regs){	struct SKMCA_NETDEV *dev = (struct SKMCA_NETDEV *) device;	u16 csr0val;	/* read CSR0 to get interrupt cause */	csr0val = GetLANCE(dev, LANCE_CSR0);	/* in case we're not meant... */	if ((csr0val & CSR0_INTR) == 0)		return;#if (LINUX_VERSION_CODE >= 0x02032a)#if 0	set_bit(LINK_STATE_RXSEM, &dev->state);#endif#else	dev->interrupt = 1;#endif	/* loop through the interrupt bits until everything is clear */	do {		if ((csr0val & CSR0_IDON) != 0)			csr0val = irqstart_handler(dev, csr0val);		if ((csr0val & CSR0_RINT) != 0)			csr0val = irqrx_handler(dev, csr0val);		if ((csr0val & CSR0_MISS) != 0)			csr0val = irqmiss_handler(dev, csr0val);		if ((csr0val & CSR0_TINT) != 0)			csr0val = irqtx_handler(dev, csr0val);		if ((csr0val & CSR0_MERR) != 0) {			SetLANCE(dev, LANCE_CSR0, csr0val | CSR0_MERR);			csr0val = GetLANCE(dev, LANCE_CSR0);		}		if ((csr0val & CSR0_BABL) != 0) {			SetLANCE(dev, LANCE_CSR0, csr0val | CSR0_BABL);			csr0val = GetLANCE(dev, LANCE_CSR0);		}	}	while ((csr0val & CSR0_INTR) != 0);#if (LINUX_VERSION_CODE >= 0x02032a)#if 0	clear_bit(LINK_STATE_RXSEM, &dev->state);#endif#else	dev->interrupt = 0;#endif}/* ------------------------------------------------------------------------ * driver methods * ------------------------------------------------------------------------ *//* MCA info */static int skmca_getinfo(char *buf, int slot, void *d){	int len = 0, i;	struct SKMCA_NETDEV *dev = (struct SKMCA_NETDEV *) d;	skmca_priv *priv;	/* can't say anything about an uninitialized device... */	if (dev == NULL)		return len;	if (dev->priv == NULL)		return len;	priv = (skmca_priv *) dev->priv;	/* print info */	len += sprintf(buf + len, "IRQ: %d\n", priv->realirq);	len += sprintf(buf + len, "Memory: %#lx-%#lx\n", dev->mem_start,		       dev->mem_end - 1);	len +=	    sprintf(buf + len, "Transceiver: %s\n",		    MediaNames[priv->medium]);	len += sprintf(buf + len, "Device: %s\n", dev->name);	len += sprintf(buf + len, "MAC address:");	for (i = 0; i < 6; i++)		len += sprintf(buf + len, " %02x", dev->dev_addr[i]);	buf[len++] = '\n';	buf[len] = 0;	return len;}/* open driver.  Means also initialization and start of LANCE */static int skmca_open(struct SKMCA_NETDEV *dev){	int result;	skmca_priv *priv = (skmca_priv *) dev->priv;	/* register resources - only necessary for IRQ */	result =	    request_irq(priv->realirq, irq_handler,			SA_SHIRQ | SA_SAMPLE_RANDOM, "sk_mca", dev);	if (result != 0) {		printk("%s: failed to register irq %d\n", dev->name,		       dev->irq);		return result;

⌨️ 快捷键说明

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