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

📄 sonic.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * sonic.c * * (C) 1996,1998 by Thomas Bogendoerfer (tsbogend@alpha.franken.de) *  * This driver is based on work from Andreas Busse, but most of * the code is rewritten. *  * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de) * *    Core code included by system sonic drivers *//* * Sources: Olivetti M700-10 Risc Personal Computer hardware handbook, * National Semiconductors data sheet for the DP83932B Sonic Ethernet * controller, and the files "8390.c" and "skeleton.c" in this directory. *//* * Open/initialize the SONIC controller. * * This routine should set everything up anew at each open, even *  registers that "should" only need to be set once at boot, so that *  there is non-reboot way to recover if something goes wrong. */static int sonic_open(struct net_device *dev){	if (sonic_debug > 2)		printk("sonic_open: initializing sonic driver.\n");	/*	 * We don't need to deal with auto-irq stuff since we	 * hardwire the sonic interrupt.	 *//* * XXX Horrible work around:  We install sonic_interrupt as fast interrupt. * This means that during execution of the handler interrupt are disabled * covering another bug otherwise corrupting data.  This doesn't mean * this glue works ok under all situations. *///    if (sonic_request_irq(dev->irq, &sonic_interrupt, 0, "sonic", dev)) {	if (sonic_request_irq(dev->irq, &sonic_interrupt, SA_INTERRUPT,	                      "sonic", dev)) {		printk("\n%s: unable to get IRQ %d .\n", dev->name, dev->irq);		return -EAGAIN;	}	/*	 * Initialize the SONIC	 */	sonic_init(dev);	netif_start_queue(dev);	if (sonic_debug > 2)		printk("sonic_open: Initialization done.\n");	return 0;}/* * Close the SONIC device */static int sonic_close(struct net_device *dev){	unsigned int base_addr = dev->base_addr;	if (sonic_debug > 2)		printk("sonic_close\n");	netif_stop_queue(dev);	/*	 * stop the SONIC, disable interrupts	 */	SONIC_WRITE(SONIC_ISR, 0x7fff);	SONIC_WRITE(SONIC_IMR, 0);	SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);	sonic_free_irq(dev->irq, dev);	/* release the IRQ */	return 0;}static void sonic_tx_timeout(struct net_device *dev){	struct sonic_local *lp = (struct sonic_local *) dev->priv;	printk("%s: transmit timed out.\n", dev->name);	/* Try to restart the adaptor. */	sonic_init(dev);	lp->stats.tx_errors++;	dev->trans_start = jiffies;	netif_wake_queue(dev);}/* * transmit packet */static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev){	struct sonic_local *lp = (struct sonic_local *) dev->priv;	unsigned int base_addr = dev->base_addr;	unsigned int laddr;	int entry, length;	netif_stop_queue(dev);	if (sonic_debug > 2)		printk("sonic_send_packet: skb=%p, dev=%p\n", skb, dev);	/* 	 * Block a timer-based transmit from overlapping.  This could better be	 * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.	 */	if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) {		printk("%s: Transmitter access conflict.\n", dev->name);		return 1;	}	/*	 * Map the packet data into the logical DMA address space	 */	if ((laddr = vdma_alloc(PHYSADDR(skb->data), skb->len)) == ~0UL) {		printk("%s: no VDMA entry for transmit available.\n",		       dev->name);		dev_kfree_skb(skb);		netif_start_queue(dev);		return 1;	}	entry = lp->cur_tx & SONIC_TDS_MASK;	lp->tx_laddr[entry] = laddr;	lp->tx_skb[entry] = skb;	length = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;	flush_cache_all();	/*	 * Setup the transmit descriptor and issue the transmit command.	 */	lp->tda[entry].tx_status = 0;	/* clear status */	lp->tda[entry].tx_frag_count = 1;	/* single fragment */	lp->tda[entry].tx_pktsize = length;	/* length of packet */	lp->tda[entry].tx_frag_ptr_l = laddr & 0xffff;	lp->tda[entry].tx_frag_ptr_h = laddr >> 16;	lp->tda[entry].tx_frag_size = length;	lp->cur_tx++;	lp->stats.tx_bytes += length;	if (sonic_debug > 2)		printk("sonic_send_packet: issueing Tx command\n");	SONIC_WRITE(SONIC_CMD, SONIC_CR_TXP);	dev->trans_start = jiffies;	if (lp->cur_tx < lp->dirty_tx + SONIC_NUM_TDS)		netif_start_queue(dev);	else		lp->tx_full = 1;	return 0;}/* * The typical workload of the driver: * Handle the network interface interrupts. */static void sonic_interrupt(int irq, void *dev_id, struct pt_regs *regs){	struct net_device *dev = (struct net_device *) dev_id;	unsigned int base_addr = dev->base_addr;	struct sonic_local *lp;	int status;	if (dev == NULL) {		printk("sonic_interrupt: irq %d for unknown device.\n", irq);		return;	}	lp = (struct sonic_local *) dev->priv;	status = SONIC_READ(SONIC_ISR);	SONIC_WRITE(SONIC_ISR, 0x7fff);	/* clear all bits */	if (sonic_debug > 2)		printk("sonic_interrupt: ISR=%x\n", status);	if (status & SONIC_INT_PKTRX) {		sonic_rx(dev);	/* got packet(s) */	}	if (status & SONIC_INT_TXDN) {		int dirty_tx = lp->dirty_tx;		while (dirty_tx < lp->cur_tx) {			int entry = dirty_tx & SONIC_TDS_MASK;			int status = lp->tda[entry].tx_status;			if (sonic_debug > 3)				printk				    ("sonic_interrupt: status %d, cur_tx %d, dirty_tx %d\n",				     status, lp->cur_tx, lp->dirty_tx);			if (status == 0) {				/* It still hasn't been Txed, kick the sonic again */				SONIC_WRITE(SONIC_CMD, SONIC_CR_TXP);				break;			}			/* put back EOL and free descriptor */			lp->tda[entry].tx_frag_count = 0;			lp->tda[entry].tx_status = 0;			if (status & 0x0001)				lp->stats.tx_packets++;			else {				lp->stats.tx_errors++;				if (status & 0x0642)					lp->stats.tx_aborted_errors++;				if (status & 0x0180)					lp->stats.tx_carrier_errors++;				if (status & 0x0020)					lp->stats.tx_window_errors++;				if (status & 0x0004)					lp->stats.tx_fifo_errors++;			}			/* We must free the original skb */			if (lp->tx_skb[entry]) {				dev_kfree_skb(lp->tx_skb[entry]);				lp->tx_skb[entry] = 0;			}			/* and the VDMA address */			vdma_free(lp->tx_laddr[entry]);			dirty_tx++;		}		if (lp->tx_full		    && dirty_tx + SONIC_NUM_TDS > lp->cur_tx + 2) {			/* The ring is no longer full, clear tbusy. */			lp->tx_full = 0;			netif_wake_queue(dev);		}		lp->dirty_tx = dirty_tx;	}	/*	 * check error conditions	 */	if (status & SONIC_INT_RFO) {		printk("%s: receive fifo underrun\n", dev->name);		lp->stats.rx_fifo_errors++;	}	if (status & SONIC_INT_RDE) {		printk("%s: receive descriptors exhausted\n", dev->name);		lp->stats.rx_dropped++;	}	if (status & SONIC_INT_RBE) {		printk("%s: receive buffer exhausted\n", dev->name);		lp->stats.rx_dropped++;	}	if (status & SONIC_INT_RBAE) {		printk("%s: receive buffer area exhausted\n", dev->name);		lp->stats.rx_dropped++;	}	/* counter overruns; all counters are 16bit wide */	if (status & SONIC_INT_FAE)		lp->stats.rx_frame_errors += 65536;	if (status & SONIC_INT_CRC)		lp->stats.rx_crc_errors += 65536;	if (status & SONIC_INT_MP)		lp->stats.rx_missed_errors += 65536;	/* transmit error */	if (status & SONIC_INT_TXER)		lp->stats.tx_errors++;	/*	 * clear interrupt bits and return	 */	SONIC_WRITE(SONIC_ISR, status);}/* * We have a good packet(s), get it/them out of the buffers. */static void sonic_rx(struct net_device *dev){	unsigned int base_addr = dev->base_addr;	struct sonic_local *lp = (struct sonic_local *) dev->priv;	sonic_rd_t *rd = &lp->rda[lp->cur_rx & SONIC_RDS_MASK];	int status;	while (rd->in_use == 0) {		struct sk_buff *skb;		int pkt_len;		unsigned char *pkt_ptr;		status = rd->rx_status;		if (sonic_debug > 3)			printk("status %x, cur_rx %d, cur_rra %x\n",			       status, lp->cur_rx, lp->cur_rra);		if (status & SONIC_RCR_PRX) {			pkt_len = rd->rx_pktlen;			pkt_ptr =

⌨️ 快捷键说明

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