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

📄 w740mac.c

📁 华邦w740以太网驱动 mac driver
💻 C
📖 第 1 页 / 共 3 页
字号:
static int w740_set_mac_address(struct net_device *dev, void *addr)
{ 
	struct w740_priv * priv=(struct w740_priv *)dev->priv;

	if(netif_running(dev))
		return -EBUSY;
	memcpy(&priv->mac_address[0],addr+2,ETH_ALEN);
	
	memcpy(dev->dev_addr,priv->mac_address,ETH_ALEN);
	if(priv->which)
		memcpy(w740_mac_address1,dev->dev_addr,ETH_ALEN);
	else
		memcpy(w740_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]);
	
	//w740_WriteReg(CAMEN,w740_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 w740_priv * w740_priv=dev->priv;
	
	w740_priv->start_tx_ptr =(unsigned long)&w740_priv->tx_desc[0]|NON_CACHE_FLAG;	
	w740_priv->start_tx_buf =(unsigned long)&w740_priv->tx_buf[0] | NON_CACHE_FLAG;
	
	w740_priv->start_rx_ptr =(unsigned long)&w740_priv->rx_desc[0]|NON_CACHE_FLAG;
	w740_priv->start_rx_buf =(unsigned long)&w740_priv->rx_buf[0] | NON_CACHE_FLAG;
	
	
	//Tx Ring
	MAC_ASSERT(w740_priv->start_tx_ptr );
	MAC_ASSERT(w740_priv->start_tx_buf );
	TRACE(" tx which %d start_tx_ptr %x\n",w740_priv->which,w740_priv->start_tx_ptr);

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

/************************************************************************
* FUNCTION                                                             
*       w740_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   w740_open(struct net_device *dev)
{
  	struct w740_priv * priv;
  	int    which ;

  	priv=(struct w740_priv *)dev->priv;
  	which= priv->which; 
  	  	
  	init_rxtx_rings(dev);
  	priv->rx_ptr=priv->start_rx_ptr ;
  	priv->tx_ptr=priv->start_tx_ptr ;
  	
  	w740_WriteReg(FIFOTHD,0x10000,which); //0x10100
  	w740_WriteReg(FIFOTHD,0x100300,which); //0x10100
  	w740_WriteReg(RXDLSA,priv->start_rx_ptr,which);
  	w740_WriteReg(TXDLSA,priv->start_tx_ptr,which);
  	w740_WriteReg(DMARFC,2000,which);
  	
  	w740_WriteCam(priv->which,0,dev->dev_addr);
	w740_WriteReg(CAMEN,w740_ReadReg(CAMEN,priv->which) | 1,priv->which);
  
  	w740_WriteReg(CAMCMR,CAMCMR_ECMP|CAMCMR_ABP|CAMCMR_AMP,which);
  	//w740_WriteReg(CAMCMR,CAMCMR_ECMP|CAMCMR_ABP|CAMCMR_AMP|CAMCMR_AUP,which);	
  	
  	w740_WriteReg(MCMDR,1<<19,which);
    ResetP(which);
    if(ResetPhyChip(which)==1)
    {	
    	TRACE_ERROR("ResetPhyChip Failed\n");
    	return -1;
    }	
  	
    //number interrupt  number     
    TRACE("**** which %d \n", which);
    
    /* Configure the MAC control registers. */
    w740_WriteReg(MIEN,gMIEN,which);
    w740_WriteReg(MCMDR,w740_ReadReg(MCMDR,which)|gMCMDR,which);
    w740_WriteReg(MCMDR,w740_ReadReg(MCMDR,which)|MCMDR_RXON,which);
   	
    priv->mcmdr=w740_ReadReg(MCMDR,which);
    priv->bInit=1; 
    priv->rx_packets=0;
	priv->rx_bytes=0;
	priv->start_time=jiffies;
	
   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(EMCTXINT0);
    //	Enable_Int(EMCRXINT0);
    	/* set MAC0 as LAN port */
    	//MCMDR_0 |= MCMDR_LAN ;
    }
    else
    {
    	/* Tx interrupt vector setup. */
    	AIC_SCR_EMCTX1 = 0x41;
    	/* Rx interrupt vector setup. */
    	AIC_SCR_EMCRX1 = 0x41;
    	/* Enable MAC Tx and Rx interrupt. */
    //	Enable_Int(EMCTXINT1);
    //	Enable_Int(EMCRXINT1);
    	/* set MAC0 as LAN port */
    	//MCMDR_1 |= MCMDR_LAN ;
    }
    
	if(request_irq(TX_INTERRUPT+which,&tx_interrupt,SA_INTERRUPT,"",dev))
    {
    	TRACE_ERROR(KERN_ERR "W90N740 : register irq tx failed\n");
    	return -EAGAIN;
    }
    
     //compute    interrupt number   
    if(request_irq(RX_INTERRUPT+which,&rx_interrupt,SA_INTERRUPT,"",dev))
    {
    	TRACE_ERROR(KERN_ERR "w90N740 : register irq rx failed\n");
    	return -EAGAIN;
    }
    netif_start_queue(dev);
    w740_WriteReg(RSDR ,0,which);

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

static int   w740_close(struct net_device *dev)
{
	struct w740_priv *priv=(struct w740_priv *)dev->priv;
	int which=priv->which;
	
	priv->bInit=0; 
	
	netif_stop_queue(dev);
	w740_WriteReg(MCMDR,0,which);
	free_irq(RX_INTERRUPT+which,dev);
	free_irq(TX_INTERRUPT+which,dev);

	return 0;
}

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

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

#ifdef DEBUG
	int i=0;
    unsigned long cur_ptr;
    TXBD  *txbd;
    
	cur_ptr=w740_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),
    	w740_ReadReg(MIEN,which),w740_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",w740_ReadReg(RXFSM,which));
		printk("TXFSM:%x\n",w740_ReadReg(TXFSM,which));
		printk("FSM0:%x\n",w740_ReadReg(FSM0,which));
		printk("FSM1:%x\n",w740_ReadReg(FSM1,which));
		//if((w740_ReadReg(TXFSM,which)&0x0FFF0000)==0x8200000)
		ResetMAC(dev);
	}
	dev->trans_start = jiffies;

}

static int w740_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("w740_start_xmit:dev:%x\n",dev);
    if(!(send_frame(dev,skb->data,skb->len)) )   
    {
    	dev_kfree_skb(skb);
    	TRACE("w740_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 w740_priv *priv = (struct w740_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=w740_ReadReg(MISTA,which);   //get  interrupt status;
    //w740_WriteReg(MISTA,status&0xFFFF0000,which);  //clear interrupt
    w740_WriteReg(MISTA,status,which);  //clear interrupt
    restore_flags(flags);

	cur_ptr=w740_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++;
	    }	
	    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("W90N740 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))	
		{	
			netif_wake_queue(dev);
			TRACE_ERROR("queue restart TDU\n"); 
		}
    }
    TRACE("After %d tx_interrupt status %x  \n",which,status);
}
volatile unsigned long rx_jiffies0=0;
volatile unsigned long rx_jiffies1=0;
extern volatile unsigned long jiffies;

static void rx_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
	struct net_device *dev = (struct net_device *)dev_id;
	struct w740_priv  *priv = (struct w740_priv *) dev->priv;
	unsigned long status;
	int which=priv->which;
	unsigned long flags;
	if(which==0)
		rx_jiffies0 = jiffies;
	else if(which==1)	
		rx_jiffies1 = jiffies;
    status=w740_ReadReg(MISTA,which);   //get  interrupt status;   
	save_flags(flags); cli();
    //w740_WriteReg(MISTA,status&0xFFFF,which); //clear interrupt
    w740_WriteReg(MISTA,status,which); //clear interrupt
    restore_flags(flags);

    priv->cur_rx_entry++;
#if 0
    if(which==1)
    	printk("rx_interrupt status %x\n",which,status);
#endif
    if(status & (MISTA_RDU|MISTA_RxBErr))
    {
    	printk("No Descript available\n");
    	priv->is_rx_all=RX_DESC_SIZE; //receive all
        netdev_rx(dev);    //start doing
        priv->is_rx_all=0;
  		if(status&MISTA_RxBErr)
  		{
  			printk("MISTA_RxBErr\n");
        	ResetMAC(dev);
        }
        w740_WriteReg(RSDR ,0,which);
	    TRACE("* %d rx_interrupt MISTA %x \n",irq,status);

        return ;
    }
    save_flags(flags); cli();
    w740_WriteReg(MISTA,status,which); //clear interrupt
    restore_flags(flags);
    netdev_rx(dev);
}
 
void  ResetMACRx(struct net_device * dev)
 {
 	struct w740_priv * priv=(struct w740_priv *)dev->priv;
  	unsigned long val=w740_ReadReg(MCMDR,priv->which);
  	printk("In ResetMAC Rx \n");
  	ResetRxRing(dev->priv);    
    w740_WriteReg(MCMDR,(MCMDR_RXON|val),priv->which);
}

void ResetMACTx(struct net_device * dev)
{
 	struct w740_priv * priv=(struct w740_priv *)dev->priv;
  	unsigned long val=w740_ReadReg(MCMDR,priv->which);
  	printk("In ResetMAC Tx \n");
  	//ResetTxRing(dev->priv);    
    w740_WriteReg(MCMDR,(MCMDR_TXON|val),priv->which);
}
	
 void ResetRxRing(struct w740_priv * w740_priv)
 {
 	
 	 int i;
 	for( i =0 ; i < RX_DESC_SIZE ; i++)
    {    
	    w740_priv->rx_desc[i].SL=0;
	    w740_priv->rx_desc[i].SL|=RXfOwnership_DMA;
	}	  
 	
}
#if 0
void DescriptorLock(struct w740_priv * priv)

⌨️ 快捷键说明

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