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

📄 3c523.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
	p->rfd_last = p->rfd_first + p->num_recv_buffs - 1;	p->scb->rfa_offset = make16(p->rfd_first);	p->rfd_first->rbd_offset = make16(rbd);	return ptr;}/************************************************** * Interrupt Handler ... */static void elmc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr){	struct device *dev = (struct device *) dev_id;	unsigned short stat;	struct priv *p;	if (dev == NULL) {		printk("elmc-interrupt: irq %d for unknown device.\n", (int) -(((struct pt_regs *) reg_ptr)->orig_eax + 2));		return;	} else if (!dev->start) {		/* The 3c523 has this habit of generating interrupts during the		   reset.  I'm not sure if the ni52 has this same problem, but it's		   really annoying if we haven't finished initializing it.  I was		   hoping all the elmc_id_* commands would disable this, but I		   might have missed a few. */		elmc_id_attn586();	/* ack inter. and disable any more */		return;	} else if (!(ELMC_CTRL_INT & inb(dev->base_addr + ELMC_CTRL))) {		/* wasn't this device */		return;	}	/* reading ELMC_CTRL also clears the INT bit. */	p = (struct priv *) dev->priv;	dev->interrupt = 1;	while ((stat = p->scb->status & STAT_MASK)) 	{		p->scb->cmd = stat;		elmc_attn586();	/* ack inter. */		if (stat & STAT_CX) {			/* command with I-bit set complete */			elmc_xmt_int(dev);		}		if (stat & STAT_FR) {			/* received a frame */			elmc_rcv_int(dev);		}#ifndef NO_NOPCOMMANDS		if (stat & STAT_CNA) {			/* CU went 'not ready' */			if (dev->start) {				printk("%s: oops! CU has left active state. stat: %04x/%04x.\n", dev->name, (int) stat, (int) p->scb->status);			}		}#endif		if (stat & STAT_RNR) {			/* RU went 'not ready' */			if (p->scb->status & RU_SUSPEND) {				/* special case: RU_SUSPEND */				WAIT_4_SCB_CMD();				p->scb->cmd = RUC_RESUME;				elmc_attn586();			} else {				printk("%s: Receiver-Unit went 'NOT READY': %04x/%04x.\n", dev->name, (int) stat, (int) p->scb->status);				elmc_rnr_int(dev);			}		}		WAIT_4_SCB_CMD();	/* wait for ack. (elmc_xmt_int can be faster than ack!!) */		if (p->scb->cmd) {	/* timed out? */			break;		}	}	dev->interrupt = 0;}/******************************************************* * receive-interrupt */static void elmc_rcv_int(struct device *dev){	int status;	unsigned short totlen;	struct sk_buff *skb;	struct rbd_struct *rbd;	struct priv *p = (struct priv *) dev->priv;	for (; (status = p->rfd_top->status) & STAT_COMPL;) {		rbd = (struct rbd_struct *) make32(p->rfd_top->rbd_offset);		if (status & STAT_OK) {		/* frame received without error? */			if ((totlen = rbd->status) & RBD_LAST) {	/* the first and the last buffer? */				totlen &= RBD_MASK;	/* length of this frame */				rbd->status = 0;				skb = (struct sk_buff *) dev_alloc_skb(totlen + 2);				if (skb != NULL) {					skb->dev = dev;					skb_reserve(skb, 2);	/* 16 byte alignment */					memcpy(skb_put(skb, totlen), (u8 *)phys_to_virt(p->base) + (unsigned long) rbd->buffer, totlen);					skb->protocol = eth_type_trans(skb, dev);					netif_rx(skb);					p->stats.rx_packets++;					p->stats.rx_bytes += totlen;				} else {					p->stats.rx_dropped++;				}			} else {				printk("%s: received oversized frame.\n", dev->name);				p->stats.rx_dropped++;			}		} else {	/* frame !(ok), only with 'save-bad-frames' */			printk("%s: oops! rfd-error-status: %04x\n", dev->name, status);			p->stats.rx_errors++;		}		p->rfd_top->status = 0;		p->rfd_top->last = RFD_SUSP;		p->rfd_last->last = 0;	/* delete RU_SUSP  */		p->rfd_last = p->rfd_top;		p->rfd_top = (struct rfd_struct *) make32(p->rfd_top->next);	/* step to next RFD */	}}/********************************************************** * handle 'Receiver went not ready'. */static void elmc_rnr_int(struct device *dev){	struct priv *p = (struct priv *) dev->priv;	p->stats.rx_errors++;	WAIT_4_SCB_CMD();	/* wait for the last cmd */	p->scb->cmd = RUC_ABORT;	/* usually the RU is in the 'no resource'-state .. abort it now. */	elmc_attn586();	WAIT_4_SCB_CMD();	/* wait for accept cmd. */	alloc_rfa(dev, (char *) p->rfd_first);	startrecv586(dev);	/* restart RU */	printk("%s: Receive-Unit restarted. Status: %04x\n", dev->name, p->scb->status);}/********************************************************** * handle xmit - interrupt */static void elmc_xmt_int(struct device *dev){	int status;	struct priv *p = (struct priv *) dev->priv;	status = p->xmit_cmds[p->xmit_last]->cmd_status;	if (!(status & STAT_COMPL)) {		printk("%s: strange .. xmit-int without a 'COMPLETE'\n", dev->name);	}	if (status & STAT_OK) {		p->stats.tx_packets++;		p->stats.collisions += (status & TCMD_MAXCOLLMASK);	} else {		p->stats.tx_errors++;		if (status & TCMD_LATECOLL) {			printk("%s: late collision detected.\n", dev->name);			p->stats.collisions++;		} else if (status & TCMD_NOCARRIER) {			p->stats.tx_carrier_errors++;			printk("%s: no carrier detected.\n", dev->name);		} else if (status & TCMD_LOSTCTS) {			printk("%s: loss of CTS detected.\n", dev->name);		} else if (status & TCMD_UNDERRUN) {			p->stats.tx_fifo_errors++;			printk("%s: DMA underrun detected.\n", dev->name);		} else if (status & TCMD_MAXCOLL) {			printk("%s: Max. collisions exceeded.\n", dev->name);			p->stats.collisions += 16;		}	}#if (NUM_XMIT_BUFFS != 1)	if ((++p->xmit_last) == NUM_XMIT_BUFFS) {		p->xmit_last = 0;	}#endif	dev->tbusy = 0;	mark_bh(NET_BH);}/*********************************************************** * (re)start the receiver */static void startrecv586(struct device *dev){	struct priv *p = (struct priv *) dev->priv;	p->scb->rfa_offset = make16(p->rfd_first);	p->scb->cmd = RUC_START;	elmc_attn586();		/* start cmd. */	WAIT_4_SCB_CMD();	/* wait for accept cmd. (no timeout!!) */}/****************************************************** * send frame */static int elmc_send_packet(struct sk_buff *skb, struct device *dev){	int len;#ifndef NO_NOPCOMMANDS	int next_nop;#endif	struct priv *p = (struct priv *) dev->priv;	if (dev->tbusy) {		int tickssofar = jiffies - dev->trans_start;		if (tickssofar < 5) {			return 1;		}		/* COMMAND-UNIT active? */		if (p->scb->status & CU_ACTIVE) {			dev->tbusy = 0;#ifdef DEBUG			printk("%s: strange ... timeout with CU active?!?\n", dev->name);			printk("%s: X0: %04x N0: %04x N1: %04x %d\n", dev->name, (int) p->xmit_cmds[0]->cmd_status, (int) p->nop_cmds[0]->cmd_status, (int) p->nop_cmds[1]->cmd_status, (int) p->nop_point);#endif			p->scb->cmd = CUC_ABORT;			elmc_attn586();			WAIT_4_SCB_CMD();			p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]);			p->scb->cmd = CUC_START;			elmc_attn586();			WAIT_4_SCB_CMD();			dev->trans_start = jiffies;			return 0;		} else {#ifdef DEBUG			printk("%s: xmitter timed out, try to restart! stat: %04x\n", dev->name, p->scb->status);			printk("%s: command-stats: %04x %04x\n", dev->name, p->xmit_cmds[0]->cmd_status, p->xmit_cmds[1]->cmd_status);#endif			elmc_close(dev);			elmc_open(dev);		}		dev->trans_start = jiffies;		return 0;	}	if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) {		printk("%s: Transmitter access conflict.\n", dev->name);	} else {		memcpy((char *) p->xmit_cbuffs[p->xmit_count], (char *) (skb->data), skb->len);		len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;#if (NUM_XMIT_BUFFS == 1)#ifdef NO_NOPCOMMANDS		p->xmit_buffs[0]->size = TBD_LAST | len;		for (i = 0; i < 16; i++) {			p->scb->cbl_offset = make16(p->xmit_cmds[0]);			p->scb->cmd = CUC_START;			p->xmit_cmds[0]->cmd_status = 0;			elmc_attn586();			dev->trans_start = jiffies;			if (!i) {				dev_kfree_skb(skb);			}			WAIT_4_SCB_CMD();			if ((p->scb->status & CU_ACTIVE)) {	/* test it, because CU sometimes doesn't start immediately */				break;			}			if (p->xmit_cmds[0]->cmd_status) {				break;			}			if (i == 15) {				printk("%s: Can't start transmit-command.\n", dev->name);			}		}#else		next_nop = (p->nop_point + 1) & 0x1;		p->xmit_buffs[0]->size = TBD_LAST | len;		p->xmit_cmds[0]->cmd_link = p->nop_cmds[next_nop]->cmd_link		    = make16((p->nop_cmds[next_nop]));		p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0;		p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0]));		dev->trans_start = jiffies;		p->nop_point = next_nop;		dev_kfree_skb(skb);#endif#else		p->xmit_buffs[p->xmit_count]->size = TBD_LAST | len;		if ((next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS) {			next_nop = 0;		}		p->xmit_cmds[p->xmit_count]->cmd_status = 0;		p->xmit_cmds[p->xmit_count]->cmd_link = p->nop_cmds[next_nop]->cmd_link		    = make16((p->nop_cmds[next_nop]));		p->nop_cmds[next_nop]->cmd_status = 0;		p->nop_cmds[p->xmit_count]->cmd_link = make16((p->xmit_cmds[p->xmit_count]));		dev->trans_start = jiffies;		p->xmit_count = next_nop;		cli();		if (p->xmit_count != p->xmit_last) {			dev->tbusy = 0;		}		sti();		dev_kfree_skb(skb);#endif	}	return 0;}/******************************************* * Someone wanna have the statistics */static struct net_device_stats *elmc_get_stats(struct device *dev){	struct priv *p = (struct priv *) dev->priv;	unsigned short crc, aln, rsc, ovrn;	crc = p->scb->crc_errs;	/* get error-statistic from the ni82586 */	p->scb->crc_errs -= crc;	aln = p->scb->aln_errs;	p->scb->aln_errs -= aln;	rsc = p->scb->rsc_errs;	p->scb->rsc_errs -= rsc;	ovrn = p->scb->ovrn_errs;	p->scb->ovrn_errs -= ovrn;	p->stats.rx_crc_errors += crc;	p->stats.rx_fifo_errors += ovrn;	p->stats.rx_frame_errors += aln;	p->stats.rx_dropped += rsc;	return &p->stats;}/******************************************************** * Set MC list .. */static void set_multicast_list(struct device *dev){	if (!dev->start) {		/* without a running interface, promiscuous doesn't work */		return;	}	dev->start = 0;	alloc586(dev);	init586(dev);	startrecv586(dev);	dev->start = 1;}/*************************************************************************/#ifdef MODULEstatic char devicename[9] = {0,};static struct device dev_elmc ={	devicename /*"3c523" */ , 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, elmc_probe};static int irq = 0;static int io = 0;MODULE_PARM(irq, "i");MODULE_PARM(io, "i");int init_module(void){	struct device *dev = &dev_elmc;	dev->base_addr = io;	dev->irq = irq;	if (register_netdev(dev) != 0) {		return -EIO;	}	return 0;}void cleanup_module(void){	struct device *dev = &dev_elmc;	/* shutdown interrupts on the card */	elmc_id_reset586();	if (dev->irq != 0) {		/* this should be done by close, but if we failed to		   initialize properly something may have gotten hosed. */		free_irq(dev->irq, dev);		dev->irq = 0;	}	if (dev->base_addr != 0) {		release_region(dev->base_addr, ELMC_IO_EXTENT);		dev->base_addr = 0;	}	irq = 0;	io = 0;	unregister_netdev(dev);	mca_set_adapter_procfn(((struct priv *) (dev->priv))->slot,			       NULL, NULL);	kfree_s(dev->priv, sizeof(struct priv));	dev->priv = NULL;}#endif				/* MODULE */

⌨️ 快捷键说明

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