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

📄 3c523.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	return ptr;}/************************************************** * Interrupt Handler ... */static void elmc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr){	struct net_device *dev = (struct net_device *) dev_id;	unsigned short stat;	struct priv *p;	if (dev == NULL) {		printk(KERN_ERR "elmc-interrupt: irq %d for unknown device.\n", (int) -(((struct pt_regs *) reg_ptr)->orig_eax + 2));		return;	} else if (!netif_running(dev)) {		/* 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;	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 (netif_running(dev)) {				printk(KERN_WARNING "%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(KERN_WARNING "%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;		}	}}/******************************************************* * receive-interrupt */static void elmc_rcv_int(struct net_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(KERN_WARNING "%s: received oversized frame.\n", dev->name);				p->stats.rx_dropped++;			}		} else {	/* frame !(ok), only with 'save-bad-frames' */			printk(KERN_WARNING "%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 net_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(KERN_WARNING "%s: Receive-Unit restarted. Status: %04x\n", dev->name, p->scb->status);}/********************************************************** * handle xmit - interrupt */static void elmc_xmt_int(struct net_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(KERN_WARNING "%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(KERN_WARNING "%s: late collision detected.\n", dev->name);			p->stats.collisions++;		} else if (status & TCMD_NOCARRIER) {			p->stats.tx_carrier_errors++;			printk(KERN_WARNING "%s: no carrier detected.\n", dev->name);		} else if (status & TCMD_LOSTCTS) {			printk(KERN_WARNING "%s: loss of CTS detected.\n", dev->name);		} else if (status & TCMD_UNDERRUN) {			p->stats.tx_fifo_errors++;			printk(KERN_WARNING "%s: DMA underrun detected.\n", dev->name);		} else if (status & TCMD_MAXCOLL) {			printk(KERN_WARNING "%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	netif_wake_queue(dev);}/*********************************************************** * (re)start the receiver */static void startrecv586(struct net_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!!) */}/****************************************************** * timeout */ static void elmc_timeout(struct net_device *dev){	struct priv *p = (struct priv *) dev->priv;	/* COMMAND-UNIT active? */	if (p->scb->status & CU_ACTIVE) {#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();		netif_wake_queue(dev);	} 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);	}} /****************************************************** * send frame */static int elmc_send_packet(struct sk_buff *skb, struct net_device *dev){	int len;#ifndef NO_NOPCOMMANDS	int next_nop;#endif	struct priv *p = (struct priv *) dev->priv;	netif_stop_queue(dev);	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(KERN_WARNING "%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;	if (p->xmit_count != p->xmit_last)		netif_wake_queue(dev);	dev_kfree_skb(skb);#endif	return 0;}/******************************************* * Someone wanna have the statistics */static struct net_device_stats *elmc_get_stats(struct net_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 .. */#ifdef ELMC_MULTICASTstatic void set_multicast_list(struct net_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;}#endif/*************************************************************************/#ifdef MODULE/* Increase if needed ;) */#define MAX_3C523_CARDS 4static struct net_device dev_elmc[MAX_3C523_CARDS];static int irq[MAX_3C523_CARDS];static int io[MAX_3C523_CARDS];MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_3C523_CARDS) "i");MODULE_PARM(io, "1-" __MODULE_STRING(MAX_3C523_CARDS) "i");int init_module(void){	int this_dev,found = 0;	/* Loop until we either can't find any more cards, or we have MAX_3C523_CARDS */		for(this_dev=0; this_dev<MAX_3C523_CARDS; this_dev++) 		{		struct net_device *dev = &dev_elmc[this_dev];		dev->irq=irq[this_dev];		dev->base_addr=io[this_dev];		dev->init=elmc_probe;		if(register_netdev(dev)!=0) {			if(io[this_dev]==0) break;			printk(KERN_WARNING "3c523.c: No 3c523 card found at io=%#x\n",io[this_dev]);		} else found++;	}	if(found==0) {		if(io[0]==0) printk(KERN_NOTICE "3c523.c: No 3c523 cards found\n");		return -ENXIO;	} else return 0;}void cleanup_module(void){	int this_dev;	for(this_dev=0; this_dev<MAX_3C523_CARDS; this_dev++) {		struct net_device *dev = &dev_elmc[this_dev];		if(dev->priv) {			/* 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[this_dev] = 0;			io[this_dev] = 0;			unregister_netdev(dev);			mca_set_adapter_procfn(((struct priv *) (dev->priv))->slot,			       NULL, NULL);			kfree(dev->priv);			dev->priv = NULL;		}	}}#endif				/* MODULE */

⌨️ 快捷键说明

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