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

📄 ax88180.c

📁 网络ax88180linux下的驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
	spin_lock_irqsave(&pax88180_local->lock, flags);	//Update the statistics counter here.....	READ_MACREG(RXIPCRCCNT, tmp_regval);	pax88180_local->stats.rx_errors += tmp_regval;	WRITE_MACREG(RXIPCRCCNT, 0);	READ_MACREG(RXCRCCNT, tmp_regval);	pax88180_local->stats.rx_errors += tmp_regval;	WRITE_MACREG(RXCRCCNT, 0);		READ_MACREG(TXFAILCNT, tmp_regval);	pax88180_local->stats.tx_errors += tmp_regval;	WRITE_MACREG(TXFAILCNT, 0);		spin_unlock_irqrestore(&pax88180_local->lock, flags);	PRINTK(OTHERS_MSG, "ax88180: ax88180_get_stats end ..........\n");	return &pax88180_local->stats;}/* ***************************************************************************** * ax88180_set_multicast_list() ***************************************************************************** */static void ax88180_set_multicast_list(struct net_device *global_dev){	struct _AX88180_PRIVATE *pax88180_local;	struct dev_mc_list *mc_list;	unsigned long mc_hash_table[2];	int crc_val,i;	pax88180_local = (struct _AX88180_PRIVATE *) global_dev->priv;	PRINTK(OTHERS_MSG, "ax88180: ax88180_set_multicast_list beginning ..........\n");      	pax88180_local->RxFilterMode = DEFAULT_RXFILTER;	if (global_dev->flags & IFF_PROMISC) {		pax88180_local->RxFilterMode |= RX_RXANY;	} else if (global_dev->flags & IFF_ALLMULTI) {		pax88180_local->RxFilterMode |= RX_MULTICAST;	} else if (global_dev->flags & IFF_MULTICAST) {		pax88180_local->RxFilterMode |= RX_MULTI_HASH;		/* Handle Rx multicast hash table here */		mc_hash_table[0] = mc_hash_table[1] = 0;		for (i = 0, mc_list = global_dev->mc_list; (mc_list != NULL) && (i < global_dev->mc_count); 		     i++, mc_list = mc_list->next) {			crc_val = ether_crc(ETH_ALEN, mc_list->dmi_addr);				set_bit(crc_val >> 26, mc_hash_table);		}		WRITE_MACREG(HASHTAB0, (unsigned int)mc_hash_table[0]);		WRITE_MACREG(HASHTAB1, (unsigned int)(mc_hash_table[0] >> 16));		WRITE_MACREG(HASHTAB2, (unsigned int)mc_hash_table[1]);		WRITE_MACREG(HASHTAB3, (unsigned int)(mc_hash_table[1] >> 16));	}	WRITE_MACREG(RXFILTER, pax88180_local->RxFilterMode);	PRINTK(OTHERS_MSG, "ax88180: ax88180_set_multicast_list end ..........\n");	return;}/* ***************************************************************************** * ax88180_interrupt() * * Handle the network interface interrupts. * *****************************************************************************  */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)static void ax88180_interrupt(int irq, void *global_dev_id, struct pt_regs * regs)#elsestatic irqreturn_t ax88180_interrupt(int irq, void *global_dev_id, struct pt_regs * regs)#endif{	struct net_device *global_dev = global_dev_id;	struct _AX88180_PRIVATE *pax88180_local;	unsigned long ISR_Status;	unsigned long rxcurt_ptr, rxbound_ptr;	unsigned long bmsr_val;	unsigned long tmp_regval;	int i;	pax88180_local = (struct _AX88180_PRIVATE *) global_dev->priv;	/* Read and check interrupt status here...... */	READ_MACREG(ISR, ISR_Status);	if ( (ISR_Status == 0) || (ISR_Status & ~DEFAULT_IMR) ) {//		PRINTK(WARNING_MSG, "ax88180: Not our interrupt!!\n");#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)		return;#else		return 0;#endif	}	PRINTK(INT_MSG, "ax88180: ax88180_interrupt beginning ..........\n");	//allan9 add for debugging//	DISPLAY_ALLMACREG;		//	DISPLAY_ALLPHYREG;	/* Disable AX88180 interrupt */	DISABLE_INTERRUPT;	/* Clear the interrupt status */	WRITE_MACREG(ISR, ISR_Status);	PRINTK(INT_MSG, "ax88180: The interrupt status = 0x%08lx\n", ISR_Status);	/* Handle AX88180 interrupt events */	if (ISR_Status & ISR_WATCHDOG) {		PRINTK(DRIVER_MSG, "ax88180: Watchdog Timer interrupt (ISR = 0x%08lx)\n", ISR_Status);	} 	if (ISR_Status & ISR_RX) {		ax88180_rx_handler(global_dev);	} 	if (ISR_Status & ISR_TX) {		ax88180_tx_handler(global_dev);	} 	if (ISR_Status & ISR_RXBUFFOVR) {		pax88180_local->rxbuf_overflow_count++;		pax88180_local->stats.rx_fifo_errors++;		READ_MACREG(RXCURT, rxcurt_ptr);		READ_MACREG(RXBOUND, rxbound_ptr);		PRINTK(ERROR_MSG, "ax88180: RX Buffer overflow!! (count=%d, RXBOUND=0x%08lx, RXCURT=0x%08lx)\n", 			(int)pax88180_local->rxbuf_overflow_count, rxbound_ptr, rxcurt_ptr);		PRINTK(ERROR_MSG, "ax88180: The interrupt status = 0x%08lx\n", ISR_Status);		if (pax88180_local->rxbuf_overflow_count > 10) {				RESET_MAC;			INIT_TXRX_VARIABLES;		}	} 	if (ISR_Status & ISR_PHY) {		/* Read ISR register once to clear Marvell PHY interrupt bit */		READ_PHYREG(pax88180_local->PhyAddr, M88_ISR, tmp_regval);		/* Waiting 200 msecs for PHY link stable */		for (i = 0; i < 200; i++) {			READ_PHYREG(pax88180_local->PhyAddr, BMSR, bmsr_val);			if (bmsr_val & LINKOK) {				break;			}			mdelay(1);		}		if (bmsr_val & LINKOK) {			PRINTK(WARNING_MSG, "ax88180: The cable is connected.\n");			netif_carrier_on(global_dev);			if (pax88180_local->ForceMedia == AUTO_MEDIA) 				ax88180_meida_config(global_dev);			DISPLAY_ALLPHYREG;		} else {			PRINTK(WARNING_MSG, "ax88180: The cable is disconnected.\n");			netif_carrier_off(global_dev);			DISPLAY_ALLPHYREG;		}	}	/* Enable AX88180 interrupt */	ENABLE_INTERRUPT;	PRINTK(INT_MSG, "ax88180: ax88180_interrupt end ..........\n\n");#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	return;#else	return IRQ_RETVAL(0);#endif}/* * =========================================================================== * <<<<<<             Declare INIT/OTHERS SUB-ROUTINES                  >>>>>> * =========================================================================== *//* ***************************************************************************** * ax88180_initialization() ***************************************************************************** */static int ax88180_initialization(struct net_device *global_dev){	struct _AX88180_PRIVATE *pax88180_local;//	unsigned long flags;	unsigned long macid0_val, macid1_val, macid2_val;	unsigned long tmp_regval;	int i;	pax88180_local = (struct _AX88180_PRIVATE *) global_dev->priv;	PRINTK(INIT_MSG, "ax88180: ax88180_initialization beginning ..........\n");//	spin_lock_irqsave(&pax88180_local->lock, flags);	RESET_MAC;	/* Reload MAC address from EEPROM */	WRITE_MACREG(PROMCTRL, RELOAD_EEPROM);	for (i = 0; i < 500; i++) {		READ_MACREG(PROMCTRL, tmp_regval);		if ((tmp_regval & RELOAD_EEPROM) == 0)			break;		mdelay(1);	}		/* Disable AX88180 interrupt */	DISABLE_INTERRUPT;	/* Disable AX88180 TX/RX functions */	WRITE_MACREG(CMD, WAKEMOD);	/* Get MAC addresses */ 	READ_MACREG(MACID0, macid0_val);	READ_MACREG(MACID1, macid1_val);	READ_MACREG(MACID2, macid2_val);	if ((macid0_val | macid1_val | macid2_val) != 0) {		global_dev->dev_addr[0] = (unsigned char)macid0_val;		global_dev->dev_addr[1] = (unsigned char)(macid0_val >> 8);		global_dev->dev_addr[2] = (unsigned char)macid1_val;		global_dev->dev_addr[3] = (unsigned char)(macid1_val >> 8);		global_dev->dev_addr[4] = (unsigned char)macid2_val;		global_dev->dev_addr[5] = (unsigned char)(macid2_val >> 8);	} else {		/* No EEPROM found!! Set a default MAC address. */		/* The driver designer should assign a legal MAC address here. */		global_dev->dev_addr[0] = 0x00;		global_dev->dev_addr[1] = 0x12;		global_dev->dev_addr[2] = 0x34;		global_dev->dev_addr[3] = 0x56;		global_dev->dev_addr[4] = 0x78;		global_dev->dev_addr[5] = 0x9a;		macid0_val = (global_dev->dev_addr[1] << 8) + global_dev->dev_addr[0];		macid1_val = (global_dev->dev_addr[3] << 8) + global_dev->dev_addr[2];		macid2_val = (global_dev->dev_addr[5] << 8) + global_dev->dev_addr[4];		WRITE_MACREG(MACID0, macid0_val);		WRITE_MACREG(MACID1, macid1_val);		WRITE_MACREG(MACID2, macid2_val);	}			/* Print the MAC address */	PRINTK(DRIVER_MSG, "ax88180: The MAC address is");	for (i = 0; i < ETH_ALEN; i++)		PRINTK(DRIVER_MSG, "%c%02x", i ? ':' : ' ', global_dev->dev_addr[i]);	PRINTK(DRIVER_MSG, "\n");	/* Initial PHY registers */	ax88180_PHY_initial(global_dev);	/* Configure MAC media mode registers */	ax88180_meida_config(global_dev);#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)	/* Initial MII interface information for ethtool ioctl */	pax88180_local->mii_if.dev = global_dev;	pax88180_local->mii_if.phy_id = pax88180_local->PhyAddr;	pax88180_local->mii_if.phy_id_mask = 0x1F;	pax88180_local->mii_if.reg_num_mask = 0x1F;	pax88180_local->mii_if.mdio_read = mdio_read;	pax88180_local->mii_if.mdio_write = mdio_write;	pax88180_local->mii_if.force_media = pax88180_local->ForceMedia; 	pax88180_local->mii_if.full_duplex = pax88180_local->LineSpeed;	pax88180_local->mii_if.force_media = pax88180_local->DuplexMode; #endif	WRITE_MACREG(RXFILTER, DEFAULT_RXFILTER);//	spin_unlock_irqrestore(&pax88180_local->lock, flags);	PRINTK(INIT_MSG, "ax88180: ax88180_initialization end ..........\n");	return 0;}/* ***************************************************************************** * ax88180_PHY_initial() * * Initialize PHY registers.  * ***************************************************************************** */static void ax88180_PHY_initial(struct net_device *global_dev){	struct _AX88180_PRIVATE *pax88180_local;	unsigned long bmcr_val, anar_val, bmsr_val;	unsigned long aux_1000_ctrl;	unsigned long tmp_regval;	unsigned int i;	pax88180_local = (struct _AX88180_PRIVATE *) global_dev->priv;	PRINTK(INIT_MSG, "ax88180: ax88180_PHY_initial beginning ..........\n");	/* Check avaliable PHY chipset  */	pax88180_local->PhyAddr = MARVELL_88E1111_PHYADDR;	READ_PHYREG(pax88180_local->PhyAddr, PHYIDR0, pax88180_local->PhyID0);	if (pax88180_local->PhyID0 == MARVELL_88E1111_PHYIDR0) {		PRINTK(DRIVER_MSG, "ax88180: Found Marvell 88E1111 PHY chipset. (PHY Addr=0x%x)\n", 			(unsigned int)pax88180_local->PhyAddr);		READ_PHYREG(pax88180_local->PhyAddr, M88_EXT_SSR, tmp_regval);		if ((tmp_regval & HWCFG_MODE_MASK) == RGMII_COPPER_MODE) {			WRITE_PHYREG(pax88180_local->PhyAddr, M88_EXT_SCR, DEFAULT_EXT_SCR);			RESET_PHY;			WRITE_PHYREG(pax88180_local->PhyAddr, M88_IER, LINK_CHANGE_INT);		}	} else {		pax88180_local->PhyAddr = CICADA_CIS8201_PHYADDR;		READ_PHYREG(pax88180_local->PhyAddr, PHYIDR0, pax88180_local->PhyID0);		if (pax88180_local->PhyID0 == CICADA_CIS8201_PHYIDR0) {			PRINTK(DRIVER_MSG, "ax88180: Found CICADA CIS8201 PHY chipset. (PHY Addr=0x%x)\n", 				(unsigned int)pax88180_local->PhyAddr);			WRITE_PHYREG(pax88180_local->PhyAddr, CIS_IMR, (CIS_INT_ENABLE | LINK_CHANGE_INT));			/* Set CIS_SMI_PRIORITY bit before force the media mode  */			READ_PHYREG(pax88180_local->PhyAddr, CIS_AUX_CTRL_STATUS, tmp_regval);			tmp_regval &= ~CIS_SMI_PRIORITY;			if (pax88180_local->MediaMode != MEDIA_AUTO)				tmp_regval |= CIS_SMI_PRIORITY;			WRITE_PHYREG(pax88180_local->PhyAddr, CIS_AUX_CTRL_STATUS, tmp_regval);		} else {			PRINTK(ERROR_MSG, "ax88180: Unknown PHY chipset!!\n");			//allan9 add for debugging			DISPLAY_ALLPHYREG;		}	}	PRINTK(INIT_MSG, "ax88180: PHY_Addr=0x%lx, PHY_ID=0x%04x, media=%d\n", 		pax88180_local->PhyAddr, (unsigned int)pax88180_local->PhyID0, media); 	switch (pax88180_local->MediaMode) {	default:	case MEDIA_AUTO:		PRINTK(INIT_MSG, "ax88180: The meida mode is autosense.\n");		pax88180_local->ForceMedia = AUTO_MEDIA;		aux_1000_ctrl = DEFAULT_AUX_1000_CTRL;		anar_val = (ANAR_PAUSE | ANAR_100FULL | ANAR_100HALF | ANAR_10FULL | ANAR_10HALF | ANAR_8023BIT);		break;	case MEDIA_100FULL:		PRINTK(INIT_MSG, "ax88180: The meida mode is forced to 100full.\n");		pax88180_local->ForceMedia = FORCE_MEDIA;		aux_1000_ctrl = 0;		anar_val = (ANAR_PAUSE | ANAR_100FULL | ANAR_8023BIT);		break;	case MEDIA_100HALF:		PRINTK(INIT_MSG, "ax88180: The meida mode is forced to 100half.\n");		pax88180_local->ForceMedia = FORCE_MEDIA;		aux_1000_ctrl = 0;		anar_val = (ANAR_100HALF | ANAR_8023BIT);		break;	case MEDIA_10FULL:		PRINTK(INIT_MSG, "ax88180: The meida mode is forced to 10full.\n");		pax88180_local->ForceMedia = FORCE_MEDIA;		aux_1000_ctrl = 0;		anar_val = (ANAR_PAUSE | ANAR_10FULL | ANAR_8023BIT);		break;	case MEDIA_10HALF:		PRINTK(INIT_MSG, "ax88180: The meida mode is forced to 10half.\n");		pax88180_local->ForceMedia = FORCE_MEDIA;		aux_1000_ctrl = 0;		anar_val = (ANAR_10HALF | ANAR_8023BIT);		break;	}	WRITE_PHYREG(pax88180_local->PhyAddr, AUX_1000_CTRL, aux_1000_ctrl);	WRITE_PHYREG(pax88180_local->PhyAddr, ANAR, anar_val);	/* Enable and restart auto-negotiation operation */	bmcr_val = (AUTONEG_EN | RESTART_AUTONEG);	WRITE_PHYREG(pax88180_local->PhyAddr, BMCR, bmcr_val);	/* Waiting 5 secs for PHY link stable */	PRINTK(DRIVER_MSG, "ax88180: Waiting for auto-negotiation completion......\n");	for (i = 0; i < 5000; i++) {		READ_PHYREG(pax88180_local->PhyAddr, BMSR, bmsr_val);		if (bmsr_val & LINKOK) {			break;		}		mdelay(1);	}	//allan9 add for debugging	DISPLAY_ALLPHYREG;	PRINTK(INIT_MSG, "ax88180: ax88180_PHY_initial end ..........\n");	return;}/* ***************************************************************************** * ax88180_meida_config() * * Configure MAC registers (RXCFG, MACCFG0, MACCFG1) to match the real PHY media mode.  * ***************************************************************************** */static void ax88180_meida_config(struct net_device *global_dev){	struct _AX88180_PRIVATE *pax88180_local;	unsigned long bmcr_val, bmsr_val;	unsigned long rxcfg_val, maccfg0_val, maccfg1_val;	int i;	pax88180_local = (struct _AX88180_PRIVATE *) global_dev->priv;	PRINTK(INIT_MSG, "ax88180: ax88180_meida_config beginning ..........\n");	/* Waiting 200 msecs for PHY link stable */	for (i = 0; i < 200; i++) {		READ_PHYREG(pax88180_local->PhyAddr, BMSR, bmsr_val);		if (bmsr_val & LINKOK) {			break;		}		mdelay(1);	}	//allan9 add for debugging//	DISPLAY_ALLPHYREG;	READ_PHYREG(pax88180_local->PhyAddr, BMSR, bmsr_val);	if (bmsr_val & LINKOK) {		READ_PHYREG(pax88180_local->PhyAddr, BMCR, bmcr_val);		if (bmcr_val & AUTONEG_EN) {			/* Waiting for Auto-negotiation completion */			PRINTK(INIT_MSG, "ax88180: Auto-negotiation is enabled. Waiting for NWay completion.....\n");			for (i = 0; i < 5000; i++) {				if (bmsr_val & AUTONEG_COMPLETE) {					break;				}				mdelay(1);				READ_PHYREG(pax88180_local->PhyAddr, BMSR, bmsr_val);			}			if (i >= 5000)				PRINTK(INIT_MSG, "ax88180: Auto-negotiation is NOT completed!!\n");		} else 			PRINTK(INIT_MSG, "ax88180: Auto-negotiation is disabled.\n");		PRINTK(DEBUG_MSG, "ax88180: BMCR=0x%04x, BMSR=0x%04x\n", 			(unsigned int)bmcr_val, (unsigned int)bmsr_val);		/* Get real media mode here */		if (pax88180_local->PhyID0 == MARVELL_88E1111_PHYIDR0) {			get_MarvellPHY_meida_mode(global_dev);		} else if (pax88180_local->PhyID0 == CICADA_CIS8201_PHYIDR0) {			get_CicadaPHY_meida_mode(global_dev);		} else {			pax88180_local->RealMediaMode = MEDIA_1000FULL;		}		switch (pax88180_local->RealMediaMode) {		default:		case MEDIA_1000FULL:			PRINTK(DRIVER_MSG, "ax88180: Set to 1000Mbps Full-duplex mode.\n");			pax88180_local->LineSpeed = SPEED_1000;			pax88180_local->DuplexMode = DUPLEX_FULL;			rxcfg_val = RXFLOW_ENABLE | DEFAULT_RXCFG;			maccfg0_val = TXFLOW_ENABLE | DEFAULT_MACCFG0;			maccfg1_val = GIGA_MODE_EN | RXFLOW_EN | FULLDUPLEX | DEFAULT_MACCFG1;

⌨️ 快捷键说明

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