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

📄 lp486e.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 3 页
字号:
		tx_cmd_tbd->pad = 0;		tx_cmd_tbd->size = (EOF | length);		tx_cmd_tbd->pa_data = va_to_pa (skb->data);		tx_cmd_tbd->skb = skb;		if (i596_debug & LOG_SRCDST)			print_eth (skb->data);		i596_add_cmd (dev, (struct i596_cmd *) tx_cmd);		lp->stats.tx_packets++;	}	return 0;}static voidi596_tx_timeout (struct net_device *dev) {	volatile struct i596_private *lp = dev->priv;	int ioaddr = dev->base_addr;	/* Transmitter timeout, serious problems. */	printk ("%s: transmit timed out, status resetting.\n", dev->name);	lp->stats.tx_errors++;	/* Try to restart the adaptor */	if (lp->last_restart == lp->stats.tx_packets) {		printk ("Resetting board.\n");		/* Shutdown and restart */		i596_reset (dev, lp, ioaddr);	} else {		/* Issue a channel attention signal */		printk ("Kicking board.\n");		lp->scb.command = (CUC_START | RX_START);		CA();		lp->last_restart = lp->stats.tx_packets;	}	netif_wake_queue(dev);}static voidprint_eth(char *add) {	int i;	printk ("Dest  ");	for (i = 0; i < 6; i++)		printk(" %2.2X", (unsigned char) add[i]);	printk ("\n");	printk ("Source");	for (i = 0; i < 6; i++)		printk(" %2.2X", (unsigned char) add[i+6]);	printk ("\n");	printk ("type %2.2X%2.2X\n",		(unsigned char) add[12], (unsigned char) add[13]);}int __initlp486e_probe(struct net_device *dev) {	volatile struct i596_private *lp;	unsigned char eth_addr[6] = { 0, 0xaa, 0, 0, 0, 0 };	unsigned char *bios;	int i, j;	int ret = -ENOMEM;	static int probed;	if (probed)		return -ENODEV;	probed++;	if (!request_region(IOADDR, LP486E_TOTAL_SIZE, dev->name)) {		printk(KERN_ERR "lp486e: IO address 0x%x in use\n", IOADDR);		return -EBUSY;	}	/*	 * Allocate working memory, 16-byte aligned	 */	dev->mem_start = (unsigned long)		kmalloc(sizeof(struct i596_private) + 0x0f, GFP_KERNEL);	if (!dev->mem_start)		goto err_out;	dev->priv = (void *)((dev->mem_start + 0xf) & 0xfffffff0);	lp = (struct i596_private *) dev->priv;	memset((void *)lp, 0, sizeof(struct i596_private));	/*	 * Do we really have this thing?	 */	if (i596_scp_setup(dev)) {		ret = -ENODEV;		goto err_out_kfree;	}	dev->base_addr = IOADDR;	dev->irq = IRQ;	ether_setup(dev);	/*	 * How do we find the ethernet address? I don't know.	 * One possibility is to look at the EISA configuration area	 * [0xe8000-0xe9fff]. This contains the ethernet address	 * but not at a fixed address - things depend on setup options.	 *	 * If we find no address, or the wrong address, use	 *   ifconfig eth0 hw ether a1:a2:a3:a4:a5:a6	 * with the value found in the BIOS setup.	 */	bios = bus_to_virt(0xe8000);	for (j = 0; j < 0x2000; j++) {		if (bios[j] == 0 && bios[j+1] == 0xaa && bios[j+2] == 0) {			printk("%s: maybe address at BIOS 0x%x:",			       dev->name, 0xe8000+j);			for (i = 0; i < 6; i++) {				eth_addr[i] = bios[i+j];				printk(" %2.2X", eth_addr[i]);			}			printk("\n");		}	}	printk("%s: lp486e 82596 at %#3lx, IRQ %d,",	       dev->name, dev->base_addr, dev->irq);	for (i = 0; i < 6; i++)		printk(" %2.2X", dev->dev_addr[i] = eth_addr[i]);	printk("\n");	/* The LP486E-specific entries in the device structure. */	dev->open = &i596_open;	dev->stop = &i596_close;	dev->hard_start_xmit = &i596_start_xmit;	dev->get_stats = &i596_get_stats;	dev->set_multicast_list = &set_multicast_list;	dev->watchdog_timeo = 5*HZ;	dev->tx_timeout = i596_tx_timeout;#if 0	/* selftest reports 0x320925ae - don't know what that means */	i596_port_do(dev, PORT_SELFTEST, "selftest");	i596_port_do(dev, PORT_DUMP, "dump");#endif	return 0;err_out_kfree:	kfree ((void *) dev->mem_start);err_out:	release_region(IOADDR, LP486E_TOTAL_SIZE);	return ret;}static void inlinei596_handle_CU_completion(struct net_device *dev,			  volatile struct i596_private *lp,			  unsigned short status,			  unsigned short *ack_cmdp) {	volatile struct i596_cmd *cmd;	int frames_out = 0;	int commands_done = 0;	int cmd_val;	cmd = lp->cmd_head;	while (lp->cmd_head && (lp->cmd_head->status & CMD_STAT_C)) {		cmd = lp->cmd_head;		lp->cmd_head = pa_to_va(lp->cmd_head->pa_next);		lp->cmd_backlog--;		commands_done++;		cmd_val = cmd->command & 0x7;#if 0		printk("finished CU %s command (%d)\n",		       CUcmdnames[cmd_val], cmd_val);#endif		switch (cmd_val) {		case CmdTx:		{			struct tx_cmd *tx_cmd;			struct i596_tbd *tx_cmd_tbd;			tx_cmd = (struct tx_cmd *) cmd;			tx_cmd_tbd = pa_to_va(tx_cmd->pa_tbd);			frames_out++;			if (cmd->status & CMD_STAT_OK) {				if (i596_debug)					print_eth(pa_to_va(tx_cmd_tbd->pa_data));			} else {				lp->stats.tx_errors++;				if (i596_debug)					printk("transmission failure:%04x\n",					       cmd->status);				if (cmd->status & 0x0020)					lp->stats.collisions++;				if (!(cmd->status & 0x0040))					lp->stats.tx_heartbeat_errors++;				if (cmd->status & 0x0400)					lp->stats.tx_carrier_errors++;				if (cmd->status & 0x0800)					lp->stats.collisions++;				if (cmd->status & 0x1000)					lp->stats.tx_aborted_errors++;			}			dev_kfree_skb_irq(tx_cmd_tbd->skb);			cmd->pa_next = I596_NULL;			kfree((unsigned char *)tx_cmd);			netif_wake_queue(dev);			break;		}		case CmdMulticastList:			cmd->pa_next = I596_NULL;			kfree((unsigned char *)cmd);			break;		case CmdTDR:		{			unsigned long status = *((unsigned long *) (cmd + 1));			if (status & 0x8000) {				if (i596_debug)					printk("%s: link ok.\n", dev->name);			} else {				if (status & 0x4000)					printk("%s: Transceiver problem.\n",					       dev->name);				if (status & 0x2000)					printk("%s: Termination problem.\n",					       dev->name);				if (status & 0x1000)					printk("%s: Short circuit.\n",					       dev->name);				printk("%s: Time %ld.\n",				       dev->name, status & 0x07ff);			}		}		default:			cmd->pa_next = I596_NULL;			lp->last_cmd = jiffies;					}	}	cmd = lp->cmd_head;	while (cmd && (cmd != lp->cmd_tail)) {		cmd->command &= 0x1fff;		cmd = pa_to_va(cmd->pa_next);	}	if (lp->cmd_head)		*ack_cmdp |= CUC_START;	lp->scb.pa_cmd = va_to_pa(lp->cmd_head);}static voidi596_interrupt (int irq, void *dev_instance, struct pt_regs *regs) {	struct net_device *dev = (struct net_device *) dev_instance;	volatile struct i596_private *lp;	unsigned short status, ack_cmd = 0;	int frames_in = 0;	if (dev == NULL) {		printk ("i596_interrupt(): irq %d for unknown device.\n", irq);		return;	}	lp = (struct i596_private *) dev->priv;	/*	 * The 82596 examines the command, performs the required action,	 * and then clears the SCB command word.	 */	if (lp->scb.command && i596_timeout(dev, "interrupt", 40))		;	/*	 * The status word indicates the status of the 82596.	 * It is modified only by the 82596.	 *	 * [So, we must not clear it. I find often status 0xffff,	 *  which is not one of the values allowed by the docs.]	 */	status = lp->scb.status;#if 0	if (i596_debug) {		printk("%s: i596 interrupt, ", dev->name);		i596_out_status(status);	}#endif	/* Impossible, but it happens - perhaps when we get	   a receive interrupt but scb.pa_rfd is I596_NULL. */	if (status == 0xffff) {		printk("%s: i596_interrupt: got status 0xffff\n", dev->name);		goto out;	}	ack_cmd = (status & STAT_ACK);	if (status & (STAT_CX | STAT_CNA))		i596_handle_CU_completion(dev, lp, status, &ack_cmd);	if (status & (STAT_FR | STAT_RNR)) {		/* Restart the receive unit when it got inactive somehow */		if ((status & STAT_RNR) && netif_running(dev))			ack_cmd |= RX_START;		if (status & STAT_FR) {			frames_in = i596_rx(dev);			if (!frames_in)				printk("receive frame reported, but no frames\n");		}	}	/* acknowledge the interrupt */	/*	if ((lp->scb.pa_cmd != I596_NULL) && netif_running(dev))		ack_cmd |= CUC_START;	*/	if (lp->scb.command && i596_timeout(dev, "i596 interrupt", 100))		;	lp->scb.command = ack_cmd;	CLEAR_INT();	CA(); out:	return;}static int i596_close(struct net_device *dev) {	volatile struct i596_private *lp = dev->priv;	netif_stop_queue(dev);	if (i596_debug)		printk("%s: Shutting down ethercard, status was %4.4x.\n",		       dev->name, lp->scb.status);	lp->scb.command = (CUC_ABORT | RX_ABORT);	CA();	i596_cleanup_cmd(dev);	if (lp->scb.command && i596_timeout(dev, "i596_close", 200))		;	free_irq(dev->irq, dev);	remove_rx_bufs(dev);	return 0;}static struct net_device_stats * i596_get_stats(struct net_device *dev) {	struct i596_private *lp = dev->priv;	return &lp->stats;}/**	Set or clear the multicast filter for this adaptor.*/static void set_multicast_list(struct net_device *dev) {	volatile struct i596_private *lp = dev->priv;	struct i596_cmd *cmd;	if (i596_debug > 1)		printk ("%s: set multicast list %d\n",			dev->name, dev->mc_count);	if (dev->mc_count > 0) {		struct dev_mc_list *dmi;		char *cp;		cmd = (struct i596_cmd *)			kmalloc(sizeof(struct i596_cmd)+2+dev->mc_count*6,				GFP_ATOMIC);		if (cmd == NULL) {			printk ("%s: set_multicast Memory squeeze.\n",				dev->name);			return;		}		cmd->command = CmdMulticastList;		*((unsigned short *) (cmd + 1)) = dev->mc_count * 6;		cp = ((char *)(cmd + 1))+2;		for (dmi = dev->mc_list; dmi != NULL; dmi = dmi->next) {			memcpy(cp, dmi,6);			cp += 6;		}		if (i596_debug & LOG_SRCDST)			print_eth (((char *)(cmd + 1)) + 2);		i596_add_cmd(dev, cmd);	} else {		if (lp->set_conf.pa_next != I596_NULL) {			return;		}		if (dev->mc_count == 0 &&		    !(dev->flags & (IFF_PROMISC | IFF_ALLMULTI))) {			if (dev->flags & IFF_ALLMULTI)				dev->flags |= IFF_PROMISC;			lp->i596_config[8] &= ~0x01;		} else {			lp->i596_config[8] |= 0x01;		}		i596_add_cmd(dev, (struct i596_cmd *) &lp->set_conf);	}}MODULE_AUTHOR("Ard van Breemen <ard@cstmel.nl.eu.org>");MODULE_DESCRIPTION("Intel Panther onboard i82596 driver");MODULE_LICENSE("GPL");MODULE_PARM(debug, "i");//MODULE_PARM(max_interrupt_work, "i");//MODULE_PARM(reverse_probe, "i");//MODULE_PARM(rx_copybreak, "i");MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");static struct net_device dev_lp486e;static int full_duplex;static int options;static int io = IOADDR;static int irq = IRQ;static int __init lp486e_init_module(void) {	struct net_device *dev = &dev_lp486e;	dev->irq = irq;	dev->base_addr = io;	dev->init = lp486e_probe;	if (register_netdev(dev) != 0)		return -EIO;	full_duplex = 0;	options = 0;	return 0;}static void __exit lp486e_cleanup_module(void) {	unregister_netdev(&dev_lp486e);	kfree((void *)dev_lp486e.mem_start);	dev_lp486e.priv = NULL;	release_region(dev_lp486e.base_addr, LP486E_TOTAL_SIZE);}module_init(lp486e_init_module);module_exit(lp486e_cleanup_module);

⌨️ 快捷键说明

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