qla3xxx.c

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

C
2,557
字号
}static int ql_is_full_dup(struct ql3_adapter *qdev){	u16 reg;	switch(qdev->phyType) {	case PHY_AGERE_ET1011C:	{		if (ql_mii_read_reg(qdev, 0x1A, &reg))			return 0;		return ((reg & 0x0080) && (reg & 0x1000)) != 0;	}	case PHY_VITESSE_VSC8211:	default:	{		if (ql_mii_read_reg(qdev, AUX_CONTROL_STATUS, &reg) < 0)			return 0;		return (reg & PHY_AUX_DUPLEX_STAT) != 0;	}	}}static int ql_is_phy_neg_pause(struct ql3_adapter *qdev){	u16 reg;	if (ql_mii_read_reg(qdev, PHY_NEG_PARTNER, &reg) < 0)		return 0;	return (reg & PHY_NEG_PAUSE) != 0;}static int PHY_Setup(struct ql3_adapter *qdev){	u16   reg1;	u16   reg2;	bool  agereAddrChangeNeeded = false;	u32 miiAddr = 0;	int err;	/*  Determine the PHY we are using by reading the ID's */	err = ql_mii_read_reg(qdev, PHY_ID_0_REG, &reg1);	if(err != 0) {		printk(KERN_ERR "%s: Could not read from reg PHY_ID_0_REG\n",		       qdev->ndev->name);                return err;	}	err = ql_mii_read_reg(qdev, PHY_ID_1_REG, &reg2);	if(err != 0) {		printk(KERN_ERR "%s: Could not read from reg PHY_ID_0_REG\n",		       qdev->ndev->name);                return err;	}	/*  Check if we have a Agere PHY */	if ((reg1 == 0xffff) || (reg2 == 0xffff)) {		/* Determine which MII address we should be using		   determined by the index of the card */		if (qdev->mac_index == 0) {			miiAddr = MII_AGERE_ADDR_1;		} else {			miiAddr = MII_AGERE_ADDR_2;		}		err =ql_mii_read_reg_ex(qdev, PHY_ID_0_REG, &reg1, miiAddr);		if(err != 0) {			printk(KERN_ERR "%s: Could not read from reg PHY_ID_0_REG after Agere detected\n",		       	       qdev->ndev->name);			return err;		}		err = ql_mii_read_reg_ex(qdev, PHY_ID_1_REG, &reg2, miiAddr);		if(err != 0) {			printk(KERN_ERR "%s: Could not read from reg PHY_ID_0_REG after Agere detected\n",			       qdev->ndev->name);        	        return err;		}		/*  We need to remember to initialize the Agere PHY */		agereAddrChangeNeeded = true;	}	/*  Determine the particular PHY we have on board to apply	    PHY specific initializations */	qdev->phyType = getPhyType(qdev, reg1, reg2);	if ((qdev->phyType == PHY_AGERE_ET1011C) && agereAddrChangeNeeded) {		/* need this here so address gets changed */		phyAgereSpecificInit(qdev, miiAddr);	} else if (qdev->phyType == PHY_TYPE_UNKNOWN) {		printk(KERN_ERR "%s: PHY is unknown\n", qdev->ndev->name);		return -EIO;	}	return 0;}/* * Caller holds hw_lock. */static void ql_mac_enable(struct ql3_adapter *qdev, u32 enable){	struct ql3xxx_port_registers __iomem *port_regs =	    		qdev->mem_map_registers;	u32 value;	if (enable)		value = (MAC_CONFIG_REG_PE | (MAC_CONFIG_REG_PE << 16));	else		value = (MAC_CONFIG_REG_PE << 16);	if (qdev->mac_index)		ql_write_page0_reg(qdev, &port_regs->mac1ConfigReg, value);	else		ql_write_page0_reg(qdev, &port_regs->mac0ConfigReg, value);}/* * Caller holds hw_lock. */static void ql_mac_cfg_soft_reset(struct ql3_adapter *qdev, u32 enable){	struct ql3xxx_port_registers __iomem *port_regs =	    		qdev->mem_map_registers;	u32 value;	if (enable)		value = (MAC_CONFIG_REG_SR | (MAC_CONFIG_REG_SR << 16));	else		value = (MAC_CONFIG_REG_SR << 16);	if (qdev->mac_index)		ql_write_page0_reg(qdev, &port_regs->mac1ConfigReg, value);	else		ql_write_page0_reg(qdev, &port_regs->mac0ConfigReg, value);}/* * Caller holds hw_lock. */static void ql_mac_cfg_gig(struct ql3_adapter *qdev, u32 enable){	struct ql3xxx_port_registers __iomem *port_regs =	    		qdev->mem_map_registers;	u32 value;	if (enable)		value = (MAC_CONFIG_REG_GM | (MAC_CONFIG_REG_GM << 16));	else		value = (MAC_CONFIG_REG_GM << 16);	if (qdev->mac_index)		ql_write_page0_reg(qdev, &port_regs->mac1ConfigReg, value);	else		ql_write_page0_reg(qdev, &port_regs->mac0ConfigReg, value);}/* * Caller holds hw_lock. */static void ql_mac_cfg_full_dup(struct ql3_adapter *qdev, u32 enable){	struct ql3xxx_port_registers __iomem *port_regs =	    		qdev->mem_map_registers;	u32 value;	if (enable)		value = (MAC_CONFIG_REG_FD | (MAC_CONFIG_REG_FD << 16));	else		value = (MAC_CONFIG_REG_FD << 16);	if (qdev->mac_index)		ql_write_page0_reg(qdev, &port_regs->mac1ConfigReg, value);	else		ql_write_page0_reg(qdev, &port_regs->mac0ConfigReg, value);}/* * Caller holds hw_lock. */static void ql_mac_cfg_pause(struct ql3_adapter *qdev, u32 enable){	struct ql3xxx_port_registers __iomem *port_regs =	    		qdev->mem_map_registers;	u32 value;	if (enable)		value =		    ((MAC_CONFIG_REG_TF | MAC_CONFIG_REG_RF) |		     ((MAC_CONFIG_REG_TF | MAC_CONFIG_REG_RF) << 16));	else		value = ((MAC_CONFIG_REG_TF | MAC_CONFIG_REG_RF) << 16);	if (qdev->mac_index)		ql_write_page0_reg(qdev, &port_regs->mac1ConfigReg, value);	else		ql_write_page0_reg(qdev, &port_regs->mac0ConfigReg, value);}/* * Caller holds hw_lock. */static int ql_is_fiber(struct ql3_adapter *qdev){	struct ql3xxx_port_registers __iomem *port_regs =	    		qdev->mem_map_registers;	u32 bitToCheck = 0;	u32 temp;	switch (qdev->mac_index) {	case 0:		bitToCheck = PORT_STATUS_SM0;		break;	case 1:		bitToCheck = PORT_STATUS_SM1;		break;	}	temp = ql_read_page0_reg(qdev, &port_regs->portStatus);	return (temp & bitToCheck) != 0;}static int ql_is_auto_cfg(struct ql3_adapter *qdev){	u16 reg;	ql_mii_read_reg(qdev, 0x00, &reg);	return (reg & 0x1000) != 0;}/* * Caller holds hw_lock. */static int ql_is_auto_neg_complete(struct ql3_adapter *qdev){	struct ql3xxx_port_registers __iomem *port_regs =	    		qdev->mem_map_registers;	u32 bitToCheck = 0;	u32 temp;	switch (qdev->mac_index) {	case 0:		bitToCheck = PORT_STATUS_AC0;		break;	case 1:		bitToCheck = PORT_STATUS_AC1;		break;	}	temp = ql_read_page0_reg(qdev, &port_regs->portStatus);	if (temp & bitToCheck) {		if (netif_msg_link(qdev))			printk(KERN_INFO PFX			       "%s: Auto-Negotiate complete.\n",			       qdev->ndev->name);		return 1;	} else {		if (netif_msg_link(qdev))			printk(KERN_WARNING PFX			       "%s: Auto-Negotiate incomplete.\n",			       qdev->ndev->name);		return 0;	}}/* *  ql_is_neg_pause() returns 1 if pause was negotiated to be on */static int ql_is_neg_pause(struct ql3_adapter *qdev){	if (ql_is_fiber(qdev))		return ql_is_petbi_neg_pause(qdev);	else		return ql_is_phy_neg_pause(qdev);}static int ql_auto_neg_error(struct ql3_adapter *qdev){	struct ql3xxx_port_registers __iomem *port_regs =	    		qdev->mem_map_registers;	u32 bitToCheck = 0;	u32 temp;	switch (qdev->mac_index) {	case 0:		bitToCheck = PORT_STATUS_AE0;		break;	case 1:		bitToCheck = PORT_STATUS_AE1;		break;	}	temp = ql_read_page0_reg(qdev, &port_regs->portStatus);	return (temp & bitToCheck) != 0;}static u32 ql_get_link_speed(struct ql3_adapter *qdev){	if (ql_is_fiber(qdev))		return SPEED_1000;	else		return ql_phy_get_speed(qdev);}static int ql_is_link_full_dup(struct ql3_adapter *qdev){	if (ql_is_fiber(qdev))		return 1;	else		return ql_is_full_dup(qdev);}/* * Caller holds hw_lock. */static int ql_link_down_detect(struct ql3_adapter *qdev){	struct ql3xxx_port_registers __iomem *port_regs =	    		qdev->mem_map_registers;	u32 bitToCheck = 0;	u32 temp;	switch (qdev->mac_index) {	case 0:		bitToCheck = ISP_CONTROL_LINK_DN_0;		break;	case 1:		bitToCheck = ISP_CONTROL_LINK_DN_1;		break;	}	temp =	    ql_read_common_reg(qdev, &port_regs->CommonRegs.ispControlStatus);	return (temp & bitToCheck) != 0;}/* * Caller holds hw_lock. */static int ql_link_down_detect_clear(struct ql3_adapter *qdev){	struct ql3xxx_port_registers __iomem *port_regs =	    		qdev->mem_map_registers;	switch (qdev->mac_index) {	case 0:		ql_write_common_reg(qdev,				    &port_regs->CommonRegs.ispControlStatus,				    (ISP_CONTROL_LINK_DN_0) |				    (ISP_CONTROL_LINK_DN_0 << 16));		break;	case 1:		ql_write_common_reg(qdev,				    &port_regs->CommonRegs.ispControlStatus,				    (ISP_CONTROL_LINK_DN_1) |				    (ISP_CONTROL_LINK_DN_1 << 16));		break;	default:		return 1;	}	return 0;}/* * Caller holds hw_lock. */static int ql_this_adapter_controls_port(struct ql3_adapter *qdev){	struct ql3xxx_port_registers __iomem *port_regs =	    		qdev->mem_map_registers;	u32 bitToCheck = 0;	u32 temp;	switch (qdev->mac_index) {	case 0:		bitToCheck = PORT_STATUS_F1_ENABLED;		break;	case 1:		bitToCheck = PORT_STATUS_F3_ENABLED;		break;	default:		break;	}	temp = ql_read_page0_reg(qdev, &port_regs->portStatus);	if (temp & bitToCheck) {		if (netif_msg_link(qdev))			printk(KERN_DEBUG PFX			       "%s: is not link master.\n", qdev->ndev->name);		return 0;	} else {		if (netif_msg_link(qdev))			printk(KERN_DEBUG PFX			       "%s: is link master.\n", qdev->ndev->name);		return 1;	}}static void ql_phy_reset_ex(struct ql3_adapter *qdev){	ql_mii_write_reg_ex(qdev, CONTROL_REG, PHY_CTRL_SOFT_RESET,			    PHYAddr[qdev->mac_index]);}static void ql_phy_start_neg_ex(struct ql3_adapter *qdev){	u16 reg;	u16 portConfiguration;	if(qdev->phyType == PHY_AGERE_ET1011C) {		/* turn off external loopback */		ql_mii_write_reg(qdev, 0x13, 0x0000);	}	if(qdev->mac_index == 0)		portConfiguration = qdev->nvram_data.macCfg_port0.portConfiguration;	else		portConfiguration = qdev->nvram_data.macCfg_port1.portConfiguration;	/*  Some HBA's in the field are set to 0 and they need to	    be reinterpreted with a default value */	if(portConfiguration == 0)		portConfiguration = PORT_CONFIG_DEFAULT;	/* Set the 1000 advertisements */	ql_mii_read_reg_ex(qdev, PHY_GIG_CONTROL, &reg,			   PHYAddr[qdev->mac_index]);	reg &= ~PHY_GIG_ALL_PARAMS;	if(portConfiguration & PORT_CONFIG_1000MB_SPEED) {		if(portConfiguration & PORT_CONFIG_FULL_DUPLEX_ENABLED) 			reg |= PHY_GIG_ADV_1000F;		else 			reg |= PHY_GIG_ADV_1000H;	}	ql_mii_write_reg_ex(qdev, PHY_GIG_CONTROL, reg,			    PHYAddr[qdev->mac_index]);	/* Set the 10/100 & pause negotiation advertisements */	ql_mii_read_reg_ex(qdev, PHY_NEG_ADVER, &reg,			   PHYAddr[qdev->mac_index]);	reg &= ~PHY_NEG_ALL_PARAMS;	if(portConfiguration & PORT_CONFIG_SYM_PAUSE_ENABLED)		reg |= PHY_NEG_ASY_PAUSE | PHY_NEG_SYM_PAUSE;	if(portConfiguration & PORT_CONFIG_FULL_DUPLEX_ENABLED) {		if(portConfiguration & PORT_CONFIG_100MB_SPEED)			reg |= PHY_NEG_ADV_100F;		if(portConfiguration & PORT_CONFIG_10MB_SPEED)			reg |= PHY_NEG_ADV_10F;	}	if(portConfiguration & PORT_CONFIG_HALF_DUPLEX_ENABLED) {		if(portConfiguration & PORT_CONFIG_100MB_SPEED)			reg |= PHY_NEG_ADV_100H;		if(portConfiguration & PORT_CONFIG_10MB_SPEED)			reg |= PHY_NEG_ADV_10H;	}	if(portConfiguration &	   PORT_CONFIG_1000MB_SPEED) {		reg |= 1;	}	ql_mii_write_reg_ex(qdev, PHY_NEG_ADVER, reg,			    PHYAddr[qdev->mac_index]);	ql_mii_read_reg_ex(qdev, CONTROL_REG, &reg, PHYAddr[qdev->mac_index]);	ql_mii_write_reg_ex(qdev, CONTROL_REG,			    reg | PHY_CTRL_RESTART_NEG | PHY_CTRL_AUTO_NEG,			    PHYAddr[qdev->mac_index]);}static void ql_phy_init_ex(struct ql3_adapter *qdev){	ql_phy_reset_ex(qdev);	PHY_Setup(qdev);	ql_phy_start_neg_ex(qdev);}/* * Caller holds hw_lock. */static u32 ql_get_link_state(struct ql3_adapter *qdev){	struct ql3xxx_port_registers __iomem *port_regs =	    		qdev->mem_map_registers;	u32 bitToCheck = 0;	u32 temp, linkState;	switch (qdev->mac_index) {	case 0:		bitToCheck = PORT_STATUS_UP0;		break;	case 1:		bitToCheck = PORT_STATUS_UP1;		break;	}	temp = ql_read_page0_reg(qdev, &port_regs->portStatus);	if (temp & bitToCheck) {		linkState = LS_UP;	} else {

⌨️ 快捷键说明

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