📄 w740mac.c
字号:
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 + -