[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 メーリングリストの案内