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

📄 e100_phy.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
 * */unsigned chare100_phy_check(struct e100_private *bdp){	unsigned char old_link;	unsigned char changed = false;	old_link = netif_carrier_ok(bdp->device) ? 1 : 0;	e100_find_speed_duplex(bdp);	if (!old_link && netif_carrier_ok(bdp->device)) {		e100_set_fc(bdp);		changed = true;	}	if (old_link && !netif_carrier_ok(bdp->device)) {		/* reset the zero lock state */		bdp->zlock_state = ZLOCK_INITIAL;		// set auto lock for phy auto-negotiation on link up		if ((bdp->PhyId & PHY_MODEL_REV_ID_MASK) == PHY_82555_TX)			e100_mdi_write(bdp, PHY_82555_MDI_EQUALIZER_CSR,				       bdp->phy_addr, 0);		changed = true;	}	e100_phy_fix_squelch(bdp);	e100_handle_zlock(bdp);	return changed;}/*  * Procedure:	e100_auto_neg * * Description: This routine will start autonegotiation and wait *		     for it to complete * * Arguments: *	bdp		- pointer to this card's e100_bdconfig structure *	force_restart	- defines if autoneg should be restarted even if it *			has been completed before * Returns: *	NOTHING */static voide100_auto_neg(struct e100_private *bdp, unsigned char force_restart){	u16 stat_reg;	unsigned long expires;	bdp->flags &= ~DF_SPEED_FORCED;	e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg);	e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg);	/* if we are capable of performing autoneg then we restart if needed */	if ((stat_reg != 0xFFFF) && (stat_reg & BMSR_ANEGCAPABLE)) {		if ((!force_restart) &&		    (stat_reg & BMSR_ANEGCOMPLETE)) {			goto exit;		}		e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr,			       BMCR_ANENABLE | BMCR_ANRESTART);		/* wait for autoneg to complete (up to 3 seconds) */		expires = jiffies + HZ * 3;		do {			/* now re-read the value. Sticky so read twice */			e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg);			e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg);			if ((stat_reg & BMSR_ANEGCOMPLETE) ||			    time_after(jiffies, expires) ) {				goto exit;			} else {				yield();			}		} while (true);	}exit:	e100_find_speed_duplex(bdp);}voide100_phy_set_speed_duplex(struct e100_private *bdp, unsigned char force_restart){	if (bdp->params.e100_speed_duplex == E100_AUTONEG) {        	if (bdp->rev_id >= D102_REV_ID) 			/* Enable MDI/MDI-X auto switching */                	e100_mdi_write(bdp, MII_NCONFIG, bdp->phy_addr,		                       MDI_MDIX_AUTO_SWITCH_ENABLE);		e100_auto_neg(bdp, force_restart);	} else {        	if (bdp->rev_id >= D102_REV_ID) 			/* Disable MDI/MDI-X auto switching */                	e100_mdi_write(bdp, MII_NCONFIG, bdp->phy_addr,		                       MDI_MDIX_RESET_ALL_MASK);		e100_force_speed_duplex(bdp);	}	e100_set_fc(bdp);}voide100_phy_autoneg(struct e100_private *bdp){	u16 ctrl_reg;	ctrl_reg = BMCR_ANENABLE | BMCR_ANRESTART | BMCR_RESET;	e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, ctrl_reg);	udelay(100);}voide100_phy_set_loopback(struct e100_private *bdp){	u16 ctrl_reg;	ctrl_reg = BMCR_LOOPBACK;	e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, ctrl_reg);		udelay(100);}	voide100_phy_reset(struct e100_private *bdp){	u16 ctrl_reg;	ctrl_reg = BMCR_RESET;	e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, ctrl_reg);	/* ieee 802.3 : The reset process shall be completed       */	/* within 0.5 seconds from the settting of PHY reset bit.  */	set_current_state(TASK_UNINTERRUPTIBLE);	schedule_timeout(HZ / 2);}unsigned chare100_phy_init(struct e100_private *bdp){	e100_phy_reset(bdp);	e100_phy_address_detect(bdp);	e100_phy_isolate(bdp);	e100_phy_id_detect(bdp);	if (!e100_phy_specific_setup(bdp))		return false;	bdp->PhyState = 0;	bdp->PhyDelay = 0;	bdp->zlock_state = ZLOCK_INITIAL;	e100_phy_set_speed_duplex(bdp, false);	e100_fix_polarity(bdp);	return true;}/*  * Procedure: e100_get_link_state *  * Description: This routine checks the link status of the adapter * * Arguments:  bdp - Pointer to the e100_private structure for the board *		     * * Returns: true - If a link is found *		false - If there is no link * */unsigned chare100_get_link_state(struct e100_private *bdp){	unsigned char link = false;	u16 status;	/* Check link status */	/* If the controller is a 82559 or later one, link status is available	 * from the CSR. This avoids the mdi_read. */	if (bdp->rev_id >= D101MA_REV_ID) {		if (readb(&bdp->scb->scb_ext.d101m_scb.scb_gen_stat) & BIT_0) {			link = true;		} else {			link = false;		}	} else {		/* Read the status register twice because of sticky bits */		e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &status);		e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &status);		if (status & BMSR_LSTATUS) {			link = true;		} else {			link = false;		}	}	return link;}/*  * Procedure: e100_update_link_state *  * Description: This routine updates the link status of the adapter, * 		also considering netif_running * * Arguments:  bdp - Pointer to the e100_private structure for the board *		     * * Returns: true - If a link is found *		false - If there is no link * */unsigned chare100_update_link_state(struct e100_private *bdp){	unsigned char link;	/* Logical AND PHY link & netif_running */	link = e100_get_link_state(bdp) && netif_running(bdp->device);	if (link) {		if (!netif_carrier_ok(bdp->device))			netif_carrier_on(bdp->device);	} else {		if (netif_carrier_ok(bdp->device))			netif_carrier_off(bdp->device);	}	return link;}/**************************************************************************\ ** ** PROC NAME:     e100_handle_zlock **    This function manages a state machine that controls **    the driver's zero locking algorithm. **    This function is called by e100_watchdog() every ~2 second. ** States: **    The current link handling state is stored in  **    bdp->zlock_state, and is one of: **    ZLOCK_INITIAL, ZLOCK_READING, ZLOCK_SLEEPING **    Detailed description of the states and the transitions **    between states is found below. **    Note that any time the link is down / there is a reset **    state will be changed outside this function to ZLOCK_INITIAL ** Algorithm: **    1. If link is up & 100 Mbps continue else stay in #1: **    2. Set 'auto lock' **    3. Read & Store 100 times 'Zero' locked in 1 sec interval **    4. If max zero read >= 0xB continue else goto 1 **    5. Set most popular 'Zero' read in #3 **    6. Sleep 5 minutes **    7. Read number of errors, if it is > 300 goto 2 else goto 6 ** Data Structures (in DRIVER_DATA): **    zlock_state           - current state of the algorithm **    zlock_read_cnt        - counts number of reads (up to 100) **    zlock_read_data[i]    - counts number of times 'Zero' read was i, 0 <= i <= 15 **    zlock_sleep_cnt       - keeps track of "sleep" time (up to 300 secs = 5 minutes) **                                 ** Parameters:    DRIVER_DATA    *bdp ** **                bdp  - Pointer to HSM's adapter data space ** ** Return Value:  NONE ** ** See Also:      e100_watchdog() ** \**************************************************************************/voide100_handle_zlock(struct e100_private *bdp){	u16 pos;	u16 eq_reg;	u16 err_cnt;	u8 mpz;			/* Most Popular Zero */	switch (bdp->zlock_state) {	case ZLOCK_INITIAL:		if (((u8) bdp->rev_id <= D102_REV_ID) ||		    !(bdp->cur_line_speed == 100) ||		    !netif_carrier_ok(bdp->device)) {			break;		}		/* initialize hw and sw and start reading */		e100_mdi_write(bdp, PHY_82555_MDI_EQUALIZER_CSR,			       bdp->phy_addr, 0);		/* reset read counters: */		bdp->zlock_read_cnt = 0;		for (pos = 0; pos < 16; pos++)			bdp->zlock_read_data[pos] = 0;		/* start reading in the next call back: */		bdp->zlock_state = ZLOCK_READING;		/* FALL THROUGH !! */	case ZLOCK_READING:		/* state: reading (100 times) zero locked in 1 sec interval		 * prev states: ZLOCK_INITIAL		 * next states: ZLOCK_INITIAL, ZLOCK_SLEEPING */		e100_mdi_read(bdp, PHY_82555_MDI_EQUALIZER_CSR,			      bdp->phy_addr, &eq_reg);		pos = (eq_reg & ZLOCK_ZERO_MASK) >> 4;		bdp->zlock_read_data[pos]++;		bdp->zlock_read_cnt++;		if (bdp->zlock_read_cnt == ZLOCK_MAX_READS) {			/* check if we read a 'Zero' value of 0xB or greater */			if ((bdp->zlock_read_data[0xB]) ||			    (bdp->zlock_read_data[0xC]) ||			    (bdp->zlock_read_data[0xD]) ||			    (bdp->zlock_read_data[0xE]) ||			    (bdp->zlock_read_data[0xF])) {				/* we've read 'Zero' value of 0xB or greater,				 * find most popular 'Zero' value and lock it */				mpz = 0;				/* this loop finds the most popular 'Zero': */				for (pos = 1; pos < 16; pos++) {					if (bdp->zlock_read_data[pos] >					    bdp->zlock_read_data[mpz])						mpz = pos;				}				/* now lock the most popular 'Zero': */				eq_reg = (ZLOCK_SET_ZERO | mpz);				e100_mdi_write(bdp,					       PHY_82555_MDI_EQUALIZER_CSR,					       bdp->phy_addr, eq_reg);				/* sleep for 5 minutes: */				bdp->zlock_sleep_cnt = jiffies;				bdp->zlock_state = ZLOCK_SLEEPING;				/* we will be reading the # of errors after 5				 * minutes, so we need to reset the error				 * counters - these registers are self clearing				 * on read, so read them */				e100_mdi_read(bdp, PHY_82555_SYMBOL_ERR,					      bdp->phy_addr, &err_cnt);			} else {				/* we did not read a 'Zero' value of 0xB or				 * above. go back to the start */				bdp->zlock_state = ZLOCK_INITIAL;			}		}		break;	case ZLOCK_SLEEPING:		/* state: sleeping for 5 minutes		 * prev states: ZLOCK_READING		 * next states: ZLOCK_READING, ZLOCK_SLEEPING */		/* if 5 minutes have passed: */		if ((jiffies - bdp->zlock_sleep_cnt) >= ZLOCK_MAX_SLEEP) {			/* read and sum up the number of errors:  */			e100_mdi_read(bdp, PHY_82555_SYMBOL_ERR,				      bdp->phy_addr, &err_cnt);			/* if we've more than 300 errors (this number was			 * calculated according to the spec max allowed errors			 * (80 errors per 1 million frames) for 5 minutes in			 * 100 Mbps (or the user specified max BER number) */			if (err_cnt > bdp->params.ber) {				/* start again in the next callback: */				bdp->zlock_state = ZLOCK_INITIAL;			} else {				/* we don't have more errors than allowed,				 * sleep for 5 minutes */				bdp->zlock_sleep_cnt = jiffies;			}		}		break;	default:		break;	}}

⌨️ 快捷键说明

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