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

📄 w90p710_mac.c

📁 w90p710网卡驱动程序源码,工作环境uClinu下
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * linux/deriver/net/w90p710_mac.c
 * Ethernet driver for winbond W90P710 ( PC34 Lsshi )
*/

#include <linux/config.h>
#include <linux/module.h>

#include <linux/init.h>
#include <linux/sched.h>
#include <linux/kernel.h>      
#include <linux/slab.h>		 
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/interrupt.h>

#include <linux/in.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/skbuff.h>
#include <asm/semaphore.h>
#include <asm/irq.h>
#include "w90p710_mac.h"
#include <asm/arch/flash.h>


#define HAVE_PHY
#define RX_TIMEOUT    1
//#define IC_PLUS
//#define TEST_REST
#undef DEBUG
//#define DEBUG
#define TRACE_ERROR printk
#ifdef	DEBUG
	#define TRACE(str, args...)	printk("W90P710 eth: " str, ## args)
	#define MAC_ASSERT(x)							 \
	do {									 \
		if (!(x))							 \
			printk("ASSERT: %s:%i(%s)\n",				 \
			       __FILE__, __LINE__, __FUNCTION__);		 \
	} while(0);
#else
	#define MAC_ASSERT(x)
	#define TRACE(str, args...)
#endif

/* Global variables  used for MAC driver */
static unsigned long  	gMCMDR = MCMDR_SPCRC | MCMDR_EnMDC | MCMDR_ACP ;//|MCMDR_LBK;

static unsigned long  	gMIEN = EnTXINTR | EnRXINTR | EnRXGD | EnTXCP |
                        EnTxBErr | EnRxBErr | EnTXABT;//| EnTXEMP;//EnDEN
                   

#define RX_DESC_SIZE (3*10)
#define TX_DESC_SIZE (10)
#define CHECK_SIZE
#define PACKET_BUFFER_SIZE 1600
#define PACKET_SIZE   1560
#define TX_TIMEOUT  (50)

#define AUTO_SENSE

struct  p710_priv
{
	struct net_device_stats stats;	
	unsigned long which;
	unsigned long rx_mode;
	volatile unsigned long cur_tx_entry;
	volatile unsigned long cur_rx_entry;
	volatile unsigned long is_rx_all;
//Test	
	unsigned long bInit;
	unsigned long rx_packets;
	unsigned long rx_bytes;
	unsigned long start_time;
#ifdef AUTO_SENSE
	struct 	timer_list timer0; // detect plug/unplug 
	struct 	timer_list timer1; // check auto negotiation result
	char		plugout;
#endif	
	volatile unsigned long tx_ptr;
	unsigned long tx_finish_ptr;
	volatile unsigned long rx_ptr;
	
	unsigned long start_tx_ptr;
	unsigned long start_tx_buf;
	
	//char aa[100*100];
	unsigned long mcmdr;
	volatile unsigned long start_rx_ptr;
	volatile unsigned long start_rx_buf;
	char 		  mac_address[ETH_ALEN];
	volatile  	  RXBD   rx_desc[RX_DESC_SIZE]  __attribute__ ((aligned (16)));
	volatile      TXBD   tx_desc[TX_DESC_SIZE]	__attribute__ ((aligned (16)));
	volatile char rx_buf[RX_DESC_SIZE][PACKET_BUFFER_SIZE]	__attribute__ ((aligned (16)));
	volatile char tx_buf[TX_DESC_SIZE][PACKET_BUFFER_SIZE]	__attribute__ ((aligned (16)));
};
 
char p710_mac_address0[ETH_ALEN]={0x00,0x02,0xac,0x55,0x88,0xa1};

static void init_rxtx_rings(struct net_device *dev);
void notify_hit(struct net_device *dev ,RXBD *rxbd);	
int send_frame(struct net_device * ,unsigned char *,int);
void ResetMACRx(struct net_device * dev);
void output_register_context(int );
static int  p710_init(struct net_device *dev);	
static void   netdev_rx(struct net_device *dev);
static void rx_interrupt(int irq, void *dev_id, struct pt_regs * regs);
static void tx_interrupt(int irq, void *dev_id, struct pt_regs * regs);
int prossess_nata(struct net_device *dev,RXBD * rxbd );	
void ResetTxRing(struct p710_priv * p710_priv);
int ResetMAC0(struct net_device * dev);
int ResetMAC1(struct net_device * dev);
void ResetMAC(struct net_device * dev);
void ResetRxRing(struct p710_priv * p710_priv);
int  MiiStationWrite(int num,unsigned long PhyInAddr,unsigned long PhyAddr,unsigned long PhyWrData);
unsigned long MiiStationRead(int num, unsigned long PhyInAddr, unsigned long PhyAddr);

static int resetPhyOk = 0;
static int timer_num = 0;

volatile struct net_device p710_netdevice[1]=
{
	{init:p710_init}
	//{init:p710_init}
};

void Dump_Register()
{
	
	printk("RXFSM:%d\n",DWORD_READ(RXFSM));
	printk("TXFSM:%d\n",DWORD_READ(TXFSM));
	printk("FSM0:%d\n",DWORD_READ(FSM0));
	printk("FSM1:%d\n",DWORD_READ(FSM1));

}


void p710_WriteCam(int which,int x, unsigned char *pval)
{
	
	unsigned int msw,lsw;
	
 	msw =  	(pval[0] << 24) |
        	(pval[1] << 16) |
        	(pval[2] << 8) |
         	pval[3];

 	lsw = (pval[4] << 24) |
           (pval[5] << 16);
    
 	p710_WriteCam0(which,0,lsw,msw);
 	
 
}

void ResetP(int num)
{
	MiiStationWrite(num,PHY_CNTL_REG,0x0100,RESET_PHY);
	MiiStationWrite(num, 20, PHYAD, MiiStationRead(num, 20, PHYAD) | 2); // Set to RMII 1.0 mode 
	
}	

int  ResetPhyChip(int num)
{
#ifdef HAVE_PHY
 	unsigned long RdValue;
 	int which=num;
 	volatile int loop=1000*100;

 	//MiiStationWrite(which, PHY_ANA_REG, PHYAD, DR10_TX_HALF|IEEE_802_3_CSMA_CD);

	TRACE_ERROR("\nWait for auto-negotiation complete...");


	if(MiiStationWrite(which, PHY_CNTL_REG, PHYAD, ENABLE_AN | RESTART_AN)==1)
 	{
 		
 		return 1;
 	}	
   
   
 	while (1) 	/* wait for auto-negotiation complete */
   	{
    	
    	RdValue = MiiStationRead(which, PHY_STATUS_REG, PHYAD) ;

    	if(RdValue==(unsigned long)1)
    	{
    		 printk("ResetPhyChip failed 1\n");
    		  return 1;
    	}

    	if ((RdValue & AN_COMPLETE) != 0 && (RdValue & 4)) // Auto-nego. complete and link valid
    	{
      		break;
      	}
      	loop--;
      	if(loop==0)
      	{
      		 return 1;
      	}	 
   	}
   	



	TRACE_ERROR("OK\n");
	resetPhyOk = 1;
 	/* read the result of auto-negotiation */

	RdValue = MiiStationRead(which, PHY_ANLPA_REG, PHYAD) ;
	if ((RdValue & 0x100)!=0) /* 100MB */
	  {
	    TRACE_ERROR("100MB - FULL\n");
	    p710_WriteReg(MCMDR,p710_ReadReg(MCMDR,which)|MCMDR_OPMOD|MCMDR_FDUP,which);
	  }
	else if ((RdValue & 0x80)!=0)
	  {
	    p710_WriteReg(MCMDR,p710_ReadReg(MCMDR,which)&~MCMDR_FDUP,which);
	    p710_WriteReg(MCMDR,p710_ReadReg(MCMDR,which)|MCMDR_OPMOD,which);
	    TRACE_ERROR("100MB - HALF\n");
	  }
	else if ((RdValue & 0x40)!=0)/* Full Duplex */
	  {
	    TRACE_ERROR("10MB - FULL\n");
	    p710_WriteReg(MCMDR,p710_ReadReg(MCMDR,which)&~MCMDR_OPMOD,which);
	    p710_WriteReg(MCMDR,p710_ReadReg(MCMDR,which)|MCMDR_FDUP,which);
	  }
	else 
	  { 
	    TRACE_ERROR("10MB - HALF\n");
	    p710_WriteReg(MCMDR,p710_ReadReg(MCMDR,which)&~MCMDR_OPMOD,which);
	    p710_WriteReg(MCMDR,p710_ReadReg(MCMDR,which)&~MCMDR_FDUP,which);
	  }

   	return 0;
#endif


#ifdef IC_PLUS
{
    unsigned long RdValue,i;
 // if (!skip_reset)   
 
	static int reset_phy=0;
MiiStationWrite(num, PHY_ANA_REG, PHYAD, DR100_TX_FULL|DR100_TX_HALF|\
		      DR10_TX_FULL|DR10_TX_HALF|IEEE_802_3_CSMA_CD);
		      
MiiStationWrite(num, PHY_CNTL_REG, PHYAD, ENABLE_AN | RESET_PHY|RESTART_AN);
    
    
    //cbhuang num
    MiiStationWrite(num, 0x16, PHYAD, 0x8420);
    RdValue = MiiStationRead(num, 0x12, PHYAD);	  
    
    MiiStationWrite(num, 0x12, PHYAD, RdValue | 0x80); // enable MII registers


      
  if(num == 1) {    
    for(i=0;i<3;i++)
	   {
		 RdValue = MiiStationRead(num, PHY_STATUS_REG, PHYAD) ;
		 if ((RdValue & AN_COMPLETE) != 0)
		  {
		 	printk("come  cbhuang %s   %s  %d  \n",__FILE__,__FUNCTION__,__LINE__);
			 break;
		  }	 
		}
    if(i==3)
      {
		printk("come  cbhuang %s   %s  %d  \n",__FILE__,__FUNCTION__,__LINE__);
		p710_WriteReg(MCMDR,p710_ReadReg(MCMDR,1)| MCMDR_OPMOD,1);
		p710_WriteReg(MCMDR,p710_ReadReg(MCMDR,1)| MCMDR_FDUP,1);		
		return 0;
	  }
     } 
	  
	  {
	    p710_WriteReg(MCMDR,p710_ReadReg(MCMDR,num)|MCMDR_OPMOD,num);	
		p710_WriteReg(MCMDR,p710_ReadReg(MCMDR,num)|MCMDR_FDUP,num);		  
	  }
	  return 0;
 	
 }
#endif
}

void ResetMAC(struct net_device * dev)
{
	struct p710_priv * priv=(struct p710_priv *)dev->priv;
	int    which=priv->which ;
	unsigned long val=p710_ReadReg(MCMDR,which);
	unsigned long flags;
	
	save_flags(flags); cli();
	p710_WriteReg(FIFOTHD,0x10000,which); //0x10100
	p710_WriteReg(MCMDR,p710_ReadReg(MCMDR,which)&~(MCMDR_TXON|MCMDR_RXON),which);
	p710_WriteReg(FIFOTHD,0x100300,which); //0x10100
	p710_WriteReg(MCMDR,p710_ReadReg(MCMDR,which)|SWR,which); //lsshi add 2005-4-22 13:05 Software reset
	
	//printk("Reset MAC:%x\n",(unsigned int)&flags);
	//printk("Reset MAC MCMDR:%x\n",p710_ReadReg(MCMDR,which));

	if(!netif_queue_stopped(dev))
	{
		netif_stop_queue(dev);
		//printk("Reset MAC stop queue\n");
	}

   	init_rxtx_rings(dev);
   	dev->trans_start=jiffies;
   	priv->cur_tx_entry=0;
    priv->cur_rx_entry=0;
	priv->rx_ptr=priv->start_rx_ptr ;
	priv->tx_ptr=priv->start_tx_ptr ;
  	
  		//11-21
  
	priv->tx_finish_ptr=priv->tx_ptr;  	
	
	p710_WriteReg(RXDLSA,priv->start_rx_ptr,which);
	p710_WriteReg(TXDLSA,priv->start_tx_ptr,which);
	p710_WriteReg(DMARFC,PACKET_SIZE,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);

    /* Configure the MAC control registers. */
    p710_WriteReg(MIEN,gMIEN,which);    	
	//p710_WriteReg(MCMDR,priv->mcmdr,priv->which);
	if(which==0)
	{
   		Enable_Int(INT_EMCTXINT0);
   		Enable_Int(INT_EMCRXINT0);
   	}
   
  	
    {
    	
    	p710_WriteReg(MCMDR,MCMDR_TXON|MCMDR_RXON|val,which);
    	p710_WriteReg(TSDR ,0,which);
    	p710_WriteReg(RSDR ,0,which);
    }
  
    p710_WriteReg(MISTA,p710_ReadReg(MISTA,which),which); //clear interrupt

    //printk("reset\n");
    restore_flags(flags);
    //up(&priv->locksend);
    
    dev->trans_start = jiffies;
	if(netif_queue_stopped(dev))
	{
		netif_wake_queue(dev);
	}
}
/************************************************************************
* FUNCTION                                                             
*        MiiStationWrite
*                                                                      
* DESCRIPTION                                                          
*        Write to the Mii Station Control register.                             
*                                                                      
* INPUTS                                                               
*        int      num         which MAC of W90P710
*        unsigned long   PhyInAddr   PHY register address
*        unsigned long   PhyAddr     Address to write to.
*        unsigned long   PhyWrData   Data to write.
*                                                                      
* OUTPUTS                                                              
*        None.                                    
*************************************************************************/

int  MiiStationWrite(int num,unsigned long PhyInAddr,unsigned long PhyAddr,unsigned long PhyWrData)
{
 	volatile int i = 1000;
 	int which=num;
    volatile int loop=1000*100;
#ifdef IC_PLUS1
	num = 0;
#endif	
	which=num;
   p710_WriteReg(MIID,PhyWrData,which);
   p710_WriteReg(MIIDA,PhyInAddr|PhyAddr|PHYBUSY|PHYWR|MDCCR1,which);
   while(i--);
   while((p710_ReadReg(MIIDA,which) &PHYBUSY))
   {
   		loop--;
   		if(loop==0)
   			return 1;
   }
   //printk("MiiStationWrite 1\n");
   return 0;
}


/************************************************************************
* FUNCTION                                                             
*        MiiStationRead
*                                                                      
* DESCRIPTION                                                          
*        Read from the Mii Station control register.                             
*                                                                      
* INPUTS                                                               
*        int      num         which MAC of W90P710
*        unsigned long   PhyInAddr   PHY register address.
*        unsigned long   PhyAddr     Address to read from.
*                                                                      
* OUTPUTS                                                              
*        unsigned long   Data read.
*************************************************************************/
unsigned long MiiStationRead(int num, unsigned long PhyInAddr, unsigned long PhyAddr)
{
 	unsigned long PhyRdData ;
 	int which=num;
 	volatile int loop=1000*100;

#ifdef  IC_PLUS1
	num = 0;
#endif	
	which=num;
    #define MDCCR1   0x00a00000  // MDC clock rating
    p710_WriteReg(MIIDA, PhyInAddr | PhyAddr | PHYBUSY | MDCCR1,which);
    while( (p710_ReadReg(MIIDA,which)& PHYBUSY) ) 
    {
    	loop--;
    	if(loop==0)
     		return (unsigned long)1;
    }
    
    PhyRdData = p710_ReadReg(MIID,which) ; 
 	return PhyRdData ;
}

/************************************************************************
* FUNCTION                                                             
*        p710_set_mac_address
*                                                                      
* DESCRIPTION                                                          
*        Set MAC Address For Device By Writing CAM Entry 0,  
*                                                                      
* INPUTS                                                               
*       dev :The MAC which address require to modified
*		addr:New Address 
*                                                                      
* OUTPUTS                                                              
*		Always sucess    
*************************************************************************/ 
static int p710_set_mac_address(struct net_device *dev, void *addr)
{ 
	struct p710_priv * priv=(struct p710_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);

⌨️ 快捷键说明

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