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

📄 3c501.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 2 页
字号:
load_it_again_sam:		lp->tx_pkt_start = gp_start;    		lp->collisions = 0;		/*		 *	Command mode with status cleared should [in theory]		 *	mean no more interrupts can be pending on the card.		 */		 #ifdef BLOCKOUT_1		disable_irq(dev->irq);		 #endif			outb_p(AX_SYS, AX_CMD);		inb_p(RX_STATUS);		inb_p(TX_STATUS);			lp->loading=1;			/* 		 *	Turn interrupts back on while we spend a pleasant afternoon		 *	loading bytes into the board 		 */		restore_flags(flags);		outw(0x00, RX_BUF_CLR);		/* Set rx packet area to 0. */		outw(gp_start, GP_LOW);		/* aim - packet will be loaded into buffer start */		outsb(DATAPORT,buf,skb->len);	/* load buffer (usual thing each byte increments the pointer) */		outw(gp_start, GP_LOW);		/* the board reuses the same register */#ifndef BLOCKOUT_1				if(lp->loading==2)		/* A receive upset our load, despite our best efforts */		{			if(el_debug>2)				printk("%s: burped during tx load.\n", dev->name);			goto load_it_again_sam;	/* Sigh... */		}#endif		outb(AX_XMIT, AX_CMD);		/* fire ... Trigger xmit.  */		lp->loading=0;#ifdef BLOCKOUT_1				enable_irq(dev->irq);#endif				dev->trans_start = jiffies;	}	if (el_debug > 2)		printk(" queued xmit.\n");	dev_kfree_skb (skb, FREE_WRITE);	return 0;}/* *	The typical workload of the driver: *	Handle the ether interface interrupts.  */static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs){	struct device *dev = (struct device *)(irq2dev_map[irq]);	struct net_local *lp;	int ioaddr;	int axsr;			/* Aux. status reg. */	if (dev == NULL  ||  dev->irq != irq) 	{		printk ("3c501 driver: irq %d for unknown device.\n", irq);		return;	}	ioaddr = dev->base_addr;	lp = (struct net_local *)dev->priv;	/*	 *	What happened ?	 */	 	axsr = inb(AX_STATUS);	/*	 *	Log it	 */	if (el_debug > 3)		printk("%s: el_interrupt() aux=%#02x", dev->name, axsr);	if (dev->interrupt)		printk("%s: Reentering the interrupt driver!\n", dev->name);	dev->interrupt = 1;#ifndef BLOCKOUT_1            if(lp->loading==1 && !dev->tbusy)        	printk("%s: Inconsistent state loading while not in tx\n",        		dev->name);#endif        		#ifdef BLOCKOUT_3	lp->loading=2;		/* So we can spot loading interruptions */#endif	if (dev->tbusy) 	{        		/*    		 *	Board in transmit mode. May be loading. If we are    		 *	loading we shouldn't have got this.    		 */    	 		int txsr = inb(TX_STATUS);#ifdef BLOCKOUT_2				if(lp->loading==1)		{			if(el_debug > 2)			{				printk("%s: Interrupt while loading [", dev->name);				printk(" txsr=%02x gp=%04x rp=%04x]\n", txsr, inw(GP_LOW),inw(RX_LOW));			}			lp->loading=2;		/* Force a reload */			dev->interrupt = 0;			return;		}#endif		if (el_debug > 6)			printk(" txsr=%02x gp=%04x rp=%04x", txsr, inw(GP_LOW),inw(RX_LOW));		if ((axsr & 0x80) && (txsr & TX_READY) == 0) 		{			/*			 *	FIXME: is there a logic to whether to keep on trying or			 *	reset immediately ?			 */			if(el_debug>1)				printk("%s: Unusual interrupt during Tx, txsr=%02x axsr=%02x"			  		" gp=%03x rp=%03x.\n", dev->name, txsr, axsr,			inw(ioaddr + EL1_DATAPTR), inw(ioaddr + EL1_RXPTR));			dev->tbusy = 0;			mark_bh(NET_BH);		} 		else if (txsr & TX_16COLLISIONS) 		{			/*			 *	Timed out			 */			if (el_debug)				printk("%s: Transmit failed 16 times, ethernet jammed?\n",dev->name);			outb(AX_SYS, AX_CMD);			lp->stats.tx_aborted_errors++;		}		else if (txsr & TX_COLLISION) 		{				/*			 *	Retrigger xmit. 			 */			 			if (el_debug > 6)				printk(" retransmitting after a collision.\n");			/*			 *	Poor little chip can't reset its own start pointer			 */						outb(AX_SYS, AX_CMD);			outw(lp->tx_pkt_start, GP_LOW);			outb(AX_XMIT, AX_CMD);			lp->stats.collisions++;			dev->interrupt = 0;			return;		}		else		{			/*			 *	It worked.. we will now fall through and receive			 */			lp->stats.tx_packets++;			if (el_debug > 6)				printk(" Tx succeeded %s\n",		       			(txsr & TX_RDY) ? "." : "but tx is busy!");			/*			 *	This is safe the interrupt is atomic WRT itself.			 */			dev->tbusy = 0;			mark_bh(NET_BH);	/* In case more to transmit */		}	}	else	{    		/*    		 *	In receive mode.    		 */    	 		int rxsr = inb(RX_STATUS);		if (el_debug > 5)			printk(" rxsr=%02x txsr=%02x rp=%04x", rxsr, inb(TX_STATUS),inw(RX_LOW));		/*		 *	Just reading rx_status fixes most errors. 		 */		if (rxsr & RX_MISSED)			lp->stats.rx_missed_errors++;		else if (rxsr & RX_RUNT) 		{	/* Handled to avoid board lock-up. */			lp->stats.rx_length_errors++;			if (el_debug > 5) 				printk(" runt.\n");		} 		else if (rxsr & RX_GOOD) 		{			/*			 *	Receive worked.			 */			el_receive(dev);		}		else		{			/*			 *	Nothing?  Something is broken!			 */			if (el_debug > 2)				printk("%s: No packet seen, rxsr=%02x **resetting 3c501***\n",					dev->name, rxsr);			el_reset(dev);		}		if (el_debug > 3)			printk(".\n");	}	/*	 *	Move into receive mode 	 */	outb(AX_RX, AX_CMD);	outw(0x00, RX_BUF_CLR);	inb(RX_STATUS);		/* Be certain that interrupts are cleared. */	inb(TX_STATUS);	dev->interrupt = 0;	return;}/* *	We have a good packet. Well, not really "good", just mostly not broken. *	We must check everything to see if it is good.  */static void el_receive(struct device *dev){	struct net_local *lp = (struct net_local *)dev->priv;	int ioaddr = dev->base_addr;	int pkt_len;	struct sk_buff *skb;	pkt_len = inw(RX_LOW);	if (el_debug > 4)		printk(" el_receive %d.\n", pkt_len);	if ((pkt_len < 60)  ||  (pkt_len > 1536)) 	{		if (el_debug)			printk("%s: bogus packet, length=%d\n", dev->name, pkt_len);		lp->stats.rx_over_errors++;		return;	}    	/*	 *	Command mode so we can empty the buffer	 */     	outb(AX_SYS, AX_CMD);	skb = dev_alloc_skb(pkt_len+2);	/*	 *	Start of frame	 */	outw(0x00, GP_LOW);	if (skb == NULL) 	{		printk("%s: Memory squeeze, dropping packet.\n", dev->name);		lp->stats.rx_dropped++;		return;	}	else	{    		skb_reserve(skb,2);	/* Force 16 byte alignment */		skb->dev = dev;		/*		 *	The read increments through the bytes. The interrupt		 *	handler will fix the pointer when it returns to 		 *	receive mode.		 */		insb(DATAPORT, skb_put(skb,pkt_len), pkt_len);		skb->protocol=eth_type_trans(skb,dev);		netif_rx(skb);		lp->stats.rx_packets++;	}	return;}static void  el_reset(struct device *dev){	int ioaddr = dev->base_addr;	if (el_debug> 2)		printk("3c501 reset...");	outb(AX_RESET, AX_CMD);		/* Reset the chip */	outb(AX_LOOP, AX_CMD);		/* Aux control, irq and loopback enabled */	{		int i;		for (i = 0; i < 6; i++)	/* Set the station address. */			outb(dev->dev_addr[i], ioaddr + i);	}    	outw(0, RX_BUF_CLR);		/* Set rx packet area to 0. */	cli();				/* Avoid glitch on writes to CMD regs */	outb(TX_NORM, TX_CMD);		/* tx irq on done, collision */	outb(RX_NORM, RX_CMD);		/* Set Rx commands. */	inb(RX_STATUS);			/* Clear status. */	inb(TX_STATUS);	dev->interrupt = 0;	dev->tbusy = 0;	sti();}static int el1_close(struct device *dev){	int ioaddr = dev->base_addr;	if (el_debug > 2)		printk("%s: Shutting down ethercard at %#x.\n", dev->name, ioaddr);	dev->tbusy = 1;	dev->start = 0;	/*	 *	Free and disable the IRQ. 	 */	free_irq(dev->irq, NULL);	outb(AX_RESET, AX_CMD);		/* Reset the chip */	irq2dev_map[dev->irq] = 0;	MOD_DEC_USE_COUNT;	return 0;}static struct enet_statistics *el1_get_stats(struct device *dev){	struct net_local *lp = (struct net_local *)dev->priv;	return &lp->stats;}/* *	Set or clear the multicast filter for this adaptor. *			best-effort filtering. */static void set_multicast_list(struct device *dev){	int ioaddr = dev->base_addr;	if(dev->flags&IFF_PROMISC)	{    		outb(RX_PROM, RX_CMD);		inb(RX_STATUS);	}	else if (dev->mc_list || dev->flags&IFF_ALLMULTI)	{		outb(RX_MULT, RX_CMD);	/* Multicast or all multicast is the same */		inb(RX_STATUS);		/* Clear status. */	}	else 	{		outb(RX_NORM, RX_CMD);		inb(RX_STATUS);	}}#ifdef MODULEstatic char devicename[9] = { 0, };static struct device dev_3c501 = {	devicename, /* device name is inserted by linux/drivers/net/net_init.c */	0, 0, 0, 0,	0x280, 5,	0, 0, 0, NULL, el1_probe };static int io=0x280;static int irq=5;	int init_module(void){	dev_3c501.irq=irq;	dev_3c501.base_addr=io;	if (register_netdev(&dev_3c501) != 0)		return -EIO;	return 0;}void cleanup_module(void){	/*	 *	No need to check MOD_IN_USE, as sys_delete_module() checks.	 */	 	unregister_netdev(&dev_3c501);	/*	 *	Free up the private structure, or leak memory :-) 	 */	 	kfree(dev_3c501.priv);	dev_3c501.priv = NULL;	/* gets re-allocated by el1_probe1 */	/*	 *	If we don't do this, we can't re-insmod it later. 	 */	release_region(dev_3c501.base_addr, EL1_IO_EXTENT);}#endif /* MODULE *//* * Local variables: *  compile-command: "gcc -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer  -m486 -c -o 3c501.o 3c501.c" *  kept-new-versions: 5 * End: */

⌨️ 快捷键说明

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