欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

ewrk3.c

linux 内核源代码
C
第 1 页 / 共 4 页
字号:
	** Determine the base address and window length for the EWRK3	** RAM from the memory base register.	*/	mem_start = inb(EWRK3_MBR);	shmem_length = 0;	if (mem_start != 0) {		if ((mem_start >= 0x0a) && (mem_start <= 0x0f)) {			mem_start *= SHMEM_64K;			shmem_length = SHMEM_64K;		} else if ((mem_start >= 0x14) && (mem_start <= 0x1f)) {			mem_start *= SHMEM_32K;			shmem_length = SHMEM_32K;		} else if ((mem_start >= 0x40) && (mem_start <= 0xff)) {			mem_start = mem_start * SHMEM_2K + 0x80000;			shmem_length = SHMEM_2K;		} else {			return -ENXIO;		}	}	/*	** See the top of this source code for comments about	** uncommenting this line.	*//*          FORCE_2K_MODE; */	if (hard_strapped) {		printk("      is hard strapped.\n");	} else if (mem_start) {		printk("      has a %dk RAM window", (int) (shmem_length >> 10));		printk(" at 0x%.5lx", mem_start);	} else {		printk("      is in I/O only mode");	}	lp = netdev_priv(dev);	lp->shmem_base = mem_start;	lp->shmem = ioremap(mem_start, shmem_length);	if (!lp->shmem)		return -ENOMEM;	lp->shmem_length = shmem_length;	lp->lemac = lemac;	lp->hard_strapped = hard_strapped;	lp->led_mask = CR_LED;	spin_lock_init(&lp->hw_lock);	lp->mPage = 64;	if (cmr & CMR_DRAM)		lp->mPage <<= 1;	/* 2 DRAMS on module */	sprintf(lp->adapter_name, "%s (%s)", name, dev->name);	lp->irq_mask = ICR_TNEM | ICR_TXDM | ICR_RNEM | ICR_RXDM;	if (!hard_strapped) {		/*		** Enable EWRK3 board interrupts for autoprobing		*/		icr |= ICR_IE;	/* Enable interrupts */		outb(icr, EWRK3_ICR);		/* The DMA channel may be passed in on this parameter. */		dev->dma = 0;		/* To auto-IRQ we enable the initialization-done and DMA err,		   interrupts. For now we will always get a DMA error. */		if (dev->irq < 2) {#ifndef MODULE			u_char irqnum;			unsigned long irq_mask;			irq_mask = probe_irq_on();			/*			** Trigger a TNE interrupt.			*/			icr |= ICR_TNEM;			outb(1, EWRK3_TDQ);	/* Write to the TX done queue */			outb(icr, EWRK3_ICR);	/* Unmask the TXD interrupt */			irqnum = irq[((icr & IRQ_SEL) >> 4)];			mdelay(20);			dev->irq = probe_irq_off(irq_mask);			if ((dev->irq) && (irqnum == dev->irq)) {				printk(" and uses IRQ%d.\n", dev->irq);			} else {				if (!dev->irq) {					printk(" and failed to detect IRQ line.\n");				} else if ((irqnum == 1) && (lemac == LeMAC2)) {					printk(" and an illegal IRQ line detected.\n");				} else {					printk(", but incorrect IRQ line detected.\n");				}				iounmap(lp->shmem);				return -ENXIO;			}			DISABLE_IRQs;	/* Mask all interrupts */#endif				/* MODULE */		} else {			printk(" and requires IRQ%d.\n", dev->irq);		}	}	if (ewrk3_debug > 1) {		printk(version);	}	/* The EWRK3-specific entries in the device structure. */	dev->open = ewrk3_open;	dev->hard_start_xmit = ewrk3_queue_pkt;	dev->stop = ewrk3_close;	dev->set_multicast_list = set_multicast_list;	dev->do_ioctl = ewrk3_ioctl;	if (lp->adapter_name[4] == '3')		SET_ETHTOOL_OPS(dev, &ethtool_ops_203);	else		SET_ETHTOOL_OPS(dev, &ethtool_ops);	dev->tx_timeout = ewrk3_timeout;	dev->watchdog_timeo = QUEUE_PKT_TIMEOUT;	dev->mem_start = 0;	return 0;}static int ewrk3_open(struct net_device *dev){	struct ewrk3_private *lp = netdev_priv(dev);	u_long iobase = dev->base_addr;	int status = 0;	u_char icr, csr;	/*	   ** Stop the TX and RX...	 */	STOP_EWRK3;	if (!lp->hard_strapped) {		if (request_irq(dev->irq, (void *) ewrk3_interrupt, 0, "ewrk3", dev)) {			printk("ewrk3_open(): Requested IRQ%d is busy\n", dev->irq);			status = -EAGAIN;		} else {			/*			   ** Re-initialize the EWRK3...			 */			ewrk3_init(dev);			if (ewrk3_debug > 1) {				DECLARE_MAC_BUF(mac);				printk("%s: ewrk3 open with irq %d\n", dev->name, dev->irq);				printk("  physical address: %s\n",				       print_mac(mac, dev->dev_addr));				if (lp->shmem_length == 0) {					printk("  no shared memory, I/O only mode\n");				} else {					printk("  start of shared memory: 0x%08lx\n", lp->shmem_base);					printk("  window length: 0x%04lx\n", lp->shmem_length);				}				printk("  # of DRAMS: %d\n", ((inb(EWRK3_CMR) & 0x02) ? 2 : 1));				printk("  csr:  0x%02x\n", inb(EWRK3_CSR));				printk("  cr:   0x%02x\n", inb(EWRK3_CR));				printk("  icr:  0x%02x\n", inb(EWRK3_ICR));				printk("  cmr:  0x%02x\n", inb(EWRK3_CMR));				printk("  fmqc: 0x%02x\n", inb(EWRK3_FMQC));			}			netif_start_queue(dev);			/*			   ** Unmask EWRK3 board interrupts			 */			icr = inb(EWRK3_ICR);			ENABLE_IRQs;		}	} else {		printk(KERN_ERR "%s: ewrk3 available for hard strapped set up only.\n", dev->name);		printk(KERN_ERR "      Run the 'ewrk3setup' utility or remove the hard straps.\n");		return -EINVAL;	}	return status;}/*   ** Initialize the EtherWORKS 3 operating conditions */static void ewrk3_init(struct net_device *dev){	struct ewrk3_private *lp = netdev_priv(dev);	u_char csr, page;	u_long iobase = dev->base_addr;	int i;	/*	   ** Enable any multicasts	 */	set_multicast_list(dev);	/*	** Set hardware MAC address. Address is initialized from the EEPROM	** during startup but may have since been changed by the user.	*/	for (i=0; i<ETH_ALEN; i++)		outb(dev->dev_addr[i], EWRK3_PAR0 + i);	/*	   ** Clean out any remaining entries in all the queues here	 */	while (inb(EWRK3_TQ));	while (inb(EWRK3_TDQ));	while (inb(EWRK3_RQ));	while (inb(EWRK3_FMQ));	/*	   ** Write a clean free memory queue	 */	for (page = 1; page < lp->mPage; page++) {	/* Write the free page numbers */		outb(page, EWRK3_FMQ);	/* to the Free Memory Queue */	}	START_EWRK3;		/* Enable the TX and/or RX */}/* *  Transmit timeout */static void ewrk3_timeout(struct net_device *dev){	struct ewrk3_private *lp = netdev_priv(dev);	u_char icr, csr;	u_long iobase = dev->base_addr;	if (!lp->hard_strapped)	{		printk(KERN_WARNING"%s: transmit timed/locked out, status %04x, resetting.\n",		       dev->name, inb(EWRK3_CSR));		/*		   ** Mask all board interrupts		 */		DISABLE_IRQs;		/*		   ** Stop the TX and RX...		 */		STOP_EWRK3;		ewrk3_init(dev);		/*		   ** Unmask EWRK3 board interrupts		 */		ENABLE_IRQs;		dev->trans_start = jiffies;		netif_wake_queue(dev);	}}/*   ** Writes a socket buffer to the free page queue */static int ewrk3_queue_pkt (struct sk_buff *skb, struct net_device *dev){	struct ewrk3_private *lp = netdev_priv(dev);	u_long iobase = dev->base_addr;	void __iomem *buf = NULL;	u_char icr;	u_char page;	spin_lock_irq (&lp->hw_lock);	DISABLE_IRQs;	/* if no resources available, exit, request packet be queued */	if (inb (EWRK3_FMQC) == 0) {		printk (KERN_WARNING "%s: ewrk3_queue_pkt(): No free resources...\n",			dev->name);		printk (KERN_WARNING "%s: ewrk3_queue_pkt(): CSR: %02x ICR: %02x FMQC: %02x\n",			dev->name, inb (EWRK3_CSR), inb (EWRK3_ICR),			inb (EWRK3_FMQC));		goto err_out;	}	/*	 ** Get a free page from the FMQ	 */	if ((page = inb (EWRK3_FMQ)) >= lp->mPage) {		printk ("ewrk3_queue_pkt(): Invalid free memory page (%d).\n",		     (u_char) page);		goto err_out;	}	/*	 ** Set up shared memory window and pointer into the window	 */	if (lp->shmem_length == IO_ONLY) {		outb (page, EWRK3_IOPR);	} else if (lp->shmem_length == SHMEM_2K) {		buf = lp->shmem;		outb (page, EWRK3_MPR);	} else if (lp->shmem_length == SHMEM_32K) {		buf = (((short) page << 11) & 0x7800) + lp->shmem;		outb ((page >> 4), EWRK3_MPR);	} else if (lp->shmem_length == SHMEM_64K) {		buf = (((short) page << 11) & 0xf800) + lp->shmem;		outb ((page >> 5), EWRK3_MPR);	} else {		printk (KERN_ERR "%s: Oops - your private data area is hosed!\n",			dev->name);		BUG ();	}	/*	 ** Set up the buffer control structures and copy the data from	 ** the socket buffer to the shared memory .	 */	if (lp->shmem_length == IO_ONLY) {		int i;		u_char *p = skb->data;		outb ((char) (TCR_QMODE | TCR_PAD | TCR_IFC), EWRK3_DATA);		outb ((char) (skb->len & 0xff), EWRK3_DATA);		outb ((char) ((skb->len >> 8) & 0xff), EWRK3_DATA);		outb ((char) 0x04, EWRK3_DATA);		for (i = 0; i < skb->len; i++) {			outb (*p++, EWRK3_DATA);		}		outb (page, EWRK3_TQ);	/* Start sending pkt */	} else {		writeb ((char) (TCR_QMODE | TCR_PAD | TCR_IFC), buf);	/* ctrl byte */		buf += 1;		writeb ((char) (skb->len & 0xff), buf);	/* length (16 bit xfer) */		buf += 1;		if (lp->txc) {			writeb(((skb->len >> 8) & 0xff) | XCT, buf);			buf += 1;			writeb (0x04, buf);	/* index byte */			buf += 1;			writeb (0x00, (buf + skb->len));	/* Write the XCT flag */			memcpy_toio (buf, skb->data, PRELOAD);	/* Write PRELOAD bytes */			outb (page, EWRK3_TQ);	/* Start sending pkt */			memcpy_toio (buf + PRELOAD,					 skb->data + PRELOAD,					 skb->len - PRELOAD);			writeb (0xff, (buf + skb->len));	/* Write the XCT flag */		} else {			writeb ((skb->len >> 8) & 0xff, buf);			buf += 1;			writeb (0x04, buf);	/* index byte */			buf += 1;			memcpy_toio (buf, skb->data, skb->len);	/* Write data bytes */			outb (page, EWRK3_TQ);	/* Start sending pkt */		}	}	ENABLE_IRQs;	spin_unlock_irq (&lp->hw_lock);	dev->stats.tx_bytes += skb->len;	dev->trans_start = jiffies;	dev_kfree_skb (skb);	/* Check for free resources: stop Tx queue if there are none */	if (inb (EWRK3_FMQC) == 0)		netif_stop_queue (dev);	return 0;err_out:	ENABLE_IRQs;	spin_unlock_irq (&lp->hw_lock);	return 1;}/*   ** The EWRK3 interrupt handler. */static irqreturn_t ewrk3_interrupt(int irq, void *dev_id){	struct net_device *dev = dev_id;	struct ewrk3_private *lp;	u_long iobase;	u_char icr, cr, csr;	lp = netdev_priv(dev);	iobase = dev->base_addr;	/* get the interrupt information */	csr = inb(EWRK3_CSR);	/*	 ** Mask the EWRK3 board interrupts and turn on the LED	 */	spin_lock(&lp->hw_lock);	DISABLE_IRQs;	cr = inb(EWRK3_CR);	cr |= lp->led_mask;	outb(cr, EWRK3_CR);	if (csr & CSR_RNE)	/* Rx interrupt (packet[s] arrived) */		ewrk3_rx(dev);	if (csr & CSR_TNE)	/* Tx interrupt (packet sent) */		ewrk3_tx(dev);	/*	 ** Now deal with the TX/RX disable flags. These are set when there	 ** are no more resources. If resources free up then enable these	 ** interrupts, otherwise mask them - failure to do this will result	 ** in the system hanging in an interrupt loop.	 */	if (inb(EWRK3_FMQC)) {	/* any resources available? */		lp->irq_mask |= ICR_TXDM | ICR_RXDM;	/* enable the interrupt source */		csr &= ~(CSR_TXD | CSR_RXD);	/* ensure restart of a stalled TX or RX */		outb(csr, EWRK3_CSR);		netif_wake_queue(dev);	} else {		lp->irq_mask &= ~(ICR_TXDM | ICR_RXDM);		/* disable the interrupt source */	}	/* Unmask the EWRK3 board interrupts and turn off the LED */	cr &= ~(lp->led_mask);	outb(cr, EWRK3_CR);	ENABLE_IRQs;	spin_unlock(&lp->hw_lock);	return IRQ_HANDLED;}/* Called with lp->hw_lock held */static int ewrk3_rx(struct net_device *dev){	struct ewrk3_private *lp = netdev_priv(dev);	u_long iobase = dev->base_addr;	int i, status = 0;	u_char page;	void __iomem *buf = NULL;	while (inb(EWRK3_RQC) && !status) {	/* Whilst there's incoming data */		if ((page = inb(EWRK3_RQ)) < lp->mPage) {	/* Get next entry's buffer page */			/*			   ** Set up shared memory window and pointer into the window			 */			if (lp->shmem_length == IO_ONLY) {				outb(page, EWRK3_IOPR);			} else if (lp->shmem_length == SHMEM_2K) {				buf = lp->shmem;				outb(page, EWRK3_MPR);			} else if (lp->shmem_length == SHMEM_32K) {				buf = (((short) page << 11) & 0x7800) + lp->shmem;				outb((page >> 4), EWRK3_MPR);			} else if (lp->shmem_length == SHMEM_64K) {				buf = (((short) page << 11) & 0xf800) + lp->shmem;				outb((page >> 5), EWRK3_MPR);			} else {				status = -1;				printk("%s: Oops - your private data area is hosed!\n", dev->name);			}			if (!status) {				char rx_status;				int pkt_len;				if (lp->shmem_length == IO_ONLY) {					rx_status = inb(EWRK3_DATA);					pkt_len = inb(EWRK3_DATA);					pkt_len |= ((u_short) inb(EWRK3_DATA) << 8);				} else {					rx_status = readb(buf);					buf += 1;					pkt_len = readw(buf);					buf += 3;				}				if (!(rx_status & R_ROK)) {	/* There was an error. */					dev->stats.rx_errors++;	/* Update the error stats. */					if (rx_status & R_DBE)						dev->stats.rx_frame_errors++;					if (rx_status & R_CRC)						dev->stats.rx_crc_errors++;					if (rx_status & R_PLL)						dev->stats.rx_fifo_errors++;				} else {					struct sk_buff *skb;					if ((skb = dev_alloc_skb(pkt_len + 2)) != NULL) {						unsigned char *p;						skb_reserve(skb, 2);	/* Align to 16 bytes */						p = skb_put(skb, pkt_len);						if (lp->shmem_length == IO_ONLY) {							*p = inb(EWRK3_DATA);	/* dummy read */

⌨️ 快捷键说明

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