qla3xxx.c

来自「linux 内核源代码」· C语言 代码 · 共 2,557 行 · 第 1/5 页

C
2,557
字号
				    serialPortInterfaceReg,				    ISP_NVRAM_MASK | qdev->eeprom_cmd_data |				    AUBURN_EEPROM_CLK_RISE);		ql_write_nvram_reg(qdev,				    &port_regs->CommonRegs.				    serialPortInterfaceReg,				    ISP_NVRAM_MASK | qdev->eeprom_cmd_data |				    AUBURN_EEPROM_CLK_FALL);		dataBit =		    (ql_read_common_reg		     (qdev,		      &port_regs->CommonRegs.		      serialPortInterfaceReg) & AUBURN_EEPROM_DI_1) ? 1 : 0;		data = (data << 1) | dataBit;	}	*value = (u16) data;}/* * Caller holds hw_lock. */static void eeprom_readword(struct ql3_adapter *qdev,			    u32 eepromAddr, unsigned short *value){	fm93c56a_select(qdev);	fm93c56a_cmd(qdev, (int)FM93C56A_READ, eepromAddr);	fm93c56a_datain(qdev, value);	fm93c56a_deselect(qdev);}static void ql_swap_mac_addr(u8 * macAddress){#ifdef __BIG_ENDIAN	u8 temp;	temp = macAddress[0];	macAddress[0] = macAddress[1];	macAddress[1] = temp;	temp = macAddress[2];	macAddress[2] = macAddress[3];	macAddress[3] = temp;	temp = macAddress[4];	macAddress[4] = macAddress[5];	macAddress[5] = temp;#endif}static int ql_get_nvram_params(struct ql3_adapter *qdev){	u16 *pEEPROMData;	u16 checksum = 0;	u32 index;	unsigned long hw_flags;	spin_lock_irqsave(&qdev->hw_lock, hw_flags);	pEEPROMData = (u16 *) & qdev->nvram_data;	qdev->eeprom_cmd_data = 0;	if(ql_sem_spinlock(qdev, QL_NVRAM_SEM_MASK,			(QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) *			 2) << 10)) {		printk(KERN_ERR PFX"%s: Failed ql_sem_spinlock().\n",			__func__);		spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);		return -1;	}	for (index = 0; index < EEPROM_SIZE; index++) {		eeprom_readword(qdev, index, pEEPROMData);		checksum += *pEEPROMData;		pEEPROMData++;	}	ql_sem_unlock(qdev, QL_NVRAM_SEM_MASK);	if (checksum != 0) {		printk(KERN_ERR PFX "%s: checksum should be zero, is %x!!\n",		       qdev->ndev->name, checksum);		spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);		return -1;	}	/*	 * We have a problem with endianness for the MAC addresses	 * and the two 8-bit values version, and numPorts.  We	 * have to swap them on big endian systems.	 */	ql_swap_mac_addr(qdev->nvram_data.funcCfg_fn0.macAddress);	ql_swap_mac_addr(qdev->nvram_data.funcCfg_fn1.macAddress);	ql_swap_mac_addr(qdev->nvram_data.funcCfg_fn2.macAddress);	ql_swap_mac_addr(qdev->nvram_data.funcCfg_fn3.macAddress);	pEEPROMData = (u16 *) & qdev->nvram_data.version;	*pEEPROMData = le16_to_cpu(*pEEPROMData);	spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);	return checksum;}static const u32 PHYAddr[2] = {	PORT0_PHY_ADDRESS, PORT1_PHY_ADDRESS};static int ql_wait_for_mii_ready(struct ql3_adapter *qdev){	struct ql3xxx_port_registers __iomem *port_regs =	    		qdev->mem_map_registers;	u32 temp;	int count = 1000;	while (count) {		temp = ql_read_page0_reg(qdev, &port_regs->macMIIStatusReg);		if (!(temp & MAC_MII_STATUS_BSY))			return 0;		udelay(10);		count--;	}	return -1;}static void ql_mii_enable_scan_mode(struct ql3_adapter *qdev){	struct ql3xxx_port_registers __iomem *port_regs =	    		qdev->mem_map_registers;	u32 scanControl;	if (qdev->numPorts > 1) {		/* Auto scan will cycle through multiple ports */		scanControl = MAC_MII_CONTROL_AS | MAC_MII_CONTROL_SC;	} else {		scanControl = MAC_MII_CONTROL_SC;	}	/*	 * Scan register 1 of PHY/PETBI,	 * Set up to scan both devices	 * The autoscan starts from the first register, completes	 * the last one before rolling over to the first	 */	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg,			   PHYAddr[0] | MII_SCAN_REGISTER);	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg,			   (scanControl) |			   ((MAC_MII_CONTROL_SC | MAC_MII_CONTROL_AS) << 16));}static u8 ql_mii_disable_scan_mode(struct ql3_adapter *qdev){	u8 ret;	struct ql3xxx_port_registers __iomem *port_regs =	    				qdev->mem_map_registers;	/* See if scan mode is enabled before we turn it off */	if (ql_read_page0_reg(qdev, &port_regs->macMIIMgmtControlReg) &	    (MAC_MII_CONTROL_AS | MAC_MII_CONTROL_SC)) {		/* Scan is enabled */		ret = 1;	} else {		/* Scan is disabled */		ret = 0;	}	/*	 * When disabling scan mode you must first change the MII register	 * address	 */	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg,			   PHYAddr[0] | MII_SCAN_REGISTER);	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg,			   ((MAC_MII_CONTROL_SC | MAC_MII_CONTROL_AS |			     MAC_MII_CONTROL_RC) << 16));	return ret;}static int ql_mii_write_reg_ex(struct ql3_adapter *qdev,			       u16 regAddr, u16 value, u32 phyAddr){	struct ql3xxx_port_registers __iomem *port_regs =	    		qdev->mem_map_registers;	u8 scanWasEnabled;	scanWasEnabled = ql_mii_disable_scan_mode(qdev);	if (ql_wait_for_mii_ready(qdev)) {		if (netif_msg_link(qdev))			printk(KERN_WARNING PFX			       "%s Timed out waiting for management port to "			       "get free before issuing command.\n",			       qdev->ndev->name);		return -1;	}	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg,			   phyAddr | regAddr);	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtDataReg, value);	/* Wait for write to complete 9/10/04 SJP */	if (ql_wait_for_mii_ready(qdev)) {		if (netif_msg_link(qdev))			printk(KERN_WARNING PFX			       "%s: Timed out waiting for management port to"			       "get free before issuing command.\n",			       qdev->ndev->name);		return -1;	}	if (scanWasEnabled)		ql_mii_enable_scan_mode(qdev);	return 0;}static int ql_mii_read_reg_ex(struct ql3_adapter *qdev, u16 regAddr,			      u16 * value, u32 phyAddr){	struct ql3xxx_port_registers __iomem *port_regs =	    		qdev->mem_map_registers;	u8 scanWasEnabled;	u32 temp;	scanWasEnabled = ql_mii_disable_scan_mode(qdev);	if (ql_wait_for_mii_ready(qdev)) {		if (netif_msg_link(qdev))			printk(KERN_WARNING PFX			       "%s: Timed out waiting for management port to "			       "get free before issuing command.\n",			       qdev->ndev->name);		return -1;	}	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg,			   phyAddr | regAddr);	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg,			   (MAC_MII_CONTROL_RC << 16));	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg,			   (MAC_MII_CONTROL_RC << 16) | MAC_MII_CONTROL_RC);	/* Wait for the read to complete */	if (ql_wait_for_mii_ready(qdev)) {		if (netif_msg_link(qdev))			printk(KERN_WARNING PFX			       "%s: Timed out waiting for management port to "			       "get free after issuing command.\n",			       qdev->ndev->name);		return -1;	}	temp = ql_read_page0_reg(qdev, &port_regs->macMIIMgmtDataReg);	*value = (u16) temp;	if (scanWasEnabled)		ql_mii_enable_scan_mode(qdev);	return 0;}static int ql_mii_write_reg(struct ql3_adapter *qdev, u16 regAddr, u16 value){	struct ql3xxx_port_registers __iomem *port_regs =	    		qdev->mem_map_registers;	ql_mii_disable_scan_mode(qdev);	if (ql_wait_for_mii_ready(qdev)) {		if (netif_msg_link(qdev))			printk(KERN_WARNING PFX			       "%s: Timed out waiting for management port to "			       "get free before issuing command.\n",			       qdev->ndev->name);		return -1;	}	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg,			   qdev->PHYAddr | regAddr);	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtDataReg, value);	/* Wait for write to complete. */	if (ql_wait_for_mii_ready(qdev)) {		if (netif_msg_link(qdev))			printk(KERN_WARNING PFX			       "%s: Timed out waiting for management port to "			       "get free before issuing command.\n",			       qdev->ndev->name);		return -1;	}	ql_mii_enable_scan_mode(qdev);	return 0;}static int ql_mii_read_reg(struct ql3_adapter *qdev, u16 regAddr, u16 *value){	u32 temp;	struct ql3xxx_port_registers __iomem *port_regs =	    		qdev->mem_map_registers;	ql_mii_disable_scan_mode(qdev);	if (ql_wait_for_mii_ready(qdev)) {		if (netif_msg_link(qdev))			printk(KERN_WARNING PFX			       "%s: Timed out waiting for management port to "			       "get free before issuing command.\n",			       qdev->ndev->name);		return -1;	}	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg,			   qdev->PHYAddr | regAddr);	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg,			   (MAC_MII_CONTROL_RC << 16));	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg,			   (MAC_MII_CONTROL_RC << 16) | MAC_MII_CONTROL_RC);	/* Wait for the read to complete */	if (ql_wait_for_mii_ready(qdev)) {		if (netif_msg_link(qdev))			printk(KERN_WARNING PFX			       "%s: Timed out waiting for management port to "			       "get free before issuing command.\n",			       qdev->ndev->name);		return -1;	}	temp = ql_read_page0_reg(qdev, &port_regs->macMIIMgmtDataReg);	*value = (u16) temp;	ql_mii_enable_scan_mode(qdev);	return 0;}static void ql_petbi_reset(struct ql3_adapter *qdev){	ql_mii_write_reg(qdev, PETBI_CONTROL_REG, PETBI_CTRL_SOFT_RESET);}static void ql_petbi_start_neg(struct ql3_adapter *qdev){	u16 reg;	/* Enable Auto-negotiation sense */	ql_mii_read_reg(qdev, PETBI_TBI_CTRL, &reg);	reg |= PETBI_TBI_AUTO_SENSE;	ql_mii_write_reg(qdev, PETBI_TBI_CTRL, reg);	ql_mii_write_reg(qdev, PETBI_NEG_ADVER,			 PETBI_NEG_PAUSE | PETBI_NEG_DUPLEX);	ql_mii_write_reg(qdev, PETBI_CONTROL_REG,			 PETBI_CTRL_AUTO_NEG | PETBI_CTRL_RESTART_NEG |			 PETBI_CTRL_FULL_DUPLEX | PETBI_CTRL_SPEED_1000);}static void ql_petbi_reset_ex(struct ql3_adapter *qdev){	ql_mii_write_reg_ex(qdev, PETBI_CONTROL_REG, PETBI_CTRL_SOFT_RESET,			    PHYAddr[qdev->mac_index]);}static void ql_petbi_start_neg_ex(struct ql3_adapter *qdev){	u16 reg;	/* Enable Auto-negotiation sense */	ql_mii_read_reg_ex(qdev, PETBI_TBI_CTRL, &reg,			   PHYAddr[qdev->mac_index]);	reg |= PETBI_TBI_AUTO_SENSE;	ql_mii_write_reg_ex(qdev, PETBI_TBI_CTRL, reg,			    PHYAddr[qdev->mac_index]);	ql_mii_write_reg_ex(qdev, PETBI_NEG_ADVER,			    PETBI_NEG_PAUSE | PETBI_NEG_DUPLEX,			    PHYAddr[qdev->mac_index]);	ql_mii_write_reg_ex(qdev, PETBI_CONTROL_REG,			    PETBI_CTRL_AUTO_NEG | PETBI_CTRL_RESTART_NEG |			    PETBI_CTRL_FULL_DUPLEX | PETBI_CTRL_SPEED_1000,			    PHYAddr[qdev->mac_index]);}static void ql_petbi_init(struct ql3_adapter *qdev){	ql_petbi_reset(qdev);	ql_petbi_start_neg(qdev);}static void ql_petbi_init_ex(struct ql3_adapter *qdev){	ql_petbi_reset_ex(qdev);	ql_petbi_start_neg_ex(qdev);}static int ql_is_petbi_neg_pause(struct ql3_adapter *qdev){	u16 reg;	if (ql_mii_read_reg(qdev, PETBI_NEG_PARTNER, &reg) < 0)		return 0;	return (reg & PETBI_NEG_PAUSE_MASK) == PETBI_NEG_PAUSE;}static void phyAgereSpecificInit(struct ql3_adapter *qdev, u32 miiAddr){	printk(KERN_INFO "%s: enabling Agere specific PHY\n", qdev->ndev->name);	/* power down device bit 11 = 1 */	ql_mii_write_reg_ex(qdev, 0x00, 0x1940, miiAddr);	/* enable diagnostic mode bit 2 = 1 */	ql_mii_write_reg_ex(qdev, 0x12, 0x840e, miiAddr);	/* 1000MB amplitude adjust (see Agere errata) */	ql_mii_write_reg_ex(qdev, 0x10, 0x8805, miiAddr);	/* 1000MB amplitude adjust (see Agere errata) */	ql_mii_write_reg_ex(qdev, 0x11, 0xf03e, miiAddr);	/* 100MB amplitude adjust (see Agere errata) */	ql_mii_write_reg_ex(qdev, 0x10, 0x8806, miiAddr);	/* 100MB amplitude adjust (see Agere errata) */	ql_mii_write_reg_ex(qdev, 0x11, 0x003e, miiAddr);	/* 10MB amplitude adjust (see Agere errata) */	ql_mii_write_reg_ex(qdev, 0x10, 0x8807, miiAddr);	/* 10MB amplitude adjust (see Agere errata) */	ql_mii_write_reg_ex(qdev, 0x11, 0x1f00, miiAddr);	/* point to hidden reg 0x2806 */	ql_mii_write_reg_ex(qdev, 0x10, 0x2806, miiAddr);	/* Write new PHYAD w/bit 5 set */	ql_mii_write_reg_ex(qdev, 0x11, 0x0020 | (PHYAddr[qdev->mac_index] >> 8), miiAddr);	/*	 * Disable diagnostic mode bit 2 = 0	 * Power up device bit 11 = 0	 * Link up (on) and activity (blink)	 */	ql_mii_write_reg(qdev, 0x12, 0x840a);	ql_mii_write_reg(qdev, 0x00, 0x1140);	ql_mii_write_reg(qdev, 0x1c, 0xfaf0);}static PHY_DEVICE_et getPhyType (struct ql3_adapter *qdev,				 u16 phyIdReg0, u16 phyIdReg1){	PHY_DEVICE_et result = PHY_TYPE_UNKNOWN;	u32   oui;	u16   model;	int i;	if (phyIdReg0 == 0xffff) {		return result;	}	if (phyIdReg1 == 0xffff) {		return result;	}	/* oui is split between two registers */	oui = (phyIdReg0 << 6) | ((phyIdReg1 & PHY_OUI_1_MASK) >> 10);	model = (phyIdReg1 & PHY_MODEL_MASK) >> 4;	/* Scan table for this PHY */	for(i = 0; i < MAX_PHY_DEV_TYPES; i++) {		if ((oui == PHY_DEVICES[i].phyIdOUI) && (model == PHY_DEVICES[i].phyIdModel))		{			result = PHY_DEVICES[i].phyDevice;			printk(KERN_INFO "%s: Phy: %s\n",				qdev->ndev->name, PHY_DEVICES[i].name);		        break;		}	}	return result;}static int ql_phy_get_speed(struct ql3_adapter *qdev){	u16 reg;	switch(qdev->phyType) {	case PHY_AGERE_ET1011C:	{		if (ql_mii_read_reg(qdev, 0x1A, &reg) < 0)			return 0;		reg = (reg >> 8) & 3;		break;	}	default:	if (ql_mii_read_reg(qdev, AUX_CONTROL_STATUS, &reg) < 0)		return 0;	reg = (((reg & 0x18) >> 3) & 3);	}	switch(reg) {		case 2:		return SPEED_1000;		case 1:		return SPEED_100;		case 0:		return SPEED_10;		default:		return -1;	}

⌨️ 快捷键说明

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