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

📄 w90p710_mac.c

📁 w90p710网卡驱动程序源码,工作环境uClinu下
💻 C
📖 第 1 页 / 共 3 页
字号:

	memcpy(p710_mac_address0,dev->dev_addr,ETH_ALEN);
		
	TRACE_ERROR("\nSet MaC Address %u:%u:%u:%u:%u:%u\n",
			dev->dev_addr[0],\
			dev->dev_addr[1],\
			dev->dev_addr[2],\
			dev->dev_addr[3],\
			dev->dev_addr[4],\
			dev->dev_addr[5]);
	
	//p710_WriteReg(CAMEN,p710_ReadReg(CAMEN,priv->which) & ~1,priv->which);
	
	return 0;
}

/************************************************************************
* FUNCTION                                                             
*        init_rxtx_rings
*                                                                      
* DESCRIPTION                                                          
*		Initialize the Tx ring and Rx ring.
*                                                                      
* INPUTS                                                               
*       dev :Which Ring is initialized including Tx and Rx Ring.
*                                                                      
* OUTPUTS                                                              
*		None
*************************************************************************/ 
static void init_rxtx_rings(struct net_device *dev)
{
	int i;
	struct p710_priv * p710_priv=dev->priv;
	
	p710_priv->start_tx_ptr =(unsigned long)&p710_priv->tx_desc[0]|NON_CACHE_FLAG;	
	p710_priv->start_tx_buf =(unsigned long)&p710_priv->tx_buf[0] | NON_CACHE_FLAG;
	
	p710_priv->start_rx_ptr =(unsigned long)&p710_priv->rx_desc[0]|NON_CACHE_FLAG;
	p710_priv->start_rx_buf =(unsigned long)&p710_priv->rx_buf[0] | NON_CACHE_FLAG;
	
	
	//Tx Ring
	MAC_ASSERT(p710_priv->start_tx_ptr );
	MAC_ASSERT(p710_priv->start_tx_buf );
	TRACE(" tx which %d start_tx_ptr %x\n",p710_priv->which,p710_priv->start_tx_ptr);

	for ( i = 0 ; i < TX_DESC_SIZE ; i++ )
	{
		//p710_priv->tx_desc[i]=0;
	   	p710_priv->tx_desc[i].SL=0;
	   	p710_priv->tx_desc[i].mode=0;
		p710_priv->tx_desc[i].buffer=(unsigned long)&p710_priv->tx_buf[i]|NON_CACHE_FLAG;	
		p710_priv->tx_desc[i].next=(unsigned long)&p710_priv->tx_desc[i+1]|NON_CACHE_FLAG;	
	   	TRACE(" *tx cur %d desc %x buffer  %x", i,  &p710_priv->tx_desc[i],p710_priv->tx_desc[i].buffer);
	   	TRACE("  next %x\n",p710_priv->tx_desc[i].next);	
	}
	p710_priv->tx_desc[i-1].next=(unsigned long)&p710_priv->tx_desc[0]|NON_CACHE_FLAG;	
	TRACE(" * cur %d desc %x buffer  %x", i-1,  &p710_priv->tx_desc[i-1],p710_priv->tx_desc[i-1].buffer);
	TRACE("  next %x\n",p710_priv->tx_desc[i-1].next);
	
	//Rx Ring
	MAC_ASSERT(p710_priv->start_rx_ptr );
	MAC_ASSERT(p710_priv->start_rx_buf );	
	TRACE(" tx which %d start_rx_ptr %x\n",p710_priv->which,p710_priv->start_rx_ptr);	   
    
    for( i =0 ; i < RX_DESC_SIZE ; i++)
    {    
	    p710_priv->rx_desc[i].SL=RXfOwnership_DMA;
		  
		p710_priv->rx_desc[i].buffer=(unsigned long)&p710_priv->rx_buf[i]|NON_CACHE_FLAG;	
		p710_priv->rx_desc[i].next=(unsigned long)&p710_priv->rx_desc[i+1]|NON_CACHE_FLAG;
		   
		TRACE(" # rx which %d,desc %d desc-addr  %x", p710_priv->which,i, &p710_priv->rx_desc[i]);
		TRACE("  next %x\n",p710_priv->rx_desc[i].next);
	}	
	p710_priv->rx_desc[i-1].next=(unsigned long)&p710_priv->rx_desc[0]|NON_CACHE_FLAG;	
    	
}
#ifdef AUTO_SENSE

#define MAX_AN_CHECK    5
static int an_check;

static void w710_autodetect(unsigned long arg)
{
    struct net_device * dev =(struct net_device *)arg;
    struct p710_priv *  priv=(struct p710_priv *)dev->priv;
    int which=priv->which;
    //unsigned int rxfsm=w740_ReadReg(RXFSM,priv->which);
    //unsigned  long status=w740_ReadReg(MISTA,priv->which);
    unsigned int RdValue;

    RdValue = MiiStationRead(which, PHY_STATUS_REG, PHYAD) ;
		if((RdValue&0x20)==0)
		{
			if(!priv->plugout)
			{
				printk("MAC Line-off...\n");
				*(unsigned int volatile *)(0xfff83020) = 0x50000;
				resetPhyOk = 0;
				priv->plugout=1;
			}	
			
		}
		else
		{
			if(priv->plugout)
			{
				printk("MAC Line-on...\n");
				ResetMAC(dev);
				if(MiiStationWrite(0, PHY_CNTL_REG, PHYAD, ENABLE_AN | RESTART_AN) != 1) {
                    priv->timer1.expires = jiffies + (RX_TIMEOUT) * HZ; // Check every seconds for five times
                    an_check = 1;
                    add_timer(&priv->timer1);
                    timer_num = 1;
                    return;
                }					
			} 
			
		}
	
    priv->timer0.expires = jiffies +RX_TIMEOUT*HZ;
    add_timer(&priv->timer0);
 
}

static void check_an_result(unsigned long arg)
{
    struct net_device * dev =(struct net_device *)arg;
    struct p710_priv *  priv=(struct p710_priv *)dev->priv;
    unsigned int RdValue;

    RdValue = MiiStationRead(0, PHY_STATUS_REG, PHYAD) ;
    
    if(RdValue !=(unsigned long)1) {
        // Needs to read second time to let Davicom 9161 PHYs set the link status
        RdValue = MiiStationRead(0, PHY_STATUS_REG, PHYAD) ;
        if ((RdValue & AN_COMPLETE) != 0 && (RdValue & 4)) // Auto-nego. complete and link valid
        {

	        RdValue = MiiStationRead(0, PHY_ANLPA_REG, PHYAD) ;

        	if ((RdValue & 0x100)!=0) /* 100MB */
        	  {
        	    TRACE_ERROR("100MB - FULL\n");
        	    p710_WriteReg(MCMDR,p710_ReadReg(MCMDR,0)|MCMDR_OPMOD|MCMDR_FDUP,0);
        	  }
        	else if ((RdValue & 0x80)!=0)
        	  {
        	    p710_WriteReg(MCMDR,p710_ReadReg(MCMDR,0)&~MCMDR_FDUP,0);
        	    p710_WriteReg(MCMDR,p710_ReadReg(MCMDR,0)|MCMDR_OPMOD,0);
        	    TRACE_ERROR("100MB - HALF\n");
        	  }
        	else if ((RdValue & 0x40)!=0)/* Full Duplex */
        	  {
        	    TRACE_ERROR("10MB - FULL\n");
        	    p710_WriteReg(MCMDR,p710_ReadReg(MCMDR,0)&~MCMDR_OPMOD,0);
        	    p710_WriteReg(MCMDR,p710_ReadReg(MCMDR,0)|MCMDR_FDUP,0);
        	  }
        	else 
        	  { 
        	    TRACE_ERROR("10MB - HALF\n");
        	    p710_WriteReg(MCMDR,p710_ReadReg(MCMDR,0)&~MCMDR_OPMOD,0);
        	    p710_WriteReg(MCMDR,p710_ReadReg(MCMDR,0)&~MCMDR_FDUP,0);
        	  }  
        	 resetPhyOk = 1;
        	 *(unsigned int volatile *)(0xfff83020) = 0x55555;
        	 priv->plugout=0;
        	           	   
        } else if(an_check < MAX_AN_CHECK) {
            priv->timer1.expires = jiffies + (RX_TIMEOUT * 2) * HZ;
            an_check++;
            add_timer(&priv->timer1);    
            return;        
        }    
    }
	  		
	// ok. check state finished. keep monitoring for plug/unplug
    priv->timer0.expires = jiffies +RX_TIMEOUT*HZ;
    add_timer(&priv->timer0);
    timer_num = 0;
 
}
#endif
/************************************************************************
* FUNCTION                                                             
*       p710_open
*                                                                      
* DESCRIPTION                                                          
*		Set Register ,Register ISR ,The MAC began to Receive Package.
*                                                                      
* INPUTS                                                               
*       dev :Pointer to MAC That is Opened.
*                                                                      
* OUTPUTS                                                              
*		Sucess if Return 0		
*************************************************************************/ 
static int   p710_open(struct net_device *dev)
{
  	struct p710_priv * priv;
  	int    which ;

  	priv=(struct p710_priv *)dev->priv;
  	which= priv->which; 
  	  	
  	init_rxtx_rings(dev);
		ResetMAC(dev);  	
  	priv->rx_ptr=priv->start_rx_ptr ;
  	priv->tx_ptr=priv->start_tx_ptr ;
  	
  	p710_WriteReg(FIFOTHD,0x10000,which); //0x10100
  	p710_WriteReg(FIFOTHD,0x100300,which); //0x10100
  	p710_WriteReg(RXDLSA,priv->start_rx_ptr,which);
  	p710_WriteReg(TXDLSA,priv->start_tx_ptr,which);
  	p710_WriteReg(DMARFC,2000,which);
  	
  	p710_WriteCam(priv->which,0,dev->dev_addr);
		p710_WriteReg(CAMEN,p710_ReadReg(CAMEN,priv->which) | 1,priv->which);
  
  	p710_WriteReg(CAMCMR,CAMCMR_ECMP|CAMCMR_ABP|CAMCMR_AMP,which);
  	//p710_WriteReg(CAMCMR,CAMCMR_ECMP|CAMCMR_ABP|CAMCMR_AMP|CAMCMR_AUP,which);	
  	
  	p710_WriteReg(MCMDR,1<<19,which);
	*(unsigned int volatile *)(0xfff83020) = 0x50000;
	*(unsigned int volatile *)(0xfff83024) = 0; // make sure other pins are in input mode.
    ResetP(which);
    if(ResetPhyChip(which)==1)
    {	
    	TRACE_ERROR("ResetPhyChip Failed\n");
			priv->plugout=1;
    	 /*return -1;*/  // yachen
    }
    else
    	priv->plugout=0;

  	
    //number interrupt  number     
    TRACE("**** which %d \n", which);
    
    /* Configure the MAC control registers. */
    p710_WriteReg(MIEN,gMIEN,which);
    p710_WriteReg(MCMDR,p710_ReadReg(MCMDR,which)|gMCMDR,which);
    p710_WriteReg(MCMDR,p710_ReadReg(MCMDR,which)|MCMDR_RXON,which);
   	
    priv->mcmdr=p710_ReadReg(MCMDR,which);
    priv->bInit=1; 
    priv->rx_packets=0;
	priv->rx_bytes=0;
	priv->start_time=jiffies;
	
#ifdef AUTO_SENSE
    init_timer(&priv->timer0);

	priv->timer0.expires =jiffies+RX_TIMEOUT*HZ;
	priv->timer0.data = (unsigned long) dev;
	priv->timer0.function = w710_autodetect;	
	add_timer(&priv->timer0);
    timer_num = 0;
	
	init_timer(&priv->timer1);
	priv->timer1.data = (unsigned long) dev;
	priv->timer1.function = check_an_result;	

#endif
	
   if(which==0){
   	/* Tx interrupt vector setup. */
    	AIC_SCR_EMCTX0 = 0x41;
    	/* Rx interrupt vector setup. */
    	AIC_SCR_EMCRX0 = 0x41;
    /* Enable MAC Tx and Rx interrupt. */
    //	Enable_Int(INT_EMCTXINT0);
    //	Enable_Int(EMCRXINT0);
    	/* set MAC0 as LAN port */
    	//MCMDR_0 |= MCMDR_LAN ;
    }
   
    
	if(request_irq(INT_EMCTXINT0+which,&tx_interrupt,SA_INTERRUPT,"",dev))
    {
    	TRACE_ERROR(KERN_ERR "W90P710 : register irq tx failed\n");
    	return -EAGAIN;
    }
    
     //compute    interrupt number   
    if(request_irq(INT_EMCRXINT0+which,&rx_interrupt,SA_INTERRUPT,"",dev))
    {
    	TRACE_ERROR(KERN_ERR "W90P710 : register irq rx failed\n");
    	return -EAGAIN;
    }
    netif_start_queue(dev);
    p710_WriteReg(RSDR ,0,which);

    if(resetPhyOk == 1)
      *(unsigned int volatile *)(0xfff83020) = 0x55555;

    TRACE("%s is OPENED\n",dev->name); 
    return 0;
}
 

static int   p710_close(struct net_device *dev)
{
	struct p710_priv *priv=(struct p710_priv *)dev->priv;
	int which=priv->which;
	
	priv->bInit=0; 
#ifdef AUTO_SENSE		
    // there's only one active tiemr at a time. recorded in timer_num.
    if(timer_num == 0)
	    del_timer(&priv->timer0);
	else    
	    del_timer(&priv->timer1);	
#endif
	netif_stop_queue(dev);
	p710_WriteReg(MCMDR,0,which);
	free_irq(INT_EMCTXINT0+which,dev);
	free_irq(INT_EMCRXINT0+which,dev);
	
	TRACE_ERROR(KERN_ERR "W90P710 : p710_close\n");

	return 0;
}

/* Get the current statistics.	This may be called with the card open or
   closed. */
 
static struct net_device_stats * p710_get_stats(struct net_device *dev)    
{
	struct p710_priv *priv = (struct p710_priv *)dev->priv;
	
	return &priv->stats;
}

static void p710_timeout(struct net_device *dev)
{
    struct p710_priv * priv=(struct p710_priv *)dev->priv;
    int which=priv->which;

#ifdef DEBUG
	int i=0;
    unsigned long cur_ptr;
    TXBD  *txbd;
    
	cur_ptr=p710_ReadReg(CTXDSA,which);
	printk("&(priv->tx_desc[%d]):%x,&(priv->tx_desc[%d]:%x\n"
		,priv->cur_tx_entry,&(priv->tx_desc[priv->cur_tx_entry])
		,priv->cur_tx_entry+1,&(priv->tx_desc[priv->cur_tx_entry+1]));
	printk(",cur_ptr:%x,mode:%x,SL:%x\n",
			cur_ptr,((TXBD  *)cur_ptr)->mode,((TXBD  *)cur_ptr)->SL);
	printk("priv->tx_ptr:%x,SL:%x,mode:%x\n",
    		priv->tx_ptr,((TXBD *)(priv->tx_ptr))->SL,((TXBD *)(priv->tx_ptr))->mode);
    printk("0xfff82114:%x,MIEN:%x,MISTA:%x\n",CSR_READ(0xfff82114),
    	p710_ReadReg(MIEN,which),p710_ReadReg(MISTA,which));
	//printk("MAC %d timeout,pid:%d,mode:%d\n",priv->which,current->pid,mode);
	for ( i = 0 ; i < TX_DESC_SIZE ; i++ )
	{
	   	printk("*tx cur %d desc %x buffer %x",i,&priv->tx_desc[i],priv->tx_desc[i].buffer);
	   	printk(" next %x\n",priv->tx_desc[i].next);	
	}
#endif
	{
		printk("RXFSM:%x\n",p710_ReadReg(RXFSM,which));
		printk("TXFSM:%x\n",p710_ReadReg(TXFSM,which));
		printk("FSM0:%x\n",p710_ReadReg(FSM0,which));
		printk("FSM1:%x\n",p710_ReadReg(FSM1,which));
		//if((p710_ReadReg(TXFSM,which)&0x0FFF0000)==0x8200000)
		ResetMAC(dev);
	}
	dev->trans_start = jiffies;

}

static int p710_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
#ifdef DEBUG
    char *data;
    int i=0;
    int len=skb->len;
    for(i=0;i<len;i+=10)
    	printk("%2x %2x %2x %2x %2x %2x %2x %2x %2x %2x\n",*(data+i),*(data+i+1),
    		*(data+i+2),*(data+i+3),*(data+i+4),*(data+i+5),*(data+i+6),
    		*(data+i+7),*(data+i+8),*(data+i+9));
	printk("\n");
#endif
//printk("p710_start_xmit:dev:%x\n",dev);
    if(!(send_frame(dev,skb->data,skb->len)) )   
    {
    	dev_kfree_skb(skb);
    	TRACE("p710_start_xmit ok\n");
    	return 0;
    }
printk("send failed\n");        
    return -1;	
}

/* The typical workload of the driver:
   Handle the network interface interrupts. */

static void tx_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
    struct net_device *dev = (struct net_device *)dev_id;
    struct p710_priv *priv = (struct p710_priv *)dev->priv;
    unsigned long status;  
    unsigned long cur_ptr;
    int which=priv->which;
    TXBD  *txbd;
    static  unsigned  reset_rx_loop=0;
    
    unsigned long flags;
    save_flags(flags); cli();
    status=p710_ReadReg(MISTA,which);   //get  interrupt status;
    //p710_WriteReg(MISTA,status&0xFFFF0000,which);  //clear interrupt
    p710_WriteReg(MISTA,status,which);  //clear interrupt
    restore_flags(flags);

	cur_ptr=p710_ReadReg(CTXDSA,which);
#if 0
    if(which==1)
   		printk("tx_ptr:%x,cur_ptr:%x,tx_entry:%d,s:%x\n",priv->tx_ptr,cur_ptr,priv->cur_tx_entry,status);
#endif
   while((&(priv->tx_desc[priv->cur_tx_entry]) != cur_ptr))
    {
    	txbd =(TXBD *)&(priv->tx_desc[priv->cur_tx_entry]);
    	priv->cur_tx_entry = (priv->cur_tx_entry+1)%(TX_DESC_SIZE);
    	
	    TRACE("*txbd->SL %x\n",txbd->SL);
	    TRACE("priv->tx_ptr %x  cru_ptr =%x\n",priv->tx_ptr,cur_ptr);
	    if(txbd->SL &TXDS_TXCP)
	    {
	    	priv->stats.tx_packets++;
	    	priv->stats.tx_bytes += txbd->SL&0xFFFF;
	    }	
	    else
	    {
		   priv->stats.tx_errors++;    
        }
        
        txbd->SL=0; 
        txbd->mode=0;

        if (netif_queue_stopped(dev))	
		{	
			netif_wake_queue(dev);
		}
	}
	
	if(status&MISTA_EXDEF)
	{
		printk("MISTA_EXDEF\n");
	}
    if((status & MISTA_RDU)&& ++reset_rx_loop==5)
    {
    	TRACE_ERROR("W90P710 MAC In Tx %d RX   I Have Not Any Descript Needed\n",priv->which);
        //ResetMAC(dev);
        //reset_rx_loop=0;
    }
    if(status&MISTA_TxBErr)
    	printk("MISTA_TxBErr\n");
    if(status&MISTA_TDU)
    {
    	//printk("MISTA_TDU\n");
    	if (netif_queue_stopped(dev))	
		{	

⌨️ 快捷键说明

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