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

📄 ax88180.c

📁 网络ax88180linux下的驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
 * 0xFC00~0xFCFF	MAC registers area * 0xFD00~0xFFFF	Unused * * Return 0 on success. ***************************************************************************** */int __init ax88180_probe(struct net_device *global_dev){        struct _AX88180_PRIVATE *pax88180_local;	unsigned long phy_membase = mem;/*	//allan9 add for debugging	unsigned long tmp_data;	unsigned long rx_packet_len;	unsigned int packet_len;	unsigned long rxcurt_ptr, rxbound_ptr;	int i;*/	PRINTK(DRIVER_MSG, "%s", version);	PRINTK(INIT_MSG, "ax88180: ax88180_probe beginning ..........\n");	SET_MODULE_OWNER(global_dev);	/* Allocate memory space for AX88180_PRIVATE structure */	global_dev->priv = kmalloc(sizeof(struct _AX88180_PRIVATE), GFP_KERNEL);	if (global_dev->priv == NULL) {		PRINTK(ERROR_MSG, "ax88180: Fail to allocate a private data structure!\n");		PRINTK(INIT_MSG, "ax88180: ax88180_probe fail end ..........\n");		unregister_netdev(global_dev);		return -ENOMEM;	}	/* Initialize zero values in the AX88180_PRIVATE structure */	memset(global_dev->priv, 0, sizeof(struct _AX88180_PRIVATE));	pax88180_local = (struct _AX88180_PRIVATE *) global_dev->priv;	if (check_mem_region(phy_membase , AX88180_MEMORY_SIZE) != 0) {		PRINTK(ERROR_MSG, "ax88180: Memory Region specified (0x%08lX to 0x%08lX) is not available!\n", 			phy_membase, (phy_membase + AX88180_MEMORY_SIZE - 1UL) );		kfree(global_dev->priv);		global_dev->priv = NULL;					unregister_netdev(global_dev);		return -ENOMEM;;	}	request_mem_region(phy_membase, AX88180_MEMORY_SIZE, "ASIX_AX88180");	pax88180_local->Phy_MemBase = phy_membase;	Log_MemBase = (unsigned long)ioremap(pax88180_local->Phy_MemBase, AX88180_MEMORY_SIZE);//	PRINTK(DEBUG_MSG, "ax88180: global_dev =0x%p, pax88180_local=0x%p, Log_MemBase=0x%08lx\n", //		global_dev, pax88180_local, Log_MemBase);	PRINTK(DRIVER_MSG, "ax88180: Allocate AX88180 at Phy_MemBase=0x%08lx. (name=%s, IRQ=0x%x)\n", 		pax88180_local->Phy_MemBase, global_dev->name, (unsigned int)irq);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)#ifdef CONFIG_BOARD_S3C2440_SMDK	/* Configure SAMSUNG S3C2440A controller for AX88780 operation */	BANKCON1 = BANKCON1_6CLKS_PAGE;	PRINTK(DEBUG_MSG, "ax88780: CLKDIVN=0x%04x, CAMDIVN=0x%04x, BANKCON1=0x%04x\n",	CLKDIVN, CAMDIVN, BANKCON1);	PRINTK(DEBUG_MSG, "ax88780: UBRDIV0=0x%04x, UBRDIV1=0x%04x, UBRDIV2=0x%04x\n",	UBRDIV0, UBRDIV1, UBRDIV2);	PRINTK(DEBUG_MSG, "ax88780: BWSCON=0x%08x, MISCCR=0x%06x\n", BWSCON, MISCCR);	set_external_irq(irq, EXT_LOWLEVEL, GPIO_PULLUP_DIS);	EINTMASK &= ~EINT11_MASK; 	EXTINT1 |= FLTEN11;#endif#else#ifdef CONFIG_ARCH_S3C2410	/* Configure SAMSUNG S3C2440A controller for AX88780 operation */	__raw_writel(S3C2410_BANKCON_Tacc6, S3C2410_BANKCON1);#endif#endif	/* Initialize the Ethernet Device structure */	ether_setup(global_dev);	global_dev->base_addr = mem;	global_dev->irq = irq;	pax88180_local->MediaMode = media;	pax88180_local->JumboFlag = jumbo;	pax88180_local->PhyAddr = MARVELL_88E1111_PHYADDR;	pax88180_local->rx_buf = NULL;	/* Declare ax88180 routines here */	global_dev->open		= ax88180_open;	global_dev->stop		= ax88180_stop;	global_dev->hard_start_xmit 	= ax88180_start_xmit;	global_dev->tx_timeout		= ax88180_tx_timeout;	global_dev->watchdog_timeo	= 200*HZ;	global_dev->get_stats		= ax88180_get_stats;	global_dev->set_multicast_list	= ax88180_set_multicast_list;#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)	global_dev->do_ioctl		= ax88180_ioctl;#endif	//allan9 add for debugging	DISPLAY_ALLMACREG;	DISPLAY_ALLPHYREG;/*	//allan9 add for debugging	READ_MACREG(RXCURT, rxcurt_ptr);	READ_MACREG(RXBOUND, rxbound_ptr);	START_READ_RXBUFF;	READ_RXBUF(rx_packet_len);    	if ( (rx_packet_len > 0) && (rx_packet_len <= MAX_RX_SIZE) ){		packet_len = (unsigned int)rx_packet_len;		PRINTK(DEBUG_MSG, "ax88180: Rx packet length = 0x%08lx\n", rx_packet_len);		for (i = 0; i < (packet_len - 4); i += 4) {			READ_RXBUF(tmp_data);			PRINTK(DEBUG_MSG, "ax88180: Rx data #%d = 0x%08lx\n", i, tmp_data);		}	} else {		PRINTK(DEBUG_MSG, "ax88180: Invalid Rx packet length!! (len=0x%08lx)\n", rx_packet_len);	}	STOP_READ_RXBUFF;	//allan9 end*/	PRINTK(INIT_MSG, "ax88180: ax88180_probe end ..........\n");	return 0;}#ifndef MODULE/* * ---------------------------------------------------------------------------- * Function Name: ax_kprobe * Purpose:  * Params: * Returns: * Note: * ---------------------------------------------------------------------------- */struct net_device * __init ax_kprobe(int unit){	struct net_device *dev = alloc_ei_netdev();	int err;	if (!dev)		return ERR_PTR(-ENOMEM);	sprintf(dev->name, "eth%d", unit);	netdev_boot_setup_check(dev);	err = ax88180_probe(dev);	if (err)		goto out;	return dev;out:	free_netdev(dev);	return ERR_PTR(err);}#endif/* ***************************************************************************** * ax88180_open() * * Open/initialize the board.  This is called (in the current kernel) * sometime after booting when the 'ifconfig' program is run. * * This routine should set everything up anew at each open, even * registers that "should" only need to be set once at boot, so that * there is non-reboot way to recover if something goes wrong. * * AKPM: do we need to do any locking here? * ***************************************************************************** */static int ax88180_open(struct net_device *global_dev){	struct _AX88180_PRIVATE *pax88180_local;	unsigned long tmp_regval;	int rtn = -ENODEV;	PRINTK(INIT_MSG, "ax88180: ax88180_open beginning ..........\n");	pax88180_local = (struct _AX88180_PRIVATE *) global_dev->priv;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	/* Indicate this module is in use */	MOD_INC_USE_COUNT;#endif	if (pax88180_local->rx_buf == NULL) {		/* Try to allocate memory space for RX buffer */		pax88180_local->rx_buf = kmalloc(MAX_RX_SIZE, GFP_KERNEL);		if (pax88180_local->rx_buf == NULL) {			PRINTK(ERROR_MSG, "ax88180: Fail to allocate a RX buffer space!\n");      			PRINTK(INIT_MSG, "ax88180: ax88180_open fail end ..........\n");#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)			MOD_DEC_USE_COUNT;#endif			return -ENOMEM;		}	}	/* Initialize zero values in the RX buffer */	memset(pax88180_local->rx_buf, 0, MAX_RX_SIZE);	/* Initial AX88180 registers here */	rtn = ax88180_initialization(global_dev);	if (rtn) {		/* Release allocated resource here */		PRINTK(ERROR_MSG, "ax88180: Fail to initialize AX88180 controller!!\n");		PRINTK(INIT_MSG, "ax88180: ax88180_open fail end ..........\n");#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)		MOD_DEC_USE_COUNT;#endif		return rtn;	}	/* Initial variables here */	INIT_TXRX_VARIABLES;	/* Declare Interrupt routine to the allocated IRQ */	rtn = request_irq(global_dev->irq, &ax88180_interrupt, 0, global_dev->name, global_dev);	if (rtn) {		/* Release allocated resource here */		PRINTK(ERROR_MSG, "ax88180: Fail to request IRQ (0x%x)\n", global_dev->irq);		PRINTK(INIT_MSG, "ax88180: ax88180_open fail end ..........\n");#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)		MOD_DEC_USE_COUNT;#endif		return rtn;	}	/* Enable AX88180 interrupt */	ENABLE_INTERRUPT;	/* Start AX88180 TX/RX functions */	WRITE_MACREG(CMD, RXEN | TXEN | WAKEMOD);	/* Check if there is any invalid interrupt status. If yes, clear it. */	READ_MACREG(ISR, tmp_regval);	PRINTK(INIT_MSG, "ax88180: The interrupt status = 0x%08lx\n", tmp_regval);	if (tmp_regval)		WRITE_MACREG(ISR, tmp_regval);	/* Display all AX88180 MAC and PHY registers onto console screen */	DISPLAY_ALLMACREG;	DISPLAY_ALLPHYREG;	/* Inform upper protocol to start sending packets */	netif_start_queue(global_dev);	/* Driver initialization successful */	PRINTK(DRIVER_MSG, "ax88180: name=%s, Phy_MemBase=0x%08lx, IRQ=0x%x, media=%d, jumbo=%u\n", 			global_dev->name, pax88180_local->Phy_MemBase, global_dev->irq, media, jumbo);	PRINTK(DRIVER_MSG, "ax88180: The AX88180 driver is loaded successfully.\n");	PRINTK(INIT_MSG, "ax88180: ax88180_open end ..........\n");	return 0;}/* ***************************************************************************** * ax88180_stop() * * The inverse routine to ax88180_open(). * ***************************************************************************** */static int ax88180_stop(struct net_device *global_dev){	struct _AX88180_PRIVATE *pax88180_local;	unsigned long flags;	PRINTK(INIT_MSG, "ax88180: ax88180_stop beginning ..........\n");	pax88180_local = (struct _AX88180_PRIVATE *) global_dev->priv;/*	PRINTK(DEBUG_MSG, "ax88180: global_dev =0x%p, pax88180_local=0x%p, dev_name=%s\n", 		global_dev, pax88180_local, global_dev->name);	PRINTK(DEBUG_MSG, "ax88180: Phy_MemBase=0x%08lx, Log_MemBase=0x%08lx\n", 		pax88180_local->Phy_MemBase, Log_MemBase);*/	spin_lock_irqsave(&pax88180_local->lock, flags);	kfree(pax88180_local->rx_buf);	/* Inform upper layer to stop sending packets to device driver */	if (netif_device_present(global_dev)) {		netif_stop_queue(global_dev);	}	/* Release interrupt */	free_irq(global_dev->irq, global_dev);	spin_unlock_irqrestore(&pax88180_local->lock, flags);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	/* Indicate this module is NOT used now */	MOD_DEC_USE_COUNT;#endif	/* Driver initialization successful */	PRINTK(DRIVER_MSG, "ax88180: The AX88180 driver is unloaded successfully.\n");	PRINTK(INIT_MSG, "ax88180: ax88180_stop end ..........\n");	return 0;}static int ax88180_start_xmit(struct sk_buff *skb, struct net_device *global_dev){	struct _AX88180_PRIVATE *pax88180_local;	unsigned char *txdata;	unsigned long TXDES_addr;	unsigned long txcmd_txdp, txbs_txdp;	unsigned long txdes0_val, txdes1_val, txdes2_val, txdes3_val;	unsigned long tmp_data;	int i;	pax88180_local = (struct _AX88180_PRIVATE *) global_dev->priv;	txdata = skb->data;	PRINTK(TX_MSG, "ax88180: ax88180_start_xmit beginning ..........\n");//	spin_lock_irq(&pax88180_local->lock);	/* Inform upper layer to stop sending packets to device driver */	netif_stop_queue(global_dev);	pax88180_local->FirstTxDesc = pax88180_local->NextTxDesc;	txbs_txdp = 1 << pax88180_local->FirstTxDesc;	//allan9 add to make sure TX machine is OK 	i = 0;	READ_MACREG(TXBS, tmp_data);	READ_MACREG(TXBS, tmp_data);	PRINTK(TX_MSG, "ax88180: Checking available TXDP (TXBS=0x%08lx)......\n", tmp_data);	while (tmp_data & txbs_txdp) {		pax88180_local->NextTxDesc++;		pax88180_local->NextTxDesc &= TXDP_MASK; 		pax88180_local->FirstTxDesc = pax88180_local->NextTxDesc;		txbs_txdp = 1 << pax88180_local->FirstTxDesc;		READ_MACREG(TXBS, tmp_data);		i++;		if (i > 1000) {			RESET_MAC;			pax88180_local->NextTxDesc = TXDP0;			pax88180_local->FirstTxDesc = pax88180_local->NextTxDesc;			txbs_txdp = 1 << pax88180_local->FirstTxDesc;			READ_MACREG(TXBS, tmp_data);			i = 0;			PRINTK(ERROR_MSG, "ax88180: No available TXDP!!\n"); 		}	}	PRINTK(TX_MSG, "ax88180: TXDP%d is available, i=%d\n", (int)pax88180_local->FirstTxDesc, i);	//allan9 end	txcmd_txdp = pax88180_local->FirstTxDesc << 13;	TXDES_addr = TXDES0 + (pax88180_local->FirstTxDesc << 2);	WRITE_MACREG(TXCMD, txcmd_txdp | skb->len | TX_START_WRITE);	//allan9 add for debugging	PRINTK(DEBUG_MSG, "ax88180: TX packets (len=0x%x, TXDP%d=0x%08lx)\n", 		skb->len, (int)pax88180_local->FirstTxDesc, TXDES_addr);	PRINTK(DEBUG_MSG, "[");//	for (i = 0; i < skb->len; i++) {	for (i = 0; i < 64; i++) {		PRINTK(DEBUG_MSG, "0x%02x ", *(txdata + i));		if ( (i & 0xF) == 0xF )			PRINTK(DEBUG_MSG, "\n");	}	PRINTK(DEBUG_MSG, "]\n");	//alln 2006.05.25 modify to support burst mode/*	for (i = 0; i < skb->len; i += 4) {		tmp_data = (unsigned long)*(txdata + i) + (unsigned long)(*(txdata + i + 1) << 8) 		    + (unsigned long)(*(txdata + i + 2) << 16) + (unsigned long)(*(txdata + i + 3) << 24);		WRITE_TXBUF(tmp_data);	}*/	memcpy ((void *)(Log_MemBase + TXBUFFER_START), txdata, (skb->len + (4 - skb->len%4)) );	WRITE_MACREG(TXCMD, txcmd_txdp | skb->len);	WRITE_MACREG(TXBS, txbs_txdp);	WRITE_MACREG(TXDES_addr, TXDPx_ENABLE | skb->len);	//allan9 add for debugging	READ_MACREG(TXCMD, txcmd_txdp);	READ_MACREG(TXBS, txbs_txdp);	READ_MACREG(TXDES0, txdes0_val);	READ_MACREG(TXDES1, txdes1_val);	READ_MACREG(TXDES2, txdes2_val);	READ_MACREG(TXDES3, txdes3_val);	PRINTK(TX_MSG, "ax88180: TXCMD=0x%08lx, TXBS=0x%08lx\n", txcmd_txdp, txbs_txdp);	PRINTK(TX_MSG, "ax88180: TXDES0=0x%08lx, TXDES1=0x%08lx, TXDES2=0x%08lx, TXDES3=0x%08lx\n", 		txdes0_val, txdes1_val, txdes2_val, txdes3_val);	pax88180_local->stats.tx_packets++;	pax88180_local->stats.tx_bytes += skb->len;	dev_kfree_skb(skb);	global_dev->trans_start = jiffies;	if (pax88180_local->JumboFlag == ENABLE_JUMBO)		pax88180_local->NextTxDesc += 2;	else 		pax88180_local->NextTxDesc++;	pax88180_local->NextTxDesc &= TXDP_MASK; 	/* Inform upper layer to send next queued packets now *///	netif_wake_queue(global_dev);			//allan9 move to ax88180_tx_handler routine //	spin_unlock_irq(&pax88180_local->lock);	PRINTK(TX_MSG, "ax88180: ax88180_start_xmit end ..........\n\n");	return 0;}/* ***************************************************************************** * ax88180_tx_timeout() ***************************************************************************** */static void ax88180_tx_timeout(struct net_device *global_dev){	struct _AX88180_PRIVATE *pax88180_local;	pax88180_local = (struct _AX88180_PRIVATE *) global_dev->priv;	PRINTK(TX_MSG, "ax88180: ax88180_tx_timeout beginning ..........\n");	RESET_MAC;	INIT_TXRX_VARIABLES;	/* Inform upper layer to send next queued packets now */	global_dev->trans_start = jiffies; 	netif_wake_queue(global_dev);	PRINTK(TX_MSG, "ax88180: ax88180_tx_timeout end ..........\n");	return;}/* ***************************************************************************** * ax88180_get_stats() * * Get the current statistics. This may be called with the card open or closed. * ***************************************************************************** */static struct net_device_stats * ax88180_get_stats(struct net_device *global_dev){	struct _AX88180_PRIVATE *pax88180_local;	unsigned long tmp_regval;	unsigned long flags;	pax88180_local = (struct _AX88180_PRIVATE *) global_dev->priv;	PRINTK(OTHERS_MSG, "ax88180: ax88180_get_stats beginning..........\n");

⌨️ 快捷键说明

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