kernels/linux-2.4.0/drivers/net/sis900.c
/**
 *	sis630_set_eq: - set phy equalizer value for 630 LAN
 *	@net_dev: the net device to set equalizer value
 *	@revision: 630 LAN revision number
 *
 *	630E equalizer workaround rule(Cyrus Huang 08/15)
 *	PHY register 14h(Test)
 *	Bit 14: 0 -- Automatically dectect (default)
 *		1 -- Manually set Equalizer filter
 *	Bit 13: 0 -- (Default)
 *		1 -- Speed up convergence of equalizer setting
 *	Bit 9 : 0 -- (Default)
 *		1 -- Disable Baseline Wander
 *	Bit 3~7   -- Equalizer filter setting
 *	Link ON: Set Bit 9, 13 to 1, Bit 14 to 0
 *	Then calculate equalizer value
 *	Then set equalizer value, and set Bit 14 to 1, Bit 9 to 0
 *	Link Off:Set Bit 13 to 1, Bit 14 to 0
 *	Calculate Equalizer value:
 *	When Link is ON and Bit 14 is 0, SIS900PHY will auto-dectect proper equalizer value.
 *	When the equalizer is stable, this value is not a fixed value. It will be within
 *	a small range(eg. 7~9). Then we get a minimum and a maximum value(eg. min=7, max=9)
 *	0 <= max <= 4  --> set equalizer to max
 *	5 <= max <= 14 --> set equalizer to max+1 or set equalizer to max+2 if max == min
 *	max >= 15      --> set equalizer to max+5 or set equalizer to max+6 if max == min
 */
- set phy equalizer value for 630 LAN
@net_dev: the net device to set equalizer value
@revision: 630 LAN revision number


- set phy equalizer value for 630 LAN @net_dev : the net device to set equalizer value @revision : 630 LAN revision number
static void sis630_set_eq(struct net_device *net_dev, u8 revision)
{
	struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv;
	u16 reg14h, eq_value, max_value=0, min_value=0;
	u8 host_bridge_rev;
	int i, maxcount=10;
	struct pci_dev *dev=NULL;
	if ((dev = pci_find_device(SIS630_DEVICE_ID, SIS630_VENDOR_ID, dev)))
		pci_read_config_byte(dev, PCI_CLASS_REVISION, &host_bridge_rev);
	if (netif_carrier_ok(net_dev)) {
		reg14h=mdio_read(net_dev, sis_priv->cur_phy, MII_RESV);
		mdio_write(net_dev, sis_priv->cur_phy, MII_RESV, (0x2200 | reg14h) & 0xBFFF);
		for (i=0; i < maxcount; i++) {
			eq_value=(0x00F8 & mdio_read(net_dev, sis_priv->cur_phy, MII_RESV)) >> 3;
			if (i == 0)
				max_value=min_value=eq_value;
			max_value=(eq_value > max_value) ? eq_value : max_value;
			min_value=(eq_value < min_value) ? eq_value : min_value;
		}
		if (revision == SIS630E_900_REV || revision == SIS630EA1_900_REV) {
			if (max_value < 5)
				eq_value=max_value;
			else if (max_value >= 5 && max_value < 15)
				eq_value=(max_value == min_value) ? max_value+2 : max_value+1;
			else if (max_value >= 15)
				eq_value=(max_value == min_value) ? max_value+6 : max_value+5;
		}
		if (revision == SIS630A_900_REV && host_bridge_rev == SIS630A0) {
			if (max_value < 5)
				eq_value=max_value+3;
			else if (max_value >= 5)
				eq_value=max_value+5;
		}
		if (revision == SIS630A_900_REV && 
		    (host_bridge_rev == SIS630B0 || host_bridge_rev == SIS630B1)) {
			if (max_value == 0)
				eq_value=3;
			else
				eq_value=(max_value+min_value+1)/2;
		}
		reg14h=mdio_read(net_dev, sis_priv->cur_phy, MII_RESV);
		reg14h=(reg14h & 0xFF07) | ((eq_value << 3) & 0x00F8);
		reg14h=(reg14h | 0x6000) & 0xFDFF;
		mdio_write(net_dev, sis_priv->cur_phy, MII_RESV, reg14h);
	}
	else {
		reg14h=mdio_read(net_dev, sis_priv->cur_phy, MII_RESV);
		mdio_write(net_dev, sis_priv->cur_phy, MII_RESV, (reg14h | 0x2000) & 0xBFFF);
	}
	return;
}
static void sis630_set_eq ( struct net_device * net_dev , u8 revision ) { struct sis900_private * sis_priv = ( struct sis900_private * ) net_dev -> priv ; u16 reg14h , eq_value , max_value = 0 , min_value = 0 ; u8 host_bridge_rev ; int i , maxcount = 10 ; struct pci_dev * dev = NULL ; if ( ( dev = pci_find_device ( SIS630_DEVICE_ID , SIS630_VENDOR_ID , dev ) ) ) pci_read_config_byte ( dev , PCI_CLASS_REVISION , & host_bridge_rev ) ; if ( netif_carrier_ok ( net_dev ) ) { reg14h = mdio_read ( net_dev , sis_priv -> cur_phy , MII_RESV ) ; mdio_write ( net_dev , sis_priv -> cur_phy , MII_RESV , ( 0x2200 | reg14h ) & 0xBFFF ) ; for ( i = 0 ; i < maxcount ; i ++ ) { eq_value = ( 0x00F8 & mdio_read ( net_dev , sis_priv -> cur_phy , MII_RESV ) ) >> 3 ; if ( i == 0 ) max_value = min_value = eq_value ; max_value = ( eq_value > max_value ) ? eq_value : max_value ; min_value = ( eq_value < min_value ) ? eq_value : min_value ; } if ( revision == SIS630E_900_REV || revision == SIS630EA1_900_REV ) { if ( max_value < 5 ) eq_value = max_value ; else if ( max_value >= 5 && max_value < 15 ) eq_value = ( max_value == min_value ) ? max_value + 2 : max_value + 1 ; else if ( max_value >= 15 ) eq_value = ( max_value == min_value ) ? max_value + 6 : max_value + 5 ; } if ( revision == SIS630A_900_REV && host_bridge_rev == SIS630A0 ) { if ( max_value < 5 ) eq_value = max_value + 3 ; else if ( max_value >= 5 ) eq_value = max_value + 5 ; } if ( revision == SIS630A_900_REV && ( host_bridge_rev == SIS630B0 || host_bridge_rev == SIS630B1 ) ) { if ( max_value == 0 ) eq_value = 3 ; else eq_value = ( max_value + min_value + 1 ) / 2 ; } reg14h = mdio_read ( net_dev , sis_priv -> cur_phy , MII_RESV ) ; reg14h = ( reg14h & 0xFF07 ) | ( ( eq_value << 3 ) & 0x00F8 ) ; reg14h = ( reg14h | 0x6000 ) & 0xFDFF ; mdio_write ( net_dev , sis_priv -> cur_phy , MII_RESV , reg14h ) ; } else { reg14h = mdio_read ( net_dev , sis_priv -> cur_phy , MII_RESV ) ; mdio_write ( net_dev , sis_priv -> cur_phy , MII_RESV , ( reg14h | 0x2000 ) & 0xBFFF ) ; } return ; }
sis630_set_eq: - set phy equalizer value for 630 LAN
      @net_dev: the net device to set equalizer value
      @revision: 630 LAN revision number
sis630_set_eq : - set phy equalizer value for 630 LAN @net_dev : the net device to set equalizer value @revision : 630 LAN revision number
/* 630E rule to determine the equalizer value */ /* 630A0 rule to determine the equalizer value */ /* 630B0&B1 rule to determine the equalizer value */ /* write equalizer value and setting */