[Armadillo:00717] Re: Armadillo-JのEthernetドライバの修正

Fumito Morishima email@hidden
2005年 12月 8日 (木) 15:25:19 JST


森島です。

すみません、前回送付したパッチには不具合がありました。
前回のパッチを捨てて、元のソースファイルに
今回添付するパッチをあててください。

Fumito Morishima wrote:
> 森島です。
> 
> Armadillo-JのEthernetドライバは、
> 初期起動時しかEthernetのネゴシエーションを行っておらず、
> 起動時にLANケーブルを接続しておかなければ、
> 正常に通信できないという問題がありました。
> 
> この問題を修正したパッチを作成したので添付します。
> 
> 
> 
> ------------------------------------------------------------------------
> 
> --- ns7520_eth.c.orig	2005-11-29 11:54:50.000000000 +0900
> +++ ns7520_eth.c	2005-12-01 18:38:18.000000000 +0900
> @@ -88,6 +88,9 @@
>  # define ASSERT(expr, func)
>  #endif // DEBUG
>  
> +//Macro
> +#define checkBit(Data, Bit) (((Data & Bit) == Bit) ? 1 : 0)
> +
>  // use default FS Forth-Systeme GmbH MAC address
>  #define NS7520_DEFAULT_MAC	  { 0x00, 0x04, 0xf3, 0x00, 0x06, 0x35 }
>  
> @@ -101,7 +104,6 @@
>  #define NS7520_ETH_REGION4_LEN	  (NS7520_ETH_HT4 - NS7520_ETH_HT1 + 4 )
>  
>  #define NS7520_TIMEOUT		  5*HZ // in jiffies
> -#define NS7520_MII_NEG_DELAY      5*HZ  // in jiffies
>  
>  #define NS7520_DRIVER_NAME	  "ns7520_eth"
>  
> @@ -113,6 +115,13 @@
>  #define NS7520_LEFT		  0          // left rotation
>  #define NS7520_RIGHT		  1          // right rotation
>  
> +enum auto_negotiate_stat{
> +	AN_RESET = 0,
> +	AN_START,
> +	AN_COMPLETE,
> +	AN_STOP,
> +};
> +
>  /* ns7520_private contains private data to this module */
>  struct ns7520_private_t
>  {
> @@ -142,6 +151,7 @@
>  static unsigned short uiPhyOui1 = 0;
>  static unsigned short uiPhyOui2 = 0;
>  static unsigned int nPhyMaxMdioClock = 2500000; // defaults to 2.5 MHz
> +static int an_status = AN_RESET;
>  
>  static int  ns7520_init_module( void );
>  static void ns7520_cleanup_module( void );
> @@ -166,10 +176,17 @@
>  static void ns7520_rx_lockup_timer_enable( struct net_device* pDev );
>  static void ns7520_rx_lockup_timer_disable( struct net_device* pDev );
>  static void ns7520_tx_timeout( struct net_device* pDev );
> +#if 0
>  static void ns7520_link_force( struct net_device* pDev );
> -static void ns7520_link_auto_negotiate( struct net_device* pDev );
> +#endif
> +
> +static void ns7520_auto_negotiate_start(struct net_device *pDev);
> +static int ns7520_auto_negotiate_check(struct net_device *pDev, int print);
> +static int ns7520_check_link_status(struct net_device *pDev, int init);
> +
>  static void ns7520_link_update_egcr( struct net_device* pDev );
>  static void ns7520_link_print_changed( struct net_device* pDev );
> +static void ns7520_link_changed( struct net_device* pDev );
>  
>  // the PHY stuff
>  
> @@ -180,13 +197,14 @@
>  static unsigned int ns7520_mii_poll_busy( void );
>  
>  // the multicast stuff
> -
> +#if 0
>  static void ns7520_load_mca_hash_table( struct dev_mc_list* pMcList );
>  static void ns7520_set_hash_bit( unsigned char* pucHashTable, int nBit );
>  static int ns7520_calculate_hash_bit( unsigned char* pucMac );
>  static unsigned short ns7520_rotate( unsigned short uiReg,
>  				     int nDirection,
>  				     int nBits );
> +#endif
>  
>  // declared later due to ns7520_init_device
>  struct net_device ns7520_devs =
> @@ -432,6 +450,86 @@
>  }
>  
>  
> +struct an_timer_info{
> +	struct timer_list timer;
> +	unsigned long interval;
> +	int check;
> +	int print;
> +};
> +static struct an_timer_info anTimerInfo;
> +
> +#define LINK_AN_INTERVAL (1*HZ)
> +
> +enum link_change_status{
> +	LINK_NOT_CHANGE = 0,
> +	LINK_CHANGE_DOWN,
> +	LINK_CHANGE_UP,
> +	LINK_CHANGE_MODE,
> +};
> +
> +static void reset_timer(struct timer_list *timer, unsigned long interval){
> +	del_timer(timer);
> +	timer->expires = jiffies + interval;
> +	add_timer(timer);
> +}
> +
> +static void link_an_func(unsigned long arg){
> +	struct net_device *pDev = (struct net_device *)arg;
> +	int ret;
> +
> +	switch(an_status){
> +	case AN_START:
> +		if(anTimerInfo.check > 0){
> +			ret = ns7520_auto_negotiate_check(pDev, anTimerInfo.print);
> +			if(ret == 0){
> +				netarm_dma_enable(3, pDev);	
> +				an_status = AN_COMPLETE;
> +				ns7520_check_link_status(pDev, 1);
> +			}else{
> +				anTimerInfo.check--;
> +				if(anTimerInfo.check <= 0){
> +					an_status = AN_RESET;
> +				}
> +			}
> +		}else an_status = AN_RESET;
> +		break;
> +		
> +	case AN_COMPLETE:
> +		ret = ns7520_check_link_status(pDev, 0);
> +		switch(ret){
> +		case LINK_CHANGE_DOWN:
> +			an_status = AN_RESET;
> +			break;
> +		case LINK_CHANGE_MODE:
> +			ns7520_auto_negotiate_start(pDev);
> +			anTimerInfo.check = 5;
> +			an_status = AN_START;
> +			break;
> +		}
> +		break;
> +		
> +	case AN_RESET:
> +		ret = ns7520_check_link_status(pDev, 0);
> +		switch(ret){
> +		case LINK_CHANGE_UP:
> +		case LINK_CHANGE_MODE:
> +			ns7520_auto_negotiate_start(pDev);
> +			anTimerInfo.check = 5;
> +			an_status = AN_START;
> +			break;
> +		}
> +		break;
> +		
> +	case AN_STOP:
> +		return;
> +	  
> +	default:
> +		break;
> +	}
> +	
> +	reset_timer(&anTimerInfo.timer, anTimerInfo.interval);
> +}
> +
>  /***********************************************************************
>   * @Function: ns7520_open
>   * @Return: 0 on success otherwise error
> @@ -525,6 +623,16 @@
>  	
>  	netif_start_queue( pDev );
>  
> +	//AutoNegotiation timer start
> +	an_status = AN_RESET;
> +	anTimerInfo.interval = LINK_AN_INTERVAL;
> +	anTimerInfo.check = 0;
> +	anTimerInfo.print = 0;
> +	init_timer(&anTimerInfo.timer);
> +	anTimerInfo.timer.function = link_an_func;
> +	anTimerInfo.timer.data = (unsigned long)pDev;
> +	reset_timer(&anTimerInfo.timer, anTimerInfo.interval);
> +
>  	return 0;
>  
>  	// release IRQ
> @@ -573,6 +681,9 @@
>  	
>  	DEBUG_FN( DEBUG_INIT );
>  
> +	//AutoNegotiation timer stop
> +	an_status = AN_STOP;
> +
>  	netif_stop_queue( pDev ); // can't transmit any more
>  
>  	// disable hardware
> @@ -645,6 +756,10 @@
>  	
>          spin_lock_irqsave( &pPriv->lock, ulFlags );
>  
> +	if(an_status != AN_COMPLETE){
> +		return 0;
> +	}
> +
>  	nLen = pSkb->len < ETH_ZLEN ? ETH_ZLEN : pSkb->len;
>  	pDev->trans_start = jiffies; // save the timestamp
>  	
> @@ -1309,13 +1424,6 @@
>  
>  	pPriv->uiLastLinkStatus = 0xff; // undefined
>  	
> -#if 0    
> -  // use parameters defined
> -  ns7520_link_force( pDev );
> -#else
> -  ns7520_link_auto_negotiate( pDev );
> -#endif  
> -
>  	switch( PhyDetected ){
>  	case PHY_LXT971A:
>  	    // set LED2 to link mode
> @@ -1525,6 +1633,7 @@
>   * @Descr: configures eth and MII to use the link mode defined in
>   *         ucLinkMode
>   ***********************************************************************/
> +#if 0
>  static void ns7520_link_force( struct net_device* pDev )
>  {
>  	struct ns7520_private_t* pPriv = (struct ns7520_private_t*) pDev->priv;
> @@ -1562,20 +1671,13 @@
>  	ns7520_link_print_changed( pDev );
>  	ns7520_link_update_egcr( pDev );
>  }
> +#endif
>  
>  /***********************************************************************
> - * @Function: ns7520_link_auto_negotiate
> + * @Function: ns7520_auto_negotiate_start
>   * @Return: void
> - * @Descr: performs auto-negotation of link.
>   ***********************************************************************/
> -
> -static void ns7520_link_auto_negotiate( struct net_device* pDev )
> -{
> -	unsigned long ulStartJiffies;
> -	unsigned short uiStatus;
> -
> -	DEBUG_FN( DEBUG_MAJOR );
> -
> +static void ns7520_auto_negotiate_start(struct net_device *pDev){
>  	// run auto-negotation
>  	// define what we are capable of
>  	ns7520_mii_write( PHY_COMMON_AUTO_ADV,
> @@ -1588,25 +1690,82 @@
>  	ns7520_mii_write( PHY_COMMON_CTRL,
>  			  PHY_COMMON_CTRL_AUTO_NEG |
>  			  PHY_COMMON_CTRL_RES_AUTO );
> -	// wait for completion
> +}
>  
> -	ulStartJiffies = jiffies;
> -	while( jiffies < ulStartJiffies + NS7520_MII_NEG_DELAY )
> -	{
> -	    uiStatus = ns7520_mii_read( PHY_COMMON_STAT );
> -	    if((uiStatus & (PHY_COMMON_STAT_AN_COMP|PHY_COMMON_STAT_LNK_STAT)) ==
> -	       (PHY_COMMON_STAT_AN_COMP | PHY_COMMON_STAT_LNK_STAT) ) 
> -	    {
> -		// lucky we are, auto-negotiation succeeded
> -		ns7520_link_print_changed( pDev );
> -		ns7520_link_update_egcr( pDev );
> +/***********************************************************************
> + * @Function: ns7520_auto_negotiate_check
> + * @Return: 0 on complete otherwaise incomplete
> + ***********************************************************************/
> +static int ns7520_auto_negotiate_check(struct net_device *pDev, int print){
> +	unsigned short uiStatus;
>  
> -		return;
> -	    }
> +	if(an_status != AN_START) return -1;
> +
> +	uiStatus = ns7520_mii_read(PHY_COMMON_STAT);
> +
> +	if(checkBit(uiStatus, (PHY_COMMON_STAT_AN_COMP | PHY_COMMON_STAT_LNK_STAT))){
> +		if(print){
> +			ns7520_link_print_changed(pDev);
> +		}else{
> +			ns7520_link_changed(pDev);
> +		}
> +		
> +		ns7520_link_update_egcr(pDev);
> +		return 0;
>  	}
> +	return -1;
> +}
>  
> -	DEBUG_ARGS( DEBUG_MAJOR, "auto-negotiation timed out\n" );
> -	// ignore invalid link settings
> +/***********************************************************************
> + * @Function: ns7520_check_link_status
> + * @Return: see enum link_change_status
> + ***********************************************************************/
> +static int ns7520_check_link_status(struct net_device *pDev, int init){
> +	static unsigned short __preLink = 0;
> +	static unsigned short __preMode = 0;
> +	unsigned short Link = 0;
> +	unsigned short Mode = 0;
> +	unsigned short tmp;
> +	
> +	tmp = ns7520_mii_read(PHY_COMMON_STAT);
> +	if(checkBit(tmp, PHY_COMMON_STAT_LNK_STAT)){
> +		Link = 1;
> +	}
> +
> +	switch(PhyDetected){
> +	case PHY_LXT971A:
> +		tmp = ns7520_mii_read( PHY_LXT971_STAT2 );
> +		Mode = (tmp & (PHY_LXT971_STAT2_100BTX | PHY_LXT971_STAT2_DUPLEX_MODE));
> +		break;
> +	case PHY_ICS1893BF:
> +		tmp = ns7520_mii_read( PHY_ICS1893BF_QPD_STAT );
> +		Mode = (tmp & (PHY_ICS1893BF_QPD_STAT_100BTX |
> +			       PHY_ICS1893BF_QPD_STAT_DUPLEX_MODE));
> +		break;
> +	default:
> +		break;
> +	}
> + 
> +	if(init){
> +		__preLink = Link;
> +		__preMode = Mode;
> +		return LINK_NOT_CHANGE;
> +	}
> +	
> +	if(__preLink != Link){
> +		__preLink = Link;
> +		if(Link == 1){
> +			return LINK_CHANGE_UP;
> +		}else{
> +			return LINK_CHANGE_DOWN;
> +		}
> +	}
> +	if(__preMode != Mode){
> +		__preMode = Mode;
> +		return LINK_CHANGE_MODE;
> +	}
> +	
> +	return LINK_NOT_CHANGE;
>  }
>  
>  /***********************************************************************
> @@ -1744,6 +1903,65 @@
>  }
>  
>  /***********************************************************************
> + * @Function: ns7520_link_changed
> + * @Return: void
> + * @Descr: checks whether the link status has changed
> + ***********************************************************************/
> +
> +static void ns7520_link_changed( struct net_device* pDev )
> +{
> +	struct ns7520_private_t* pPriv = (struct ns7520_private_t*) pDev->priv;
> +	unsigned short uiStatus;
> +	unsigned short uiControl;
> +	
> +	DEBUG_FN( DEBUG_ETH );
> +
> +	uiControl = ns7520_mii_read( PHY_COMMON_CTRL );
> +
> +	if((uiControl & PHY_COMMON_CTRL_AUTO_NEG) == PHY_COMMON_CTRL_AUTO_NEG){
> +	    // PHY_COMMON_STAT_LNK_STAT is only set on autonegotiation
> +	    uiStatus = ns7520_mii_read( PHY_COMMON_STAT );
> +
> +	    if( !( uiStatus & PHY_COMMON_STAT_LNK_STAT) )
> +	    {
> +		netif_carrier_off( pDev );
> +	    } else {
> +	      if( !netif_carrier_ok( pDev ) ){
> +		    // we are online again, enable it
> +		    netif_carrier_on( pDev );
> +	      }	
> +
> +		switch( PhyDetected ){
> +		case PHY_LXT971A:
> +		    uiStatus = ns7520_mii_read( PHY_LXT971_STAT2 );
> +		    uiStatus &= (PHY_LXT971_STAT2_100BTX |
> +				 PHY_LXT971_STAT2_DUPLEX_MODE |
> +				 PHY_LXT971_STAT2_AUTO_NEG );
> +		    break;
> +		case PHY_ICS1893BF:
> +		    uiStatus = ns7520_mii_read( PHY_ICS1893BF_QPD_STAT );
> +		    uiStatus &= (PHY_ICS1893BF_QPD_STAT_100BTX |
> +				 PHY_ICS1893BF_QPD_STAT_DUPLEX_MODE );
> +		    break;
> +		default:
> +		  break;
> +		}
> +	    }
> +	} else {
> +	  //  mode has been forced, so uiStatus should be the same as the last
> +	  //  link status, enforce printing
> +	    uiStatus = pPriv->uiLastLinkStatus;
> +	    pPriv->uiLastLinkStatus = 0xff;
> +	}
> +	
> +	if( uiStatus != pPriv->uiLastLinkStatus )
> +	{
> +	    // save current link status
> +	    pPriv->uiLastLinkStatus = uiStatus;
> +	}
> +}
> +
> +/***********************************************************************
>   * the MII low level stuff
>   ***********************************************************************/
>  
> @@ -1945,6 +2163,7 @@
>   *         multicast addresses contained in the provided linked list.  This
>   *         function loads this table into the Ethernet controller.
>   ***********************************************************************/
> +#if 0
>  static void ns7520_load_mca_hash_table( struct dev_mc_list* pMcList )
>  {
>  	unsigned short      auiHashTable[ 4 ];
> @@ -1980,13 +2199,14 @@
>  	*get_eth_reg_addr( NS7520_ETH_HT3 ) = auiHashTable[ 2 ];
>  	*get_eth_reg_addr( NS7520_ETH_HT4 ) = auiHashTable[ 3 ];
>  }
> +#endif
>  
>  /***********************************************************************
>   * @Function: ns7520_set_hash_bit
>   * @Return: nothing
>   * @Descr: sets a bit in the hash table
>   ***********************************************************************/
> -
> +#if 0
>  static void ns7520_set_hash_bit( unsigned char* pucHashTable, int nBit )
>  {
>  	int nByteIndex;
> @@ -1996,7 +2216,7 @@
>  	nBitIndex = nBit & 7;
>  	pucHashTable[ nByteIndex ] |= (1 << nBitIndex );
>  }
> -
> +#endif
>  
>  /***********************************************************************
>   * @Function: ns7520_calculate_hash_bit
> @@ -2004,7 +2224,7 @@
>   * @Descr:  This routine calculates the bit to set in the CRC hash table
>   *          to enable receipt of the specified multicast address.
>   ***********************************************************************/
> -
> +#if 0
>  static int ns7520_calculate_hash_bit( unsigned char* pucMac )
>  {
>  	unsigned short  unCopyMac[ 3 ];
> @@ -2048,7 +2268,7 @@
>  	
>  	return nResult;
>  }
> -
> +#endif
>  
>  /***********************************************************************
>   * @Function: ns7520_rotate
> @@ -2059,7 +2279,7 @@
>   *      direction   NS7520_LEFT or NS7520_RIGHT
>   *      bits        # of bits to rotate
>   ***********************************************************************/
> -
> +#if 0
>  static unsigned short ns7520_rotate( unsigned short uiReg,
>  				     int nDirection,
>  				     int nBits )
> @@ -2087,7 +2307,7 @@
>  
>  	return uiReg;
>  }
> -
> +#endif
>  // ns7520_init_module, ns7520_cleanup_module at end as of linux convention
>  
>  /***********************************************************************
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> armadillo mailing list
> email@hidden
> http://lists.atmark-techno.com/mailman/listinfo/armadillo
-------------- next part --------------
文字コード指定の無い添付文書を保管しました...
名前: fix2_ns7520_eth.patch
URL:  <http://lists.atmark-techno.com/pipermail/armadillo/attachments/20051208/347104a3/attachment.ksh>


armadillo メーリングリストの案内