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

📄 arlan-main.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	conf->tx_delay_ms = tx_delay_ms;	conf->ReTransmitPacketMaxSize = 200;	conf->waitReTransmitPacketMaxSize = 200;	conf->txAckTimeoutMs = 900;	conf->fastReTransCount = 3;	ARLAN_DEBUG_EXIT("arlan_read_card_configuration");	return 0;}static int lastFoundAt = 0xbe000;/* * This is the real probe routine. Linux has a history of friendly device * probes on the ISA bus. A good device probes avoids doing writes, and * verifies that the correct device exists and functions. */#define ARLAN_SHMEM_SIZE	0x2000static int __init arlan_check_fingerprint(unsigned long memaddr){	static const char probeText[] = "TELESYSTEM SLW INC.    ARLAN \0";	volatile struct arlan_shmem *arlan = (struct arlan_shmem *) memaddr;	unsigned long paddr = virt_to_phys((void *) memaddr);	char tempBuf[49];	ARLAN_DEBUG_ENTRY("arlan_check_fingerprint");	if (!request_mem_region(paddr, ARLAN_SHMEM_SIZE, "arlan")) {		// printk(KERN_WARNING "arlan: memory region %lx excluded from probing \n",paddr);		return -ENODEV;	}	memcpy_fromio(tempBuf, arlan->textRegion, 29);	tempBuf[30] = 0;	/* check for card at this address */	if (0 != strncmp(tempBuf, probeText, 29)){ 		release_mem_region(paddr, ARLAN_SHMEM_SIZE);		return -ENODEV;	}//   printk(KERN_INFO "arlan found at 0x%x \n",memaddr);	ARLAN_DEBUG_EXIT("arlan_check_fingerprint");	return 0;}static int arlan_change_mtu(struct net_device *dev, int new_mtu){	struct arlan_private *priv = dev->priv;	struct arlan_conf_stru *conf = priv->Conf;	ARLAN_DEBUG_ENTRY("arlan_change_mtu");	if (new_mtu > 2032)		return -EINVAL;	dev->mtu = new_mtu;	if (new_mtu < 256)		new_mtu = 256;	/* cards book suggests 1600 */	conf->maxDatagramSize = new_mtu;	conf->maxFrameSize = new_mtu + 48;	arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_CONF);	printk(KERN_NOTICE "%s mtu changed to %d \n", dev->name, new_mtu);	ARLAN_DEBUG_EXIT("arlan_change_mtu");	return 0;}static int arlan_mac_addr(struct net_device *dev, void *p){	struct sockaddr *addr = p;	ARLAN_DEBUG_ENTRY("arlan_mac_addr");	return -EINVAL;	if (!netif_running(dev))		return -EBUSY;	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);	ARLAN_DEBUG_EXIT("arlan_mac_addr");	return 0;}static int __init arlan_setup_device(struct net_device *dev, int num){	struct arlan_private *ap = dev->priv;	int err;	ARLAN_DEBUG_ENTRY("arlan_setup_device");	ap->conf = (struct arlan_shmem *)(ap+1);	dev->tx_queue_len = tx_queue_len;	dev->open = arlan_open;	dev->stop = arlan_close;	dev->hard_start_xmit = arlan_tx;	dev->get_stats = arlan_statistics;	dev->set_multicast_list = arlan_set_multicast;	dev->change_mtu = arlan_change_mtu;	dev->set_mac_address = arlan_mac_addr;	dev->tx_timeout = arlan_tx_timeout;	dev->watchdog_timeo = 3*HZ;		ap->irq_test_done = 0;	ap->Conf = &arlan_conf[num];	ap->Conf->pre_Command_Wait = 40;	ap->Conf->rx_tweak1 = 30;	ap->Conf->rx_tweak2 = 0;	err = register_netdev(dev);	if (err) {		release_mem_region(virt_to_phys((void *) dev->mem_start), 			   ARLAN_SHMEM_SIZE);		free_netdev(dev);		return err;	}	arlan_device[num] = dev;	ARLAN_DEBUG_EXIT("arlan_setup_device");	return 0;}static int __init arlan_probe_here(struct net_device *dev, 				   unsigned long memaddr){	struct arlan_private *ap = dev->priv;	ARLAN_DEBUG_ENTRY("arlan_probe_here");	if (arlan_check_fingerprint(memaddr))		return -ENODEV;	printk(KERN_NOTICE "%s: Arlan found at %x, \n ", dev->name, 	       (int) virt_to_phys((void*)memaddr));	ap->card = (void *) memaddr;	dev->mem_start = memaddr;	dev->mem_end = memaddr + ARLAN_SHMEM_SIZE-1;	if (dev->irq < 2)	{		READSHM(dev->irq, ap->card->irqLevel, u_char);	} else if (dev->irq == 2)		dev->irq = 9;	arlan_read_card_configuration(dev);	ARLAN_DEBUG_EXIT("arlan_probe_here");	return 0;}static int arlan_open(struct net_device *dev){	struct arlan_private *priv = dev->priv;	volatile struct arlan_shmem *arlan = priv->card;	int ret = 0;	ARLAN_DEBUG_ENTRY("arlan_open");	ret = request_irq(dev->irq, &arlan_interrupt, 0, dev->name, dev);	if (ret)	{		printk(KERN_ERR "%s: unable to get IRQ %d .\n",			dev->name, dev->irq);		return ret;	}	priv->bad = 0;	priv->lastReset = 0;	priv->reset = 0;	memcpy_fromio(dev->dev_addr, arlan->lanCardNodeId, 6);	memset(dev->broadcast, 0xff, 6);	dev->tx_queue_len = tx_queue_len;	priv->interrupt_processing_active = 0;	spin_lock_init(&priv->lock);	netif_start_queue (dev);	priv->registrationLostCount = 0;	priv->registrationLastSeen = jiffies;	priv->txLast = 0;	priv->tx_command_given = 0;	priv->rx_command_given = 0;		priv->reRegisterExp = 1;	priv->tx_last_sent = jiffies - 1;	priv->tx_last_cleared = jiffies;	priv->Conf->writeEEPROM = 0;	priv->Conf->registrationInterrupts = 1;	init_timer(&priv->timer);	priv->timer.expires = jiffies + HZ / 10;	priv->timer.data = (unsigned long) dev;	priv->timer.function = &arlan_registration_timer;	/* timer handler */	arlan_command(dev, ARLAN_COMMAND_POWERUP | ARLAN_COMMAND_LONG_WAIT_NOW);	mdelay(200);	add_timer(&priv->timer);	ARLAN_DEBUG_EXIT("arlan_open");	return 0;}static void arlan_tx_timeout (struct net_device *dev){	printk(KERN_ERR "%s: arlan transmit timed out, kernel decided\n", dev->name);	/* Try to restart the adaptor. */	arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_RESET);	// dev->trans_start = jiffies;	// netif_start_queue (dev);}static int arlan_tx(struct sk_buff *skb, struct net_device *dev){	short length;	unsigned char *buf;	ARLAN_DEBUG_ENTRY("arlan_tx");		length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;	buf = skb->data;	if (length + 0x12 > 0x800) {		printk(KERN_ERR "TX RING overflow \n");		netif_stop_queue (dev);	}	if (arlan_hw_tx(dev, buf, length) == -1)		goto bad_end;	dev->trans_start = jiffies;	dev_kfree_skb(skb);	arlan_process_interrupt(dev);	ARLAN_DEBUG_EXIT("arlan_tx");	return 0;bad_end:	arlan_process_interrupt(dev);	netif_stop_queue (dev);	ARLAN_DEBUG_EXIT("arlan_tx");	return 1;}static inline int DoNotReTransmitCrap(struct net_device *dev){	struct arlan_private *priv = dev->priv;	if (TXLAST(dev).length < priv->Conf->ReTransmitPacketMaxSize)		return 1;	return 0;}static inline int DoNotWaitReTransmitCrap(struct net_device *dev){	struct arlan_private *priv = dev->priv;	if (TXLAST(dev).length < priv->Conf->waitReTransmitPacketMaxSize)		return 1;	return 0;}static inline void arlan_queue_retransmit(struct net_device *dev){	struct arlan_private *priv = dev->priv;	ARLAN_DEBUG_ENTRY("arlan_queue_retransmit");	if (DoNotWaitReTransmitCrap(dev))	{		  arlan_drop_tx(dev);	} else		priv->ReTransmitRequested++;	ARLAN_DEBUG_EXIT("arlan_queue_retransmit");}static inline void RetryOrFail(struct net_device *dev){	struct arlan_private *priv = dev->priv;	ARLAN_DEBUG_ENTRY("RetryOrFail");	if (priv->retransmissions > priv->Conf->retries ||	    DoNotReTransmitCrap(dev))	{		arlan_drop_tx(dev);	}	else if (priv->bad <= priv->Conf->fastReTransCount)	{		arlan_retransmit_now(dev);	}	else arlan_queue_retransmit(dev);	ARLAN_DEBUG_EXIT("RetryOrFail");}static void arlan_tx_done_interrupt(struct net_device *dev, int status){	struct arlan_private *priv = dev->priv;	ARLAN_DEBUG_ENTRY("arlan_tx_done_interrupt");	priv->tx_last_cleared = jiffies;	priv->tx_command_given = 0;	switch (status)	{		case 1:		{			IFDEBUG(ARLAN_DEBUG_TX_CHAIN)				printk("arlan intr: transmit OK\n");			priv->stats.tx_packets++;			priv->bad = 0;			priv->reset = 0;			priv->retransmissions = 0;			if (priv->Conf->tx_delay_ms)			{				priv->tx_done_delayed = jiffies + (priv->Conf->tx_delay_ms * HZ) / 1000 + 1;			}			else			{				TXLAST(dev).offset = 0;				if (priv->txLast)					priv->txLast = 0;				else if (TXTAIL(dev).offset)					priv->txLast = 1;				if (TXLAST(dev).offset)				{					arlan_retransmit_now(dev);					dev->trans_start = jiffies;				}				if (!TXHEAD(dev).offset || !TXTAIL(dev).offset)				{					netif_wake_queue (dev);				}			}		}		break;				case 2:		{			IFDEBUG(ARLAN_DEBUG_TX_CHAIN)				printk("arlan intr: transmit timed out\n");			priv->bad += 1;			//arlan_queue_retransmit(dev);			RetryOrFail(dev);		}		break;		case 3:		{			IFDEBUG(ARLAN_DEBUG_TX_CHAIN)				printk("arlan intr: transmit max retries\n");			priv->bad += 1;			priv->reset = 0;			//arlan_queue_retransmit(dev);			RetryOrFail(dev);		}		break;				case 4:		{			IFDEBUG(ARLAN_DEBUG_TX_CHAIN)				printk("arlan intr: transmit aborted\n");			priv->bad += 1;			arlan_queue_retransmit(dev);			//RetryOrFail(dev);		}		break;		case 5:		{			IFDEBUG(ARLAN_DEBUG_TX_CHAIN)				printk("arlan intr: transmit not registered\n");			priv->bad += 1;			//debug=101;			arlan_queue_retransmit(dev);		}		break;		case 6:		{			IFDEBUG(ARLAN_DEBUG_TX_CHAIN) 				printk("arlan intr: transmit destination full\n");			priv->bad += 1;			priv->reset = 0;			//arlan_drop_tx(dev);			arlan_queue_retransmit(dev);		}		break;		case 7:		{			IFDEBUG(ARLAN_DEBUG_TX_CHAIN)				printk("arlan intr: transmit unknown ack\n");			priv->bad += 1;			priv->reset = 0;			arlan_queue_retransmit(dev);		}		break;				case 8:		{			IFDEBUG(ARLAN_DEBUG_TX_CHAIN)				printk("arlan intr: transmit dest mail box full\n");			priv->bad += 1;			priv->reset = 0;			//arlan_drop_tx(dev);			arlan_queue_retransmit(dev);		}		break;		case 9:		{			IFDEBUG(ARLAN_DEBUG_TX_CHAIN)				printk("arlan intr: transmit root dest not reg.\n");			priv->bad += 1;			priv->reset = 1;			//arlan_drop_tx(dev);			arlan_queue_retransmit(dev);		}		break;		default:		{			printk(KERN_ERR "arlan intr: transmit status unknown\n");			priv->bad += 1;			priv->reset = 1;			arlan_drop_tx(dev);		}	}	ARLAN_DEBUG_EXIT("arlan_tx_done_interrupt");}static void arlan_rx_interrupt(struct net_device *dev, u_char rxStatus, u_short rxOffset, u_short pkt_len){	char *skbtmp;	int i = 0;	struct arlan_private *priv = dev->priv;	volatile struct arlan_shmem *arlan = priv->card;	struct arlan_conf_stru *conf = priv->Conf;	ARLAN_DEBUG_ENTRY("arlan_rx_interrupt");	// by spec,   not                WRITESHMB(arlan->rxStatus,0x00);	// prohibited here              arlan_command(dev, ARLAN_COMMAND_RX);	if (pkt_len < 10 || pkt_len > 2048)	{		printk(KERN_WARNING "%s: got too short or long packet, len %d \n", dev->name, pkt_len);		return;	}	if (rxOffset + pkt_len > 0x2000)	{		printk("%s: got too long packet, len %d offset %x\n", dev->name, pkt_len, rxOffset);		return;

⌨️ 快捷键说明

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