From ac8b957720cfb6dd4535c9c5cc47cf4ce53551cd Mon Sep 17 00:00:00 2001 From: Oliver Schinagl Date: Wed, 16 Mar 2011 09:21:38 +0000 Subject: dos2unix --- uClinux-2.4.20-uc1/drivers/net/w90n745_mac.c | 2780 +++++++++--------- uClinux-2.4.20-uc1/drivers/net/w90n745_mac.h | 708 ++--- uClinux-2.4.20-uc1/drivers/net/wireless/base.c | 3566 ++++++++++++------------ 3 files changed, 3527 insertions(+), 3527 deletions(-) diff --git a/uClinux-2.4.20-uc1/drivers/net/w90n745_mac.c b/uClinux-2.4.20-uc1/drivers/net/w90n745_mac.c index fb70095..fbf37f7 100755 --- a/uClinux-2.4.20-uc1/drivers/net/w90n745_mac.c +++ b/uClinux-2.4.20-uc1/drivers/net/w90n745_mac.c @@ -1,1390 +1,1390 @@ -/* - * linux/deriver/net/w90n745_mac.c - * Ethernet driver for winbond W90N745 ( PC34 Lsshi ) -*/ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include "w90n745_mac.h" -#include - - -#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("W90N745 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 n745_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 n745_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 n745_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 n745_priv * n745_priv); -int ResetMAC0(struct net_device * dev); -int ResetMAC1(struct net_device * dev); -void ResetMAC(struct net_device * dev); -void ResetRxRing(struct n745_priv * n745_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 n745_netdevice[1]= -{ - {init:n745_init} - //{init:n745_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 n745_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); - - n745_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"); - n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,which)|MCMDR_OPMOD|MCMDR_FDUP,which); - } - else if ((RdValue & 0x80)!=0) - { - n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,which)&~MCMDR_FDUP,which); - n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,which)|MCMDR_OPMOD,which); - TRACE_ERROR("100MB - HALF\n"); - } - else if ((RdValue & 0x40)!=0) /* Full Duplex */ - { - TRACE_ERROR("10MB - FULL\n"); - n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,which)&~MCMDR_OPMOD,which); - n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,which)|MCMDR_FDUP,which); - } - else - { - TRACE_ERROR("10MB - HALF\n"); - n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,which)&~MCMDR_OPMOD,which); - n745_WriteReg(MCMDR,n745_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__); - n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,1)| MCMDR_OPMOD,1); - n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,1)| MCMDR_FDUP,1); - return 0; - } - } - - { - n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,num)|MCMDR_OPMOD,num); - n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,num)|MCMDR_FDUP,num); - } - return 0; - - } -#endif -} - -void ResetMAC(struct net_device * dev) -{ - struct n745_priv * priv=(struct n745_priv *)dev->priv; - int which=priv->which ; - unsigned long val=n745_ReadReg(MCMDR,which); - unsigned long flags; - - save_flags(flags); cli(); - n745_WriteReg(FIFOTHD,0x10000,which); //0x10100 - n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,which)&~(MCMDR_TXON|MCMDR_RXON),which); - n745_WriteReg(FIFOTHD,0x100300,which); //0x10100 - n745_WriteReg(MCMDR,n745_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",n745_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; - - n745_WriteReg(RXDLSA,priv->start_rx_ptr,which); - n745_WriteReg(TXDLSA,priv->start_tx_ptr,which); - n745_WriteReg(DMARFC,PACKET_SIZE,which); - - n745_WriteCam(priv->which,0,dev->dev_addr); - - n745_WriteReg(CAMEN,n745_ReadReg(CAMEN,priv->which) | 1,priv->which); - - n745_WriteReg(CAMCMR,CAMCMR_ECMP|CAMCMR_ABP|CAMCMR_AMP,which); - - /* Configure the MAC control registers. */ - n745_WriteReg(MIEN,gMIEN,which); - //n745_WriteReg(MCMDR,priv->mcmdr,priv->which); - if(which==0) - { - Enable_Int(INT_EMCTXINT0); - Enable_Int(INT_EMCRXINT0); - } - - - { - - n745_WriteReg(MCMDR,MCMDR_TXON|MCMDR_RXON|val,which); - n745_WriteReg(TSDR ,0,which); - n745_WriteReg(RSDR ,0,which); - } - - n745_WriteReg(MISTA,n745_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 W90N745 -* 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; - n745_WriteReg(MIID,PhyWrData,which); - n745_WriteReg(MIIDA,PhyInAddr|PhyAddr|PHYBUSY|PHYWR|MDCCR1,which); - while(i--); - while((n745_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 W90N745 -* 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 - n745_WriteReg(MIIDA, PhyInAddr | PhyAddr | PHYBUSY | MDCCR1,which); - while( (n745_ReadReg(MIIDA,which)& PHYBUSY) ) - { - loop--; - if(loop==0) - return (unsigned long)1; - } - - PhyRdData = n745_ReadReg(MIID,which) ; - return PhyRdData ; -} - -/************************************************************************ -* FUNCTION -* n745_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 n745_set_mac_address(struct net_device *dev, void *addr) -{ - struct n745_priv * priv=(struct n745_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); - - memcpy(n745_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]); - - //n745_WriteReg(CAMEN,n745_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 n745_priv * n745_priv=dev->priv; - - n745_priv->start_tx_ptr =(unsigned long)&n745_priv->tx_desc[0]|NON_CACHE_FLAG; - n745_priv->start_tx_buf =(unsigned long)&n745_priv->tx_buf[0] | NON_CACHE_FLAG; - - n745_priv->start_rx_ptr =(unsigned long)&n745_priv->rx_desc[0]|NON_CACHE_FLAG; - n745_priv->start_rx_buf =(unsigned long)&n745_priv->rx_buf[0] | NON_CACHE_FLAG; - - - //Tx Ring - MAC_ASSERT(n745_priv->start_tx_ptr ); - MAC_ASSERT(n745_priv->start_tx_buf ); - TRACE(" tx which %d start_tx_ptr %x\n",n745_priv->which,n745_priv->start_tx_ptr); - - for ( i = 0 ; i < TX_DESC_SIZE ; i++ ) - { - //n745_priv->tx_desc[i]=0; - n745_priv->tx_desc[i].SL=0; - n745_priv->tx_desc[i].mode=0; - n745_priv->tx_desc[i].buffer=(unsigned long)&n745_priv->tx_buf[i]|NON_CACHE_FLAG; - n745_priv->tx_desc[i].next=(unsigned long)&n745_priv->tx_desc[i+1]|NON_CACHE_FLAG; - TRACE(" *tx cur %d desc %x buffer %x", i, &n745_priv->tx_desc[i],n745_priv->tx_desc[i].buffer); - TRACE(" next %x\n",n745_priv->tx_desc[i].next); - } - n745_priv->tx_desc[i-1].next=(unsigned long)&n745_priv->tx_desc[0]|NON_CACHE_FLAG; - TRACE(" * cur %d desc %x buffer %x", i-1, &n745_priv->tx_desc[i-1],n745_priv->tx_desc[i-1].buffer); - TRACE(" next %x\n",n745_priv->tx_desc[i-1].next); - - //Rx Ring - MAC_ASSERT(n745_priv->start_rx_ptr ); - MAC_ASSERT(n745_priv->start_rx_buf ); - TRACE(" tx which %d start_rx_ptr %x\n",n745_priv->which,n745_priv->start_rx_ptr); - - for( i =0 ; i < RX_DESC_SIZE ; i++) - { - n745_priv->rx_desc[i].SL=RXfOwnership_DMA; - - n745_priv->rx_desc[i].buffer=(unsigned long)&n745_priv->rx_buf[i]|NON_CACHE_FLAG; - n745_priv->rx_desc[i].next=(unsigned long)&n745_priv->rx_desc[i+1]|NON_CACHE_FLAG; - - TRACE(" # rx which %d,desc %d desc-addr %x", n745_priv->which,i, &n745_priv->rx_desc[i]); - TRACE(" next %x\n",n745_priv->rx_desc[i].next); - } - n745_priv->rx_desc[i-1].next=(unsigned long)&n745_priv->rx_desc[0]|NON_CACHE_FLAG; - -} -#ifdef AUTO_SENSE - -#define MAX_AN_CHECK 5 -static int an_check; - -static void w745_autodetect(unsigned long arg) -{ - struct net_device * dev =(struct net_device *)arg; - struct n745_priv * priv=(struct n745_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 n745_priv * priv=(struct n745_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"); - n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,0)|MCMDR_OPMOD|MCMDR_FDUP,0); - } - else if ((RdValue & 0x80)!=0) - { - n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,0)&~MCMDR_FDUP,0); - n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,0)|MCMDR_OPMOD,0); - TRACE_ERROR("100MB - HALF\n"); - } - else if ((RdValue & 0x40)!=0)/* Full Duplex */ - { - TRACE_ERROR("10MB - FULL\n"); - n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,0)&~MCMDR_OPMOD,0); - n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,0)|MCMDR_FDUP,0); - } - else - { - TRACE_ERROR("10MB - HALF\n"); - n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,0)&~MCMDR_OPMOD,0); - n745_WriteReg(MCMDR,n745_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 -* n745_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 n745_open(struct net_device *dev) -{ - struct n745_priv * priv; - int which ; - - priv=(struct n745_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 ; - - n745_WriteReg(FIFOTHD,0x10000,which); //0x10100 - n745_WriteReg(FIFOTHD,0x100300,which); //0x10100 - n745_WriteReg(RXDLSA,priv->start_rx_ptr,which); - n745_WriteReg(TXDLSA,priv->start_tx_ptr,which); - n745_WriteReg(DMARFC,2000,which); - - n745_WriteCam(priv->which,0,dev->dev_addr); - n745_WriteReg(CAMEN,n745_ReadReg(CAMEN,priv->which) | 1,priv->which); - - n745_WriteReg(CAMCMR,CAMCMR_ECMP|CAMCMR_ABP|CAMCMR_AMP,which); - //n745_WriteReg(CAMCMR,CAMCMR_ECMP|CAMCMR_ABP|CAMCMR_AMP|CAMCMR_AUP,which); - - n745_WriteReg(MCMDR,1<<19,which); - - *(unsigned int volatile *)(0xfff83020) = 0x50000; - *(unsigned int volatile *)(0xfff83024) = 0; // Make sure all 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. */ - n745_WriteReg(MIEN,gMIEN,which); - n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,which)|gMCMDR,which); - n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,which)|MCMDR_RXON,which); - - priv->mcmdr=n745_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 = w745_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 "W90N745 : 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 "W90N745 : register irq rx failed\n"); - return -EAGAIN; - } - netif_start_queue(dev); - n745_WriteReg(RSDR ,0,which); - - if(resetPhyOk == 1) - *(unsigned int volatile *)(0xfff83020) = 0x55555; - - TRACE("%s is OPENED\n",dev->name); - return 0; -} - - -static int n745_close(struct net_device *dev) -{ - struct n745_priv *priv=(struct n745_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); - n745_WriteReg(MCMDR,0,which); - free_irq(INT_EMCTXINT0+which,dev); - free_irq(INT_EMCRXINT0+which,dev); - - TRACE_ERROR(KERN_ERR "W90N745 : n745_close\n"); - - return 0; -} - -/* Get the current statistics. This may be called with the card open or - closed. */ - -static struct net_device_stats * n745_get_stats(struct net_device *dev) -{ - struct n745_priv *priv = (struct n745_priv *)dev->priv; - - return &priv->stats; -} - -static void n745_timeout(struct net_device *dev) -{ - struct n745_priv * priv=(struct n745_priv *)dev->priv; - int which=priv->which; - -#ifdef DEBUG - int i=0; - unsigned long cur_ptr; - TXBD *txbd; - - cur_ptr=n745_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), - n745_ReadReg(MIEN,which),n745_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",n745_ReadReg(RXFSM,which)); - printk("TXFSM:%x\n",n745_ReadReg(TXFSM,which)); - printk("FSM0:%x\n",n745_ReadReg(FSM0,which)); - printk("FSM1:%x\n",n745_ReadReg(FSM1,which)); - //if((n745_ReadReg(TXFSM,which)&0x0FFF0000)==0x8200000) - ResetMAC(dev); - } - dev->trans_start = jiffies; - -} - -static int n745_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ -#ifdef DEBUG - char *data; - int i=0; - int len=skb->len; - for(i=0;idata,skb->len)) ) - { - dev_kfree_skb(skb); - TRACE("n745_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 n745_priv *priv = (struct n745_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=n745_ReadReg(MISTA,which); //get interrupt status; - //n745_WriteReg(MISTA,status&0xFFFF0000,which); //clear interrupt - n745_WriteReg(MISTA,status,which); //clear interrupt - restore_flags(flags); - - cur_ptr=n745_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("W90N745 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 n745_priv *priv = (struct n745_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=n745_ReadReg(MISTA,which); //get interrupt status; - save_flags(flags); cli(); - //n745_WriteReg(MISTA,status&0xFFFF,which); //clear interrupt - n745_WriteReg(MISTA,status,which); //clear interrupt - restore_flags(flags); - - priv->cur_rx_entry++; - - 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); - } - n745_WriteReg(RSDR ,0,which); - TRACE("* %d rx_interrupt MISTA %x \n",irq,status); - - return ; - } - save_flags(flags); cli(); - n745_WriteReg(MISTA,status,which); //clear interrupt - restore_flags(flags); - netdev_rx(dev); -} - -void ResetMACRx(struct net_device * dev) - { - struct n745_priv * priv=(struct n745_priv *)dev->priv; - unsigned long val=n745_ReadReg(MCMDR,priv->which); - //printk("In ResetMAC Rx \n"); - ResetRxRing(dev->priv); - n745_WriteReg(MCMDR,(MCMDR_RXON|val),priv->which); -} - -void ResetMACTx(struct net_device * dev) -{ - struct n745_priv * priv=(struct n745_priv *)dev->priv; - unsigned long val=n745_ReadReg(MCMDR,priv->which); - printk("In ResetMAC Tx \n"); - //ResetTxRing(dev->priv); - n745_WriteReg(MCMDR,(MCMDR_TXON|val),priv->which); -} - - void ResetRxRing(struct n745_priv * n745_priv) - { - - int i; - for( i =0 ; i < RX_DESC_SIZE ; i++) - { - n745_priv->rx_desc[i].SL=0; - n745_priv->rx_desc[i].SL|=RXfOwnership_DMA; - } - -} -#if 0 -void DescriptorLock(struct n745_priv * priv) -{ - unsigned long flags; - save_flags(flags); cli(); - if(priv->lock==1) - - while(priv->lock==1); - priv->lock=1; - restore_flags(flags); - -} -void DescriptorUnLock(struct n745_priv * priv) -{ - unsigned long flags; - save_flags(flags); cli(); - priv->lock=0; - restore_flags(flags); -} -/*0:failed,1:success*/ -int DescriptorTryLock(struct n745_priv * priv) -{ - unsigned long flags; - save_flags(flags); cli(); - if(priv->lock) - return 0; - priv->lock=1; - restore_flags(flags); - return 1; -} -#endif - -/* We have a good packet(s), get it/them out of the buffers. */ -static void netdev_rx(struct net_device *dev) -{ - struct n745_priv * priv = (struct n745_priv *)dev->priv; - RXBD *rxbd; - unsigned long length; - unsigned long status; - int flag=0; - - rxbd=(RXBD *)priv->rx_ptr ; - - do - { - - if(priv->is_rx_all>0) - { - flag=1; - --priv->is_rx_all; - } - else if(flag==1) - { - flag=0; - break; - } - else if((n745_ReadReg(CRXDSA,priv->which)==(unsigned long)rxbd)) - { - break; - } - - /* if(!(rxbd->SL & RXfOwnership_CPU)) - { - if(priv->is_rx_all) - rxbd->SL |=RXfOwnership_DMA; - - priv->rx_ptr=( RXBD *)rxbd->next; - rxbd=priv->rx_ptr; - continue; - } - */ - - length = rxbd->SL & 0xFFFF; - status = (rxbd->SL & 0xFFFF0000)&((unsigned long)~0 >>2); - - if(status & RXDS_RXGD) - { - unsigned char * data; - struct sk_buff * skb; - - data = (unsigned char *) rxbd->buffer; - - skb = dev_alloc_skb(length+2); //Get Skb Buffer; - if(!skb) { - TRACE_ERROR("W90N745: I Have Not Got Memory In Fun %s\n",__FUNCTION__); - priv->stats.rx_dropped++; - return; - } - - skb->dev = dev; - skb_reserve(skb, 2); //For IP Align 4-byte - skb_put(skb, length); - eth_copy_and_sum(skb, data, length, 0); //copy - skb->protocol = eth_type_trans(skb, dev); - priv->stats.rx_packets++; - priv->stats.rx_bytes += length; - netif_rx(skb); // Enqueue for Up Layer - - } - else - { - - if(priv->is_rx_all==RX_DESC_SIZE) - TRACE_ERROR("Rx error:%x,rxbd:%x,priv->is_rx_all:%d\n",status,rxbd,priv->is_rx_all); - priv->stats.rx_errors++; - if(status & RXDS_RP ) - { - TRACE_ERROR("W90N745 MAC: Receive Runt Packet Drop it!\n"); - priv->stats.rx_length_errors++; - } - if(status & RXDS_CRCE ) - { - TRACE_ERROR("W90N745 MAC Receive CRC Packet Drop It! \n"); - priv->stats.rx_crc_errors ++; - } - if(status & RXDS_ALIE ) - { - TRACE_ERROR("W90N745 MAC Receive Aligment Packet Dropt It!\n"); - priv->stats.rx_frame_errors++; - } - - if(status & RXDS_PTLE) - { - TRACE_ERROR("W90N745 MAC Receive Too Long Packet Dropt It!\n"); - priv->stats.rx_over_errors++; - } - } - - //rxbd->SL= RX_OWNERSHIP_DMA; //clear status and set dma flag - rxbd->SL =RXfOwnership_DMA; - rxbd->reserved = 0; - priv->rx_ptr=(unsigned long)rxbd->next; - rxbd=(RXBD *)priv->rx_ptr; - dev->last_rx = jiffies; - }while(1); - priv->is_rx_all = 0; -} - -static void n745_set_multicast_list(struct net_device *dev) -{ - - struct n745_priv *priv = (struct n745_priv *)dev->priv; - unsigned long rx_mode; -//printk("n745_set_multicast_list\n"); - int which=priv->which; - - if(dev->flags&IFF_PROMISC) - { - rx_mode = CAMCMR_AUP|CAMCMR_AMP|CAMCMR_ABP|CAMCMR_ECMP; - TRACE("W90N745 : Set Prommisc Flag \n"); - - } - else if((dev->flags&IFF_ALLMULTI)||dev->mc_list) - { - - rx_mode=CAMCMR_AMP|CAMCMR_ABP|CAMCMR_ECMP; - } - else - { - rx_mode = CAMCMR_ECMP|CAMCMR_ABP; - TRACE("W90N745 :Set Compare Flag\n"); - } - - //rx_mode=CAMCMR_AMP|CAMCMR_ABP|CAMCMR_ECMP;//|CAMCMR_AUP; - priv->rx_mode=rx_mode; - n745_WriteReg(CAMCMR,rx_mode,which); - -} -#define SIODEVSTARTNATA 0x6677 -#define SIODEVSTARTNATA 0x6688 - -static int n745_do_ioctl(struct net_device *dev,struct ifreq *ifr,int cmd) -{ - //u16 *data = (u16 *)&ifr->ifr_data; - struct n745_priv *priv=dev->priv; - int which = priv->which; - - printk("W90N745 IOCTL:\n"); - - switch(cmd) - { - case SIOCSIFHWADDR: - if(dev->flags&IFF_PROMISC) - return -1; - - memcpy(dev->dev_addr,ifr->ifr_hwaddr.sa_data,ETH_ALEN); - - memcpy(n745_mac_address0,dev->dev_addr,ETH_ALEN); - - n745_set_mac_address(dev,dev->dev_addr); - - break; - - #define SIOCn745MACDEGUG SIOCDEVPRIVATE+1 - case SIOCn745MACDEGUG : //For Debug; - output_register_context(which); - break; - - default: - return -EOPNOTSUPP; - } - return 0; -} -void output_register_context(int which) -{ - printk(" ** W90N745 EMC Register %d **\n",which); - - printk("CAMCMR:%x ",n745_ReadReg(CAMCMR,which)); - printk("CAMEN:%x ",n745_ReadReg(CAMEN,which)); - printk("MIEN: %x ",n745_ReadReg(MIEN,which)); - printk("MCMDR: %x ",n745_ReadReg(MCMDR,which)); - printk("MISTA: %x ",n745_ReadReg(MISTA,which)); - printk("TXDLSA:%x ", n745_ReadReg(TXDLSA,which)); - printk("RXDLSA:%x \n", n745_ReadReg(RXDLSA,which)); - printk("DMARFC:%x ", n745_ReadReg(DMARFC,which)); - printk("TSDR:%x ", n745_ReadReg(TSDR,which)); - printk("RSDR:%x ", n745_ReadReg(RSDR,which)); - printk("FIFOTHD:%x ", n745_ReadReg(FIFOTHD,which)); - printk("MISTA:%x ", n745_ReadReg(MISTA,which)); - printk("MGSTA:%x ", n745_ReadReg(MGSTA,which)); - - printk("CTXDSA:%x \n",n745_ReadReg(CTXDSA,which)); - printk("CTXBSA:%x ",n745_ReadReg(CTXBSA,which)); - printk("CRXDSA:%x ", n745_ReadReg(CRXDSA,which)); - printk("CRXBSA:%x ", n745_ReadReg(CRXBSA,which)); - printk("RXFSM:%x ",n745_ReadReg(RXFSM,which)); - printk("TXFSM:%x ",n745_ReadReg(TXFSM,which)); - printk("FSM0:%x ",n745_ReadReg(FSM0,which)); - printk("FSM1:%x \n",n745_ReadReg(FSM1,which)); - -} - -void ShowDescriptor(struct net_device *dev) -{ - int i; - struct n745_priv * n745_priv=dev->priv; - for(i=0;itx_desc[i],n745_priv->tx_desc[i].mode,n745_priv->tx_desc[i].SL); - for(i=0;irx_desc[i],n745_priv->rx_desc[i].SL); - printk("tx_ptr:%x,tx_entry:%d\n",n745_priv->tx_ptr,n745_priv->cur_tx_entry); - printk("rx_ptr:%x\n",n745_priv->rx_ptr); - - return; - -} -int prossess_nata(struct net_device *dev,RXBD * rxbd ) -{ - - return 1; -} -int send_frame(struct net_device *dev ,unsigned char *data,int length) -{ - struct n745_priv * priv= dev->priv; - int which; - TXBD *txbd; - unsigned long flags; - - which=priv->which; - - //if (!down_trylock(&priv->locksend)) { - txbd=( TXBD *)priv->tx_ptr; - - //Have a Descriptor For Transmition? - /* - if((txbd->mode&TXfOwnership_DMA)) - { - TRACE_ERROR("send_frame failed\n"); - netif_stop_queue(dev); - return -1; - } - */ - //txbd->mode=(TX_OWNERSHIP_DMA|TX_MODE_PAD|TX_MODE_CRC|TX_MODE_IE); - - //Check Frame Length - if(length>1514) - { - TRACE(" Send Data %d Bytes ,Please Recheck Again\n",length); - length=1514; - } - - txbd->SL=length&0xFFFF; - - memcpy((void *)txbd->buffer,data,length); - - txbd->mode=(PaddingMode | CRCMode | MACTxIntEn); - txbd->mode|= TXfOwnership_DMA; - - { - int val=n745_ReadReg(MCMDR,which); - if(!(val& MCMDR_TXON)) - { - //printk("****n745_WriteReg(MCMDR\n"); - n745_WriteReg(MCMDR,val|MCMDR_TXON,which); - } - n745_WriteReg(TSDR ,0,which); - } - txbd=(TXBD *)txbd->next; - priv->tx_ptr=(unsigned long)txbd; - dev->trans_start=jiffies; - - save_flags(flags); cli(); - if(txbd->mode&TXfOwnership_DMA) - netif_stop_queue(dev); - restore_flags(flags); - return 0; -} -void notify_hit(struct net_device *dev ,RXBD *rxbd) -{ - TRACE("notify_hit not implement\n"); -} - -#define MAC_ADDR 0x7F010008 - -static int n745_init(struct net_device *dev) -{ - static int which=0;//Only one mac for W90N745 - struct n745_priv *priv; - printk("01 %s initial ok!\n",dev->name); - - printk("which:%d\n",which); - //*((unsigned volatile int *) 0xFFF83020) = 0x55555;//lsshi GPIO to PHY - - ether_setup(dev); - dev->open=n745_open; - dev->stop=n745_close; - dev->do_ioctl=n745_do_ioctl; - dev->hard_start_xmit=n745_start_xmit; - dev->tx_timeout=n745_timeout; - dev->get_stats=n745_get_stats; - dev->watchdog_timeo =TX_TIMEOUT; - dev->irq=INT_EMCTXINT0+which; - dev->set_multicast_list=n745_set_multicast_list; - dev->set_mac_address=n745_set_mac_address; - dev->priv =(void *)(((unsigned long) kmalloc(sizeof(struct n745_priv),GFP_KERNEL))|NON_CACHE_FLAG); - - if(dev->priv == NULL) - return -ENOMEM; - memset(dev->priv, 0, sizeof(struct n745_priv)); - -#ifdef CONFIG_WBFLASH - //if( info.type == BOOTLOADER_INFO ) - memcpy(n745_mac_address0,(char*)(MAC_ADDR),ETH_ALEN); -#endif - memcpy(dev->dev_addr,n745_mac_address0,ETH_ALEN); - - priv=(struct n745_priv *)dev->priv; - priv->which=which; - priv->cur_tx_entry=0; - priv->cur_rx_entry=0; - - TRACE("%s initial ok!\n",dev->name); - return 0; - -} - -int init_module(void) -{ - int ret; -#ifdef CONFIG_W90N745FLASH - GetLoadImage(); -#endif - - memset((void *)n745_netdevice[0].name ,0 ,IFNAMSIZ); - ret=register_netdev((struct net_device *)&n745_netdevice[0]); - if(ret!=0) - { - TRACE_ERROR("Regiter EMC 0 W90N745 FAILED\n"); - return -ENODEV; - } - - return 0; -} - -void cleanup_module(void) -{ - unregister_netdev((struct net_device *)&n745_netdevice[0]); -} - -module_init(init_module); -module_exit(cleanup_module); +/* + * linux/deriver/net/w90n745_mac.c + * Ethernet driver for winbond W90N745 ( PC34 Lsshi ) +*/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "w90n745_mac.h" +#include + + +#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("W90N745 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 n745_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 n745_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 n745_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 n745_priv * n745_priv); +int ResetMAC0(struct net_device * dev); +int ResetMAC1(struct net_device * dev); +void ResetMAC(struct net_device * dev); +void ResetRxRing(struct n745_priv * n745_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 n745_netdevice[1]= +{ + {init:n745_init} + //{init:n745_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 n745_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); + + n745_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"); + n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,which)|MCMDR_OPMOD|MCMDR_FDUP,which); + } + else if ((RdValue & 0x80)!=0) + { + n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,which)&~MCMDR_FDUP,which); + n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,which)|MCMDR_OPMOD,which); + TRACE_ERROR("100MB - HALF\n"); + } + else if ((RdValue & 0x40)!=0) /* Full Duplex */ + { + TRACE_ERROR("10MB - FULL\n"); + n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,which)&~MCMDR_OPMOD,which); + n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,which)|MCMDR_FDUP,which); + } + else + { + TRACE_ERROR("10MB - HALF\n"); + n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,which)&~MCMDR_OPMOD,which); + n745_WriteReg(MCMDR,n745_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__); + n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,1)| MCMDR_OPMOD,1); + n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,1)| MCMDR_FDUP,1); + return 0; + } + } + + { + n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,num)|MCMDR_OPMOD,num); + n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,num)|MCMDR_FDUP,num); + } + return 0; + + } +#endif +} + +void ResetMAC(struct net_device * dev) +{ + struct n745_priv * priv=(struct n745_priv *)dev->priv; + int which=priv->which ; + unsigned long val=n745_ReadReg(MCMDR,which); + unsigned long flags; + + save_flags(flags); cli(); + n745_WriteReg(FIFOTHD,0x10000,which); //0x10100 + n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,which)&~(MCMDR_TXON|MCMDR_RXON),which); + n745_WriteReg(FIFOTHD,0x100300,which); //0x10100 + n745_WriteReg(MCMDR,n745_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",n745_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; + + n745_WriteReg(RXDLSA,priv->start_rx_ptr,which); + n745_WriteReg(TXDLSA,priv->start_tx_ptr,which); + n745_WriteReg(DMARFC,PACKET_SIZE,which); + + n745_WriteCam(priv->which,0,dev->dev_addr); + + n745_WriteReg(CAMEN,n745_ReadReg(CAMEN,priv->which) | 1,priv->which); + + n745_WriteReg(CAMCMR,CAMCMR_ECMP|CAMCMR_ABP|CAMCMR_AMP,which); + + /* Configure the MAC control registers. */ + n745_WriteReg(MIEN,gMIEN,which); + //n745_WriteReg(MCMDR,priv->mcmdr,priv->which); + if(which==0) + { + Enable_Int(INT_EMCTXINT0); + Enable_Int(INT_EMCRXINT0); + } + + + { + + n745_WriteReg(MCMDR,MCMDR_TXON|MCMDR_RXON|val,which); + n745_WriteReg(TSDR ,0,which); + n745_WriteReg(RSDR ,0,which); + } + + n745_WriteReg(MISTA,n745_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 W90N745 +* 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; + n745_WriteReg(MIID,PhyWrData,which); + n745_WriteReg(MIIDA,PhyInAddr|PhyAddr|PHYBUSY|PHYWR|MDCCR1,which); + while(i--); + while((n745_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 W90N745 +* 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 + n745_WriteReg(MIIDA, PhyInAddr | PhyAddr | PHYBUSY | MDCCR1,which); + while( (n745_ReadReg(MIIDA,which)& PHYBUSY) ) + { + loop--; + if(loop==0) + return (unsigned long)1; + } + + PhyRdData = n745_ReadReg(MIID,which) ; + return PhyRdData ; +} + +/************************************************************************ +* FUNCTION +* n745_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 n745_set_mac_address(struct net_device *dev, void *addr) +{ + struct n745_priv * priv=(struct n745_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); + + memcpy(n745_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]); + + //n745_WriteReg(CAMEN,n745_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 n745_priv * n745_priv=dev->priv; + + n745_priv->start_tx_ptr =(unsigned long)&n745_priv->tx_desc[0]|NON_CACHE_FLAG; + n745_priv->start_tx_buf =(unsigned long)&n745_priv->tx_buf[0] | NON_CACHE_FLAG; + + n745_priv->start_rx_ptr =(unsigned long)&n745_priv->rx_desc[0]|NON_CACHE_FLAG; + n745_priv->start_rx_buf =(unsigned long)&n745_priv->rx_buf[0] | NON_CACHE_FLAG; + + + //Tx Ring + MAC_ASSERT(n745_priv->start_tx_ptr ); + MAC_ASSERT(n745_priv->start_tx_buf ); + TRACE(" tx which %d start_tx_ptr %x\n",n745_priv->which,n745_priv->start_tx_ptr); + + for ( i = 0 ; i < TX_DESC_SIZE ; i++ ) + { + //n745_priv->tx_desc[i]=0; + n745_priv->tx_desc[i].SL=0; + n745_priv->tx_desc[i].mode=0; + n745_priv->tx_desc[i].buffer=(unsigned long)&n745_priv->tx_buf[i]|NON_CACHE_FLAG; + n745_priv->tx_desc[i].next=(unsigned long)&n745_priv->tx_desc[i+1]|NON_CACHE_FLAG; + TRACE(" *tx cur %d desc %x buffer %x", i, &n745_priv->tx_desc[i],n745_priv->tx_desc[i].buffer); + TRACE(" next %x\n",n745_priv->tx_desc[i].next); + } + n745_priv->tx_desc[i-1].next=(unsigned long)&n745_priv->tx_desc[0]|NON_CACHE_FLAG; + TRACE(" * cur %d desc %x buffer %x", i-1, &n745_priv->tx_desc[i-1],n745_priv->tx_desc[i-1].buffer); + TRACE(" next %x\n",n745_priv->tx_desc[i-1].next); + + //Rx Ring + MAC_ASSERT(n745_priv->start_rx_ptr ); + MAC_ASSERT(n745_priv->start_rx_buf ); + TRACE(" tx which %d start_rx_ptr %x\n",n745_priv->which,n745_priv->start_rx_ptr); + + for( i =0 ; i < RX_DESC_SIZE ; i++) + { + n745_priv->rx_desc[i].SL=RXfOwnership_DMA; + + n745_priv->rx_desc[i].buffer=(unsigned long)&n745_priv->rx_buf[i]|NON_CACHE_FLAG; + n745_priv->rx_desc[i].next=(unsigned long)&n745_priv->rx_desc[i+1]|NON_CACHE_FLAG; + + TRACE(" # rx which %d,desc %d desc-addr %x", n745_priv->which,i, &n745_priv->rx_desc[i]); + TRACE(" next %x\n",n745_priv->rx_desc[i].next); + } + n745_priv->rx_desc[i-1].next=(unsigned long)&n745_priv->rx_desc[0]|NON_CACHE_FLAG; + +} +#ifdef AUTO_SENSE + +#define MAX_AN_CHECK 5 +static int an_check; + +static void w745_autodetect(unsigned long arg) +{ + struct net_device * dev =(struct net_device *)arg; + struct n745_priv * priv=(struct n745_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 n745_priv * priv=(struct n745_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"); + n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,0)|MCMDR_OPMOD|MCMDR_FDUP,0); + } + else if ((RdValue & 0x80)!=0) + { + n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,0)&~MCMDR_FDUP,0); + n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,0)|MCMDR_OPMOD,0); + TRACE_ERROR("100MB - HALF\n"); + } + else if ((RdValue & 0x40)!=0)/* Full Duplex */ + { + TRACE_ERROR("10MB - FULL\n"); + n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,0)&~MCMDR_OPMOD,0); + n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,0)|MCMDR_FDUP,0); + } + else + { + TRACE_ERROR("10MB - HALF\n"); + n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,0)&~MCMDR_OPMOD,0); + n745_WriteReg(MCMDR,n745_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 +* n745_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 n745_open(struct net_device *dev) +{ + struct n745_priv * priv; + int which ; + + priv=(struct n745_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 ; + + n745_WriteReg(FIFOTHD,0x10000,which); //0x10100 + n745_WriteReg(FIFOTHD,0x100300,which); //0x10100 + n745_WriteReg(RXDLSA,priv->start_rx_ptr,which); + n745_WriteReg(TXDLSA,priv->start_tx_ptr,which); + n745_WriteReg(DMARFC,2000,which); + + n745_WriteCam(priv->which,0,dev->dev_addr); + n745_WriteReg(CAMEN,n745_ReadReg(CAMEN,priv->which) | 1,priv->which); + + n745_WriteReg(CAMCMR,CAMCMR_ECMP|CAMCMR_ABP|CAMCMR_AMP,which); + //n745_WriteReg(CAMCMR,CAMCMR_ECMP|CAMCMR_ABP|CAMCMR_AMP|CAMCMR_AUP,which); + + n745_WriteReg(MCMDR,1<<19,which); + + *(unsigned int volatile *)(0xfff83020) = 0x50000; + *(unsigned int volatile *)(0xfff83024) = 0; // Make sure all 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. */ + n745_WriteReg(MIEN,gMIEN,which); + n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,which)|gMCMDR,which); + n745_WriteReg(MCMDR,n745_ReadReg(MCMDR,which)|MCMDR_RXON,which); + + priv->mcmdr=n745_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 = w745_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 "W90N745 : 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 "W90N745 : register irq rx failed\n"); + return -EAGAIN; + } + netif_start_queue(dev); + n745_WriteReg(RSDR ,0,which); + + if(resetPhyOk == 1) + *(unsigned int volatile *)(0xfff83020) = 0x55555; + + TRACE("%s is OPENED\n",dev->name); + return 0; +} + + +static int n745_close(struct net_device *dev) +{ + struct n745_priv *priv=(struct n745_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); + n745_WriteReg(MCMDR,0,which); + free_irq(INT_EMCTXINT0+which,dev); + free_irq(INT_EMCRXINT0+which,dev); + + TRACE_ERROR(KERN_ERR "W90N745 : n745_close\n"); + + return 0; +} + +/* Get the current statistics. This may be called with the card open or + closed. */ + +static struct net_device_stats * n745_get_stats(struct net_device *dev) +{ + struct n745_priv *priv = (struct n745_priv *)dev->priv; + + return &priv->stats; +} + +static void n745_timeout(struct net_device *dev) +{ + struct n745_priv * priv=(struct n745_priv *)dev->priv; + int which=priv->which; + +#ifdef DEBUG + int i=0; + unsigned long cur_ptr; + TXBD *txbd; + + cur_ptr=n745_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), + n745_ReadReg(MIEN,which),n745_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",n745_ReadReg(RXFSM,which)); + printk("TXFSM:%x\n",n745_ReadReg(TXFSM,which)); + printk("FSM0:%x\n",n745_ReadReg(FSM0,which)); + printk("FSM1:%x\n",n745_ReadReg(FSM1,which)); + //if((n745_ReadReg(TXFSM,which)&0x0FFF0000)==0x8200000) + ResetMAC(dev); + } + dev->trans_start = jiffies; + +} + +static int n745_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ +#ifdef DEBUG + char *data; + int i=0; + int len=skb->len; + for(i=0;idata,skb->len)) ) + { + dev_kfree_skb(skb); + TRACE("n745_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 n745_priv *priv = (struct n745_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=n745_ReadReg(MISTA,which); //get interrupt status; + //n745_WriteReg(MISTA,status&0xFFFF0000,which); //clear interrupt + n745_WriteReg(MISTA,status,which); //clear interrupt + restore_flags(flags); + + cur_ptr=n745_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("W90N745 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 n745_priv *priv = (struct n745_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=n745_ReadReg(MISTA,which); //get interrupt status; + save_flags(flags); cli(); + //n745_WriteReg(MISTA,status&0xFFFF,which); //clear interrupt + n745_WriteReg(MISTA,status,which); //clear interrupt + restore_flags(flags); + + priv->cur_rx_entry++; + + 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); + } + n745_WriteReg(RSDR ,0,which); + TRACE("* %d rx_interrupt MISTA %x \n",irq,status); + + return ; + } + save_flags(flags); cli(); + n745_WriteReg(MISTA,status,which); //clear interrupt + restore_flags(flags); + netdev_rx(dev); +} + +void ResetMACRx(struct net_device * dev) + { + struct n745_priv * priv=(struct n745_priv *)dev->priv; + unsigned long val=n745_ReadReg(MCMDR,priv->which); + //printk("In ResetMAC Rx \n"); + ResetRxRing(dev->priv); + n745_WriteReg(MCMDR,(MCMDR_RXON|val),priv->which); +} + +void ResetMACTx(struct net_device * dev) +{ + struct n745_priv * priv=(struct n745_priv *)dev->priv; + unsigned long val=n745_ReadReg(MCMDR,priv->which); + printk("In ResetMAC Tx \n"); + //ResetTxRing(dev->priv); + n745_WriteReg(MCMDR,(MCMDR_TXON|val),priv->which); +} + + void ResetRxRing(struct n745_priv * n745_priv) + { + + int i; + for( i =0 ; i < RX_DESC_SIZE ; i++) + { + n745_priv->rx_desc[i].SL=0; + n745_priv->rx_desc[i].SL|=RXfOwnership_DMA; + } + +} +#if 0 +void DescriptorLock(struct n745_priv * priv) +{ + unsigned long flags; + save_flags(flags); cli(); + if(priv->lock==1) + + while(priv->lock==1); + priv->lock=1; + restore_flags(flags); + +} +void DescriptorUnLock(struct n745_priv * priv) +{ + unsigned long flags; + save_flags(flags); cli(); + priv->lock=0; + restore_flags(flags); +} +/*0:failed,1:success*/ +int DescriptorTryLock(struct n745_priv * priv) +{ + unsigned long flags; + save_flags(flags); cli(); + if(priv->lock) + return 0; + priv->lock=1; + restore_flags(flags); + return 1; +} +#endif + +/* We have a good packet(s), get it/them out of the buffers. */ +static void netdev_rx(struct net_device *dev) +{ + struct n745_priv * priv = (struct n745_priv *)dev->priv; + RXBD *rxbd; + unsigned long length; + unsigned long status; + int flag=0; + + rxbd=(RXBD *)priv->rx_ptr ; + + do + { + + if(priv->is_rx_all>0) + { + flag=1; + --priv->is_rx_all; + } + else if(flag==1) + { + flag=0; + break; + } + else if((n745_ReadReg(CRXDSA,priv->which)==(unsigned long)rxbd)) + { + break; + } + + /* if(!(rxbd->SL & RXfOwnership_CPU)) + { + if(priv->is_rx_all) + rxbd->SL |=RXfOwnership_DMA; + + priv->rx_ptr=( RXBD *)rxbd->next; + rxbd=priv->rx_ptr; + continue; + } + */ + + length = rxbd->SL & 0xFFFF; + status = (rxbd->SL & 0xFFFF0000)&((unsigned long)~0 >>2); + + if(status & RXDS_RXGD) + { + unsigned char * data; + struct sk_buff * skb; + + data = (unsigned char *) rxbd->buffer; + + skb = dev_alloc_skb(length+2); //Get Skb Buffer; + if(!skb) { + TRACE_ERROR("W90N745: I Have Not Got Memory In Fun %s\n",__FUNCTION__); + priv->stats.rx_dropped++; + return; + } + + skb->dev = dev; + skb_reserve(skb, 2); //For IP Align 4-byte + skb_put(skb, length); + eth_copy_and_sum(skb, data, length, 0); //copy + skb->protocol = eth_type_trans(skb, dev); + priv->stats.rx_packets++; + priv->stats.rx_bytes += length; + netif_rx(skb); // Enqueue for Up Layer + + } + else + { + + if(priv->is_rx_all==RX_DESC_SIZE) + TRACE_ERROR("Rx error:%x,rxbd:%x,priv->is_rx_all:%d\n",status,rxbd,priv->is_rx_all); + priv->stats.rx_errors++; + if(status & RXDS_RP ) + { + TRACE_ERROR("W90N745 MAC: Receive Runt Packet Drop it!\n"); + priv->stats.rx_length_errors++; + } + if(status & RXDS_CRCE ) + { + TRACE_ERROR("W90N745 MAC Receive CRC Packet Drop It! \n"); + priv->stats.rx_crc_errors ++; + } + if(status & RXDS_ALIE ) + { + TRACE_ERROR("W90N745 MAC Receive Aligment Packet Dropt It!\n"); + priv->stats.rx_frame_errors++; + } + + if(status & RXDS_PTLE) + { + TRACE_ERROR("W90N745 MAC Receive Too Long Packet Dropt It!\n"); + priv->stats.rx_over_errors++; + } + } + + //rxbd->SL= RX_OWNERSHIP_DMA; //clear status and set dma flag + rxbd->SL =RXfOwnership_DMA; + rxbd->reserved = 0; + priv->rx_ptr=(unsigned long)rxbd->next; + rxbd=(RXBD *)priv->rx_ptr; + dev->last_rx = jiffies; + }while(1); + priv->is_rx_all = 0; +} + +static void n745_set_multicast_list(struct net_device *dev) +{ + + struct n745_priv *priv = (struct n745_priv *)dev->priv; + unsigned long rx_mode; +//printk("n745_set_multicast_list\n"); + int which=priv->which; + + if(dev->flags&IFF_PROMISC) + { + rx_mode = CAMCMR_AUP|CAMCMR_AMP|CAMCMR_ABP|CAMCMR_ECMP; + TRACE("W90N745 : Set Prommisc Flag \n"); + + } + else if((dev->flags&IFF_ALLMULTI)||dev->mc_list) + { + + rx_mode=CAMCMR_AMP|CAMCMR_ABP|CAMCMR_ECMP; + } + else + { + rx_mode = CAMCMR_ECMP|CAMCMR_ABP; + TRACE("W90N745 :Set Compare Flag\n"); + } + + //rx_mode=CAMCMR_AMP|CAMCMR_ABP|CAMCMR_ECMP;//|CAMCMR_AUP; + priv->rx_mode=rx_mode; + n745_WriteReg(CAMCMR,rx_mode,which); + +} +#define SIODEVSTARTNATA 0x6677 +#define SIODEVSTARTNATA 0x6688 + +static int n745_do_ioctl(struct net_device *dev,struct ifreq *ifr,int cmd) +{ + //u16 *data = (u16 *)&ifr->ifr_data; + struct n745_priv *priv=dev->priv; + int which = priv->which; + + printk("W90N745 IOCTL:\n"); + + switch(cmd) + { + case SIOCSIFHWADDR: + if(dev->flags&IFF_PROMISC) + return -1; + + memcpy(dev->dev_addr,ifr->ifr_hwaddr.sa_data,ETH_ALEN); + + memcpy(n745_mac_address0,dev->dev_addr,ETH_ALEN); + + n745_set_mac_address(dev,dev->dev_addr); + + break; + + #define SIOCn745MACDEGUG SIOCDEVPRIVATE+1 + case SIOCn745MACDEGUG : //For Debug; + output_register_context(which); + break; + + default: + return -EOPNOTSUPP; + } + return 0; +} +void output_register_context(int which) +{ + printk(" ** W90N745 EMC Register %d **\n",which); + + printk("CAMCMR:%x ",n745_ReadReg(CAMCMR,which)); + printk("CAMEN:%x ",n745_ReadReg(CAMEN,which)); + printk("MIEN: %x ",n745_ReadReg(MIEN,which)); + printk("MCMDR: %x ",n745_ReadReg(MCMDR,which)); + printk("MISTA: %x ",n745_ReadReg(MISTA,which)); + printk("TXDLSA:%x ", n745_ReadReg(TXDLSA,which)); + printk("RXDLSA:%x \n", n745_ReadReg(RXDLSA,which)); + printk("DMARFC:%x ", n745_ReadReg(DMARFC,which)); + printk("TSDR:%x ", n745_ReadReg(TSDR,which)); + printk("RSDR:%x ", n745_ReadReg(RSDR,which)); + printk("FIFOTHD:%x ", n745_ReadReg(FIFOTHD,which)); + printk("MISTA:%x ", n745_ReadReg(MISTA,which)); + printk("MGSTA:%x ", n745_ReadReg(MGSTA,which)); + + printk("CTXDSA:%x \n",n745_ReadReg(CTXDSA,which)); + printk("CTXBSA:%x ",n745_ReadReg(CTXBSA,which)); + printk("CRXDSA:%x ", n745_ReadReg(CRXDSA,which)); + printk("CRXBSA:%x ", n745_ReadReg(CRXBSA,which)); + printk("RXFSM:%x ",n745_ReadReg(RXFSM,which)); + printk("TXFSM:%x ",n745_ReadReg(TXFSM,which)); + printk("FSM0:%x ",n745_ReadReg(FSM0,which)); + printk("FSM1:%x \n",n745_ReadReg(FSM1,which)); + +} + +void ShowDescriptor(struct net_device *dev) +{ + int i; + struct n745_priv * n745_priv=dev->priv; + for(i=0;itx_desc[i],n745_priv->tx_desc[i].mode,n745_priv->tx_desc[i].SL); + for(i=0;irx_desc[i],n745_priv->rx_desc[i].SL); + printk("tx_ptr:%x,tx_entry:%d\n",n745_priv->tx_ptr,n745_priv->cur_tx_entry); + printk("rx_ptr:%x\n",n745_priv->rx_ptr); + + return; + +} +int prossess_nata(struct net_device *dev,RXBD * rxbd ) +{ + + return 1; +} +int send_frame(struct net_device *dev ,unsigned char *data,int length) +{ + struct n745_priv * priv= dev->priv; + int which; + TXBD *txbd; + unsigned long flags; + + which=priv->which; + + //if (!down_trylock(&priv->locksend)) { + txbd=( TXBD *)priv->tx_ptr; + + //Have a Descriptor For Transmition? + /* + if((txbd->mode&TXfOwnership_DMA)) + { + TRACE_ERROR("send_frame failed\n"); + netif_stop_queue(dev); + return -1; + } + */ + //txbd->mode=(TX_OWNERSHIP_DMA|TX_MODE_PAD|TX_MODE_CRC|TX_MODE_IE); + + //Check Frame Length + if(length>1514) + { + TRACE(" Send Data %d Bytes ,Please Recheck Again\n",length); + length=1514; + } + + txbd->SL=length&0xFFFF; + + memcpy((void *)txbd->buffer,data,length); + + txbd->mode=(PaddingMode | CRCMode | MACTxIntEn); + txbd->mode|= TXfOwnership_DMA; + + { + int val=n745_ReadReg(MCMDR,which); + if(!(val& MCMDR_TXON)) + { + //printk("****n745_WriteReg(MCMDR\n"); + n745_WriteReg(MCMDR,val|MCMDR_TXON,which); + } + n745_WriteReg(TSDR ,0,which); + } + txbd=(TXBD *)txbd->next; + priv->tx_ptr=(unsigned long)txbd; + dev->trans_start=jiffies; + + save_flags(flags); cli(); + if(txbd->mode&TXfOwnership_DMA) + netif_stop_queue(dev); + restore_flags(flags); + return 0; +} +void notify_hit(struct net_device *dev ,RXBD *rxbd) +{ + TRACE("notify_hit not implement\n"); +} + +#define MAC_ADDR 0x7F010008 + +static int n745_init(struct net_device *dev) +{ + static int which=0;//Only one mac for W90N745 + struct n745_priv *priv; + printk("01 %s initial ok!\n",dev->name); + + printk("which:%d\n",which); + //*((unsigned volatile int *) 0xFFF83020) = 0x55555;//lsshi GPIO to PHY + + ether_setup(dev); + dev->open=n745_open; + dev->stop=n745_close; + dev->do_ioctl=n745_do_ioctl; + dev->hard_start_xmit=n745_start_xmit; + dev->tx_timeout=n745_timeout; + dev->get_stats=n745_get_stats; + dev->watchdog_timeo =TX_TIMEOUT; + dev->irq=INT_EMCTXINT0+which; + dev->set_multicast_list=n745_set_multicast_list; + dev->set_mac_address=n745_set_mac_address; + dev->priv =(void *)(((unsigned long) kmalloc(sizeof(struct n745_priv),GFP_KERNEL))|NON_CACHE_FLAG); + + if(dev->priv == NULL) + return -ENOMEM; + memset(dev->priv, 0, sizeof(struct n745_priv)); + +#ifdef CONFIG_WBFLASH + //if( info.type == BOOTLOADER_INFO ) + memcpy(n745_mac_address0,(char*)(MAC_ADDR),ETH_ALEN); +#endif + memcpy(dev->dev_addr,n745_mac_address0,ETH_ALEN); + + priv=(struct n745_priv *)dev->priv; + priv->which=which; + priv->cur_tx_entry=0; + priv->cur_rx_entry=0; + + TRACE("%s initial ok!\n",dev->name); + return 0; + +} + +int init_module(void) +{ + int ret; +#ifdef CONFIG_W90N745FLASH + GetLoadImage(); +#endif + + memset((void *)n745_netdevice[0].name ,0 ,IFNAMSIZ); + ret=register_netdev((struct net_device *)&n745_netdevice[0]); + if(ret!=0) + { + TRACE_ERROR("Regiter EMC 0 W90N745 FAILED\n"); + return -ENODEV; + } + + return 0; +} + +void cleanup_module(void) +{ + unregister_netdev((struct net_device *)&n745_netdevice[0]); +} + +module_init(init_module); +module_exit(cleanup_module); diff --git a/uClinux-2.4.20-uc1/drivers/net/w90n745_mac.h b/uClinux-2.4.20-uc1/drivers/net/w90n745_mac.h index 684f7bd..c1833f1 100755 --- a/uClinux-2.4.20-uc1/drivers/net/w90n745_mac.h +++ b/uClinux-2.4.20-uc1/drivers/net/w90n745_mac.h @@ -1,354 +1,354 @@ -/**************************************************************************** - * * - * Copyright (c) 2005 - 2007 Winbond Electronics Corp. All rights reserved. * - * * - ****************************************************************************/ - -/**************************************************************************** - * - * FILENAME - * w90n745_mac.h - * - * VERSION - * 1.0 - * - * DESCRIPTION - * The head file for MAC driver on POS-TAX Board - * - * DATA STRUCTURES - * None - * - * FUNCTIONS - * None - * - * HISTORY - * 2005/08/01 Ver 1.0 - * - * AUTHOR - * PC34 Lsshi - * - * REMARK - * None - *************************************************************************/ -#ifndef _W90N745_MAC_H_ -#define _W90N745_MAC_H_ - -#define NON_CACHE_FLAG 0x80000000 - -#define MAC_OFFSET 0x0 -#define MAC_0_OFFSET MAC_OFFSET - -// Advanced Interrupt Controller Registers -#define AIC_SCR_EMCTX0 (VPint(AIC_SCR17)) -#define AIC_SCR_EMCRX0 (VPint(AIC_SCR18)) - -//CAM Registers -#define CAMCMR (MAC_OFFSET) //CAM Command Regiser -#define CAMEN (MAC_OFFSET+0x4)//CAM ennable regiser -#define CAM0M (MAC_OFFSET+0x8)//CAM1 Most significant Word register -#define CAM0L (MAC_OFFSET+0xc)//CAM1 Least Significant Word Register -#define CAM_ENTRY_SIZE 0x8 //CAM entry size -#define CAM_ENTRIES 0x16 //CAM entries - -//MAC Regiseters -#define MIEN (MAC_OFFSET+0xac) //MAC Interrupt Enable Register -#define MCMDR (MAC_OFFSET+0x90) //MAC Command Regiser -#define MIID (MAC_OFFSET+0x94) //MII Management Data Register -#define MIIDA (MAC_OFFSET+0x98) //MII Management Data Control and Address Register -#define MPCNT (MAC_OFFSET+0xb8) //Missed Packet Counter Register - -//DMA Registers -#define TXDLSA (MAC_OFFSET+0x88) //Transmit Descriptor Link List Start Address Regiser -#define RXDLSA (MAC_OFFSET+0x8c) //Receive Descriptor LInk List Start Addresss Register -#define DMARFC (MAC_OFFSET+0xa8) //DMA Receive Frame Control Register -#define TSDR (MAC_OFFSET+0xa0) //Transmit Start Demand Register -#define RSDR (MAC_OFFSET+0xa4) //Recevie Start Demand Register -#define FIFOTHD (MAC_OFFSET+0x9c) //FIFO Threshold Adjustment Register - -//EMC Status Register -#define MISTA (MAC_OFFSET+0xb0) //MAC Interrupter Status Register -#define MGSTA (MAC_OFFSET+0xb4) //MAC General Status Register -#define MRPC (MAC_OFFSET+0xbc) //MAC Receive Pauese counter register -#define MRPCC (MAC_OFFSET+0xc0) //MAC Receive Pauese Current Count Regiser -#define MREPC (MAC_OFFSET+0xc4) //MAC Remote pause count retister - -//DMA Registers -#define DMARFS (MAC_OFFSET+0xc8) //DMA Receive Frame Status Register -#define CTXDSA (MAC_OFFSET+0xcc) //Current Transmit Descriptor Start Addresss Register -#define CTXBSA (MAC_OFFSET+0xd0) //Current Transmit Buffer Start Address Regiser -#define CRXDSA (MAC_OFFSET+0xd4) //Current Receive Descriptor start Address regiser -#define CRXBSA (MAC_OFFSET+0xd8) //Current Receive Buffer Start Address Regiser - -//Debug Mode Receive Finite State Machine Registers -#define RXFSM (MAC_OFFSET+0x200) -#define TXFSM (MAC_OFFSET+0x204) -#define FSM0 (MAC_OFFSET+0x208) -#define FSM1 (MAC_OFFSET+0x20c) - -//Descriptor -typedef struct -{ - volatile unsigned long SL; - volatile unsigned long buffer; - volatile unsigned long reserved; - volatile unsigned long next; -}RXBD; - - -typedef struct -{ - volatile unsigned long mode; - volatile unsigned long buffer; - volatile unsigned long SL; - volatile unsigned long next; -}TXBD; - - -// CAM Command Register(CAMCMR) -#define CAM_AUP 0x0001 // Accept Packets with Unicast Address -#define CAM_AMP 0x0002 // Accept Packets with Multicast Address -#define CAM_ABP 0x0004 // Accept Packets with Broadcast Address -#define CAM_CCAM 0x0008 // 0: Accept Packets CAM Recognizes and Reject Others - // 1: Reject Packets CAM Recognizes and Accept Others -#define CAM_ECMP 0x0010 // Enable CAM Compare -//ownership bit -#define RX_OWNERSHIP_CPU (0x0<<30) -#define RX_OWNERSHIP_DMA (2<<30) - -#define TX_OWNERSHIP_CPU (0x0<<30) -#define TX_OWNERSHIP_DMA (2<<30) - -// RX Frame Descriptor's Owner bit -#define RXfOwnership_DMA 0x80000000 // 10 = DMA -#define RXfOwnership_CPU 0x3fffffff // 00 = CPU - -// TX Frame Descriptor's Owner bit -#define TXfOwnership_DMA 0x80000000 // 1 = DMA -#define TXfOwnership_CPU 0x7fffffff // 0 = CPU - -// Tx Frame Descriptor's Control bits -#define MACTxIntEn 0x04 -#define CRCMode 0x02 -#define NoCRCMode 0x00 -#define PaddingMode 0x01 -#define NoPaddingMode 0x00 - -//received descriptor status -#define RXDS_RXINTR (1<<16) //set if reception of packet caused an interrupt condition -#define RXDS_CRCE (1<<17) // set if crc error -#define RXDS_PTLE (1<<19) //set if received frame longer than 1518 bytes -#define RXDS_RXGD (1<<20) // receiving good packet -#define RXDS_ALIE (1<<21) //Alignment Error -#define RXDS_RP (1<<22) //runt packet -#define RXDS_Inverse (1<<26) //current hit entry is setting on inverse mode -#define RXDS_PortHit (1<<27) //port hit -#define RXDS_IPHit (1<<28) //ip hit -#define RXDS_Hit (1<<29) //hit - -//Tx ownership bit -#define TX_OWNERSHIP_CPU (0x0<<31) -#define TX_OWNERSHIP_DMA (0x1<<31) -//tx mode -#define TX_MODE_PAD 0x1 //pad -#define TX_MODE_CRC (0x1<<1) //crc mode -#define TX_MODE_IE (0x1<<2) //interrupt enable - -//Tx status -#define TXDS_TXINTR (1<<16) //Interruput on Transmit -#define TXDS_DEF (1<<17) //Transmit defered -#define TXDS_TXCP (1<<19) //Transmit Completion -#define TXDS_EXDEF (1<<20) //exceed deferal -#define TXDS_NCS (1<<21) //No Carrier Sense Error -#define TXDS_TXABT (1<<22) //transimtting aborted -#define TXDS_LC (1<<23) //late collision -#define TXDS_TXHA (1<<24) //transmitting halted -#define TXDS_PAU (1<<25) //Paused -#define TXDS_SQE (1<<26) //SQE error -#define TXDS_CCNT (0xf<<27) //transmit collision count -//cam command regiser -#define CAMCMR_AUP 0x1 //Accept unicast packet -#define CAMCMR_AMP (0x1<<1) //Accpet multicast packet -#define CAMCMR_ABP (0x1<<2) //Accept broadcast packet -#define CAMCMR_CCAM (0x1<<3) //complement CAM -#define CAMCMR_ECMP (0x1<<4) //Enable CAM compare - - -// MAC MII Management Data Control and Address Register(MIIDA) -#define MDCCR 0x00300000 // MDC clock rating -#define PHYAD 0x00000100 // PHY Address -#define PHYWR 0x00010000 // Write Operation -#define PHYBUSY 0x00020000 // Busy Bit -#define PHYPreSP 0x00040000 // Preamble Suppress - -// PHY(DM9161) Register Description -#define PHY_CNTL_REG 0x00 -#define PHY_STATUS_REG 0x01 -#define PHY_ID1_REG 0x02 -#define PHY_ID2_REG 0x03 -#define PHY_ANA_REG 0x04 -#define PHY_ANLPA_REG 0x05 -#define PHY_ANE_REG 0x06 - -#define PHY_DSC_REG 0x10 -#define PHY_DSCS_REG 0x11 -#define PHY_10BTCS_REG 0x12 -#define PHY_SINT_REG 0x15 -#define PHY_SREC_REG 0x16 -#define PHY_DISC_REG 0x17 - -//PHY Control Register -#define RESET_PHY (1 << 15) -#define ENABLE_LOOPBACK (1 << 14) -#define DR_100MB (1 << 13) -#define ENABLE_AN (1 << 12) -#define PHY_MAC_ISOLATE (1 << 10) -#define RESTART_AN (1 << 9) -#define PHY_FULLDUPLEX (1 << 8) -#define PHY_COL_TEST (1 << 7) - - -// MAC Interrupt Enable Register(MIEN) -#define EnRXINTR 0x00000001 // Enable Interrupt on Receive Interrupt -#define EnCRCE 0x00000002 // Enable CRC Error Interrupt -#define EnRXOV 0x00000004 // Enable Receive FIFO Overflow Interrupt -#define EnPTLE 0x00000008 // Enable Packet Too Long Interrupt -#define EnRXGD 0x00000010 // Enable Receive Good Interrupt -#define EnALIE 0x00000020 // Enable Alignment Error Interrupt -#define EnRP 0x00000040 // Enable Runt Packet on Receive Interrupt -#define EnMMP 0x00000080 // Enable More Missed Packets Interrupt -#define EnDFO 0x00000100 // Enable DMA receive frame over maximum size Interrupt -#define EnDEN 0x00000200 // Enable DMA early notification Interrupt -#define EnRDU 0x00000400 // Enable Receive Descriptor Unavailable Interrupt -#define EnRxBErr 0x00000800 // Enable Receive Bus ERROR interrupt -#define EnCFR 0x00004000 // Enable Control Frame Receive Interrupt -#define EnTXINTR 0x00010000 // Enable Interrupt on Transmit Interrupt -#define EnTXEMP 0x00020000 // Enable Transmit FIFO Empty Interrupt -#define EnTXCP 0x00040000 // Enable Transmit Completion Interrupt -#define EnEXDEF 0x00080000 // Enable Defer Interrupt -#define EnNCS 0x00100000 // Enable No Carrier Sense Interrupt -#define EnTXABT 0x00200000 // Enable Transmit Abort Interrupt -#define EnLC 0x00400000 // Enable Late Collision Interrupt -#define EnTDU 0x00800000 // Enable Transmit Descriptor Unavailable Interrupt -#define EnTxBErr 0x01000000 // Enable Transmit Bus ERROR Interrupt - -// PHY Status Register -#define AN_COMPLETE (1 << 5) - -// PHY Auto-negotiation Advertisement Register - -#define MODE_DR100_FULL 3 -#define MODE_DR100_HALF 2 -#define MODE_DR10_FULL 1 -#define MODE_DR10_HALF 0 - - -#define DR100_TX_FULL (1 << 8) -#define DR100_TX_HALF (1 << 7) -#define DR10_TX_FULL (1 << 6) -#define DR10_TX_HALF (1 << 5) -#define IEEE_802_3_CSMA_CD 1 - - - -//MAC Interrupt Enable Register -#define MIEN_EnRXINTR 1 -#define MIEN_EnCRCE (1<<1) -#define MIEN_EnRXOV (1<<2) -#define MIEN_EnPTLE (1<<3) -#define MIEN_EnRXGD (1<<4) -#define MIEN_EnALIE (1<<5) -#define MIEN_EnRP (1<<6) -#define MIEN_EnMMP (1<<7) -#define MIEN_EnDFO (1<<8) -#define MIEN_EnDEN (1<<9) -#define MIEN_EnRDU (1<<10) -#define MIEN_EnRXBErr (1<<11) -#define MIEN_EnCFR (1<<14) -#define MIEN_EnTXINTR (1<<16) -#define MIEN_EnTXEMP (1<<17) -#define MIEN_EnTXCP (1<<18) -#define MIEN_EnEXDEF (1<<19) -#define MIEN_EnNCS (1<<20) -#define MIEN_EnTXABT (1<<21) -#define MIEN_EnLC (1<<22) -#define MIEN_EnTDU (1<<23) -#define MIEN_EnTxBErr (1<<24) -//MAC Command Regiser -#define MCMDR_RXON 1 -#define MCMDR_ALP (1<<1) -#define MCMDR_ARP (1<<2) -#define MCMDR_ACP (1<<3) -#define MCMDR_AEP (1<<4) -#define MCMDR_SPCRC (1<<5) -#define MCMDR_TXON (1<<8) -#define MCMDR_NDEF (1<<9) -#define MCMDR_SDPZ (1<<16) -#define MCMDR_EnSQE (1<<17) -#define MCMDR_FDUP (1<<18) -#define MCMDR_EnMDC (1<<19) -#define MCMDR_OPMOD (1<<20) -#define MCMDR_LBK (1<<21) -//#define MCMDR_EnMII (1<<22) -//#define MCMDR_LAN (1<<23) -#define SWR (1<<24)//lsshi add 2005-4-22 12:07 - - -//MAC MII Management Data Control and Address Register -#define MIIDA_PHYRAD 1 -#define MIIDA_PHYAD (1<<8) -#define MIIDA_WR (1<<16) -#define MIIDA_BUSY (1<<17) -#define MIIDA_PreSP (1<<18) -#define MIIDA_MDCON (1<<19) -#define MIIDA_MDCCR (1<<20) - -//FIFO Threshold Adjustment Register -#define FIFOTHD_RxTHD 1 -#define FIFOTHD_TxTHD (1<<8) -#define FIFOTHD_SWR (1<<16) -#define FIFOTHD_Blength (1<<20) -//MAC Interrupt Status Register -#define MISTA_RXINTR 1 -#define MISTA_CRCE (1<<1) -#define MISTA_RXOV (1<<2) -#define MISTA_PTLE (1<<3) -#define MISTA_RXGD (1<<4) -#define MISTA_ALIE (1<<5) -#define MISTA_RP (1<<6) -#define MISTA_MMP (1<<7) -#define MISTA_DFOI (1<<8) -#define MISTA_DENI (1<<9) -#define MISTA_RDU (1<<10) -#define MISTA_RxBErr (1<<11) -#define MISTA_CFR (1<<14) -#define MISTA_TXINTR (1<<16) -#define MISTA_TXEMP (1<<17) -#define MISTA_TXCP (1<<18) -#define MISTA_EXDEF (1<<19) -#define MISTA_NCS (1<<20) -#define MISTA_TXABT (1<<21) -#define MISTA_LC (1<<22) -#define MISTA_TDU (1<<23) -#define MISTA_TxBErr (1<<24) - -//MAC General Status Register -#define MGSTA_CFR 1 -#define MGSTA_RXHA (1<<1) -#define MGSTA_RFFull (1<<2) ////RxFIFO is full lsshi 2005-4-22 12:09 -#define MGSTA_DEF (1<<4) -#define MGSTA_PAU (1<<5) -#define MGSTA_SQE (1<<6) -#define MGSTA_TXHA (1<<7) - - -#define n745_WriteReg(reg,val,which) (*((volatile unsigned int *)(MAC_BASE+(which)*0x800+reg))=(val)) -#define n745_ReadReg(reg,which) (*((volatile unsigned int *)(MAC_BASE+reg+(which)*0x800))) - -#define n745_WriteCam0(which,x,lsw,msw) \ - n745_WriteReg(CAM0L+(x)*CAM_ENTRY_SIZE,lsw,which);\ - n745_WriteReg(CAM0M+(x)*CAM_ENTRY_SIZE,msw,which);\ - - -#define MDCCR1 0x00a00000 // MDC clock rating - -#endif +/**************************************************************************** + * * + * Copyright (c) 2005 - 2007 Winbond Electronics Corp. All rights reserved. * + * * + ****************************************************************************/ + +/**************************************************************************** + * + * FILENAME + * w90n745_mac.h + * + * VERSION + * 1.0 + * + * DESCRIPTION + * The head file for MAC driver on POS-TAX Board + * + * DATA STRUCTURES + * None + * + * FUNCTIONS + * None + * + * HISTORY + * 2005/08/01 Ver 1.0 + * + * AUTHOR + * PC34 Lsshi + * + * REMARK + * None + *************************************************************************/ +#ifndef _W90N745_MAC_H_ +#define _W90N745_MAC_H_ + +#define NON_CACHE_FLAG 0x80000000 + +#define MAC_OFFSET 0x0 +#define MAC_0_OFFSET MAC_OFFSET + +// Advanced Interrupt Controller Registers +#define AIC_SCR_EMCTX0 (VPint(AIC_SCR17)) +#define AIC_SCR_EMCRX0 (VPint(AIC_SCR18)) + +//CAM Registers +#define CAMCMR (MAC_OFFSET) //CAM Command Regiser +#define CAMEN (MAC_OFFSET+0x4)//CAM ennable regiser +#define CAM0M (MAC_OFFSET+0x8)//CAM1 Most significant Word register +#define CAM0L (MAC_OFFSET+0xc)//CAM1 Least Significant Word Register +#define CAM_ENTRY_SIZE 0x8 //CAM entry size +#define CAM_ENTRIES 0x16 //CAM entries + +//MAC Regiseters +#define MIEN (MAC_OFFSET+0xac) //MAC Interrupt Enable Register +#define MCMDR (MAC_OFFSET+0x90) //MAC Command Regiser +#define MIID (MAC_OFFSET+0x94) //MII Management Data Register +#define MIIDA (MAC_OFFSET+0x98) //MII Management Data Control and Address Register +#define MPCNT (MAC_OFFSET+0xb8) //Missed Packet Counter Register + +//DMA Registers +#define TXDLSA (MAC_OFFSET+0x88) //Transmit Descriptor Link List Start Address Regiser +#define RXDLSA (MAC_OFFSET+0x8c) //Receive Descriptor LInk List Start Addresss Register +#define DMARFC (MAC_OFFSET+0xa8) //DMA Receive Frame Control Register +#define TSDR (MAC_OFFSET+0xa0) //Transmit Start Demand Register +#define RSDR (MAC_OFFSET+0xa4) //Recevie Start Demand Register +#define FIFOTHD (MAC_OFFSET+0x9c) //FIFO Threshold Adjustment Register + +//EMC Status Register +#define MISTA (MAC_OFFSET+0xb0) //MAC Interrupter Status Register +#define MGSTA (MAC_OFFSET+0xb4) //MAC General Status Register +#define MRPC (MAC_OFFSET+0xbc) //MAC Receive Pauese counter register +#define MRPCC (MAC_OFFSET+0xc0) //MAC Receive Pauese Current Count Regiser +#define MREPC (MAC_OFFSET+0xc4) //MAC Remote pause count retister + +//DMA Registers +#define DMARFS (MAC_OFFSET+0xc8) //DMA Receive Frame Status Register +#define CTXDSA (MAC_OFFSET+0xcc) //Current Transmit Descriptor Start Addresss Register +#define CTXBSA (MAC_OFFSET+0xd0) //Current Transmit Buffer Start Address Regiser +#define CRXDSA (MAC_OFFSET+0xd4) //Current Receive Descriptor start Address regiser +#define CRXBSA (MAC_OFFSET+0xd8) //Current Receive Buffer Start Address Regiser + +//Debug Mode Receive Finite State Machine Registers +#define RXFSM (MAC_OFFSET+0x200) +#define TXFSM (MAC_OFFSET+0x204) +#define FSM0 (MAC_OFFSET+0x208) +#define FSM1 (MAC_OFFSET+0x20c) + +//Descriptor +typedef struct +{ + volatile unsigned long SL; + volatile unsigned long buffer; + volatile unsigned long reserved; + volatile unsigned long next; +}RXBD; + + +typedef struct +{ + volatile unsigned long mode; + volatile unsigned long buffer; + volatile unsigned long SL; + volatile unsigned long next; +}TXBD; + + +// CAM Command Register(CAMCMR) +#define CAM_AUP 0x0001 // Accept Packets with Unicast Address +#define CAM_AMP 0x0002 // Accept Packets with Multicast Address +#define CAM_ABP 0x0004 // Accept Packets with Broadcast Address +#define CAM_CCAM 0x0008 // 0: Accept Packets CAM Recognizes and Reject Others + // 1: Reject Packets CAM Recognizes and Accept Others +#define CAM_ECMP 0x0010 // Enable CAM Compare +//ownership bit +#define RX_OWNERSHIP_CPU (0x0<<30) +#define RX_OWNERSHIP_DMA (2<<30) + +#define TX_OWNERSHIP_CPU (0x0<<30) +#define TX_OWNERSHIP_DMA (2<<30) + +// RX Frame Descriptor's Owner bit +#define RXfOwnership_DMA 0x80000000 // 10 = DMA +#define RXfOwnership_CPU 0x3fffffff // 00 = CPU + +// TX Frame Descriptor's Owner bit +#define TXfOwnership_DMA 0x80000000 // 1 = DMA +#define TXfOwnership_CPU 0x7fffffff // 0 = CPU + +// Tx Frame Descriptor's Control bits +#define MACTxIntEn 0x04 +#define CRCMode 0x02 +#define NoCRCMode 0x00 +#define PaddingMode 0x01 +#define NoPaddingMode 0x00 + +//received descriptor status +#define RXDS_RXINTR (1<<16) //set if reception of packet caused an interrupt condition +#define RXDS_CRCE (1<<17) // set if crc error +#define RXDS_PTLE (1<<19) //set if received frame longer than 1518 bytes +#define RXDS_RXGD (1<<20) // receiving good packet +#define RXDS_ALIE (1<<21) //Alignment Error +#define RXDS_RP (1<<22) //runt packet +#define RXDS_Inverse (1<<26) //current hit entry is setting on inverse mode +#define RXDS_PortHit (1<<27) //port hit +#define RXDS_IPHit (1<<28) //ip hit +#define RXDS_Hit (1<<29) //hit + +//Tx ownership bit +#define TX_OWNERSHIP_CPU (0x0<<31) +#define TX_OWNERSHIP_DMA (0x1<<31) +//tx mode +#define TX_MODE_PAD 0x1 //pad +#define TX_MODE_CRC (0x1<<1) //crc mode +#define TX_MODE_IE (0x1<<2) //interrupt enable + +//Tx status +#define TXDS_TXINTR (1<<16) //Interruput on Transmit +#define TXDS_DEF (1<<17) //Transmit defered +#define TXDS_TXCP (1<<19) //Transmit Completion +#define TXDS_EXDEF (1<<20) //exceed deferal +#define TXDS_NCS (1<<21) //No Carrier Sense Error +#define TXDS_TXABT (1<<22) //transimtting aborted +#define TXDS_LC (1<<23) //late collision +#define TXDS_TXHA (1<<24) //transmitting halted +#define TXDS_PAU (1<<25) //Paused +#define TXDS_SQE (1<<26) //SQE error +#define TXDS_CCNT (0xf<<27) //transmit collision count +//cam command regiser +#define CAMCMR_AUP 0x1 //Accept unicast packet +#define CAMCMR_AMP (0x1<<1) //Accpet multicast packet +#define CAMCMR_ABP (0x1<<2) //Accept broadcast packet +#define CAMCMR_CCAM (0x1<<3) //complement CAM +#define CAMCMR_ECMP (0x1<<4) //Enable CAM compare + + +// MAC MII Management Data Control and Address Register(MIIDA) +#define MDCCR 0x00300000 // MDC clock rating +#define PHYAD 0x00000100 // PHY Address +#define PHYWR 0x00010000 // Write Operation +#define PHYBUSY 0x00020000 // Busy Bit +#define PHYPreSP 0x00040000 // Preamble Suppress + +// PHY(DM9161) Register Description +#define PHY_CNTL_REG 0x00 +#define PHY_STATUS_REG 0x01 +#define PHY_ID1_REG 0x02 +#define PHY_ID2_REG 0x03 +#define PHY_ANA_REG 0x04 +#define PHY_ANLPA_REG 0x05 +#define PHY_ANE_REG 0x06 + +#define PHY_DSC_REG 0x10 +#define PHY_DSCS_REG 0x11 +#define PHY_10BTCS_REG 0x12 +#define PHY_SINT_REG 0x15 +#define PHY_SREC_REG 0x16 +#define PHY_DISC_REG 0x17 + +//PHY Control Register +#define RESET_PHY (1 << 15) +#define ENABLE_LOOPBACK (1 << 14) +#define DR_100MB (1 << 13) +#define ENABLE_AN (1 << 12) +#define PHY_MAC_ISOLATE (1 << 10) +#define RESTART_AN (1 << 9) +#define PHY_FULLDUPLEX (1 << 8) +#define PHY_COL_TEST (1 << 7) + + +// MAC Interrupt Enable Register(MIEN) +#define EnRXINTR 0x00000001 // Enable Interrupt on Receive Interrupt +#define EnCRCE 0x00000002 // Enable CRC Error Interrupt +#define EnRXOV 0x00000004 // Enable Receive FIFO Overflow Interrupt +#define EnPTLE 0x00000008 // Enable Packet Too Long Interrupt +#define EnRXGD 0x00000010 // Enable Receive Good Interrupt +#define EnALIE 0x00000020 // Enable Alignment Error Interrupt +#define EnRP 0x00000040 // Enable Runt Packet on Receive Interrupt +#define EnMMP 0x00000080 // Enable More Missed Packets Interrupt +#define EnDFO 0x00000100 // Enable DMA receive frame over maximum size Interrupt +#define EnDEN 0x00000200 // Enable DMA early notification Interrupt +#define EnRDU 0x00000400 // Enable Receive Descriptor Unavailable Interrupt +#define EnRxBErr 0x00000800 // Enable Receive Bus ERROR interrupt +#define EnCFR 0x00004000 // Enable Control Frame Receive Interrupt +#define EnTXINTR 0x00010000 // Enable Interrupt on Transmit Interrupt +#define EnTXEMP 0x00020000 // Enable Transmit FIFO Empty Interrupt +#define EnTXCP 0x00040000 // Enable Transmit Completion Interrupt +#define EnEXDEF 0x00080000 // Enable Defer Interrupt +#define EnNCS 0x00100000 // Enable No Carrier Sense Interrupt +#define EnTXABT 0x00200000 // Enable Transmit Abort Interrupt +#define EnLC 0x00400000 // Enable Late Collision Interrupt +#define EnTDU 0x00800000 // Enable Transmit Descriptor Unavailable Interrupt +#define EnTxBErr 0x01000000 // Enable Transmit Bus ERROR Interrupt + +// PHY Status Register +#define AN_COMPLETE (1 << 5) + +// PHY Auto-negotiation Advertisement Register + +#define MODE_DR100_FULL 3 +#define MODE_DR100_HALF 2 +#define MODE_DR10_FULL 1 +#define MODE_DR10_HALF 0 + + +#define DR100_TX_FULL (1 << 8) +#define DR100_TX_HALF (1 << 7) +#define DR10_TX_FULL (1 << 6) +#define DR10_TX_HALF (1 << 5) +#define IEEE_802_3_CSMA_CD 1 + + + +//MAC Interrupt Enable Register +#define MIEN_EnRXINTR 1 +#define MIEN_EnCRCE (1<<1) +#define MIEN_EnRXOV (1<<2) +#define MIEN_EnPTLE (1<<3) +#define MIEN_EnRXGD (1<<4) +#define MIEN_EnALIE (1<<5) +#define MIEN_EnRP (1<<6) +#define MIEN_EnMMP (1<<7) +#define MIEN_EnDFO (1<<8) +#define MIEN_EnDEN (1<<9) +#define MIEN_EnRDU (1<<10) +#define MIEN_EnRXBErr (1<<11) +#define MIEN_EnCFR (1<<14) +#define MIEN_EnTXINTR (1<<16) +#define MIEN_EnTXEMP (1<<17) +#define MIEN_EnTXCP (1<<18) +#define MIEN_EnEXDEF (1<<19) +#define MIEN_EnNCS (1<<20) +#define MIEN_EnTXABT (1<<21) +#define MIEN_EnLC (1<<22) +#define MIEN_EnTDU (1<<23) +#define MIEN_EnTxBErr (1<<24) +//MAC Command Regiser +#define MCMDR_RXON 1 +#define MCMDR_ALP (1<<1) +#define MCMDR_ARP (1<<2) +#define MCMDR_ACP (1<<3) +#define MCMDR_AEP (1<<4) +#define MCMDR_SPCRC (1<<5) +#define MCMDR_TXON (1<<8) +#define MCMDR_NDEF (1<<9) +#define MCMDR_SDPZ (1<<16) +#define MCMDR_EnSQE (1<<17) +#define MCMDR_FDUP (1<<18) +#define MCMDR_EnMDC (1<<19) +#define MCMDR_OPMOD (1<<20) +#define MCMDR_LBK (1<<21) +//#define MCMDR_EnMII (1<<22) +//#define MCMDR_LAN (1<<23) +#define SWR (1<<24)//lsshi add 2005-4-22 12:07 + + +//MAC MII Management Data Control and Address Register +#define MIIDA_PHYRAD 1 +#define MIIDA_PHYAD (1<<8) +#define MIIDA_WR (1<<16) +#define MIIDA_BUSY (1<<17) +#define MIIDA_PreSP (1<<18) +#define MIIDA_MDCON (1<<19) +#define MIIDA_MDCCR (1<<20) + +//FIFO Threshold Adjustment Register +#define FIFOTHD_RxTHD 1 +#define FIFOTHD_TxTHD (1<<8) +#define FIFOTHD_SWR (1<<16) +#define FIFOTHD_Blength (1<<20) +//MAC Interrupt Status Register +#define MISTA_RXINTR 1 +#define MISTA_CRCE (1<<1) +#define MISTA_RXOV (1<<2) +#define MISTA_PTLE (1<<3) +#define MISTA_RXGD (1<<4) +#define MISTA_ALIE (1<<5) +#define MISTA_RP (1<<6) +#define MISTA_MMP (1<<7) +#define MISTA_DFOI (1<<8) +#define MISTA_DENI (1<<9) +#define MISTA_RDU (1<<10) +#define MISTA_RxBErr (1<<11) +#define MISTA_CFR (1<<14) +#define MISTA_TXINTR (1<<16) +#define MISTA_TXEMP (1<<17) +#define MISTA_TXCP (1<<18) +#define MISTA_EXDEF (1<<19) +#define MISTA_NCS (1<<20) +#define MISTA_TXABT (1<<21) +#define MISTA_LC (1<<22) +#define MISTA_TDU (1<<23) +#define MISTA_TxBErr (1<<24) + +//MAC General Status Register +#define MGSTA_CFR 1 +#define MGSTA_RXHA (1<<1) +#define MGSTA_RFFull (1<<2) ////RxFIFO is full lsshi 2005-4-22 12:09 +#define MGSTA_DEF (1<<4) +#define MGSTA_PAU (1<<5) +#define MGSTA_SQE (1<<6) +#define MGSTA_TXHA (1<<7) + + +#define n745_WriteReg(reg,val,which) (*((volatile unsigned int *)(MAC_BASE+(which)*0x800+reg))=(val)) +#define n745_ReadReg(reg,which) (*((volatile unsigned int *)(MAC_BASE+reg+(which)*0x800))) + +#define n745_WriteCam0(which,x,lsw,msw) \ + n745_WriteReg(CAM0L+(x)*CAM_ENTRY_SIZE,lsw,which);\ + n745_WriteReg(CAM0M+(x)*CAM_ENTRY_SIZE,msw,which);\ + + +#define MDCCR1 0x00a00000 // MDC clock rating + +#endif diff --git a/uClinux-2.4.20-uc1/drivers/net/wireless/base.c b/uClinux-2.4.20-uc1/drivers/net/wireless/base.c index 4d0f17a..61016ac 100755 --- a/uClinux-2.4.20-uc1/drivers/net/wireless/base.c +++ b/uClinux-2.4.20-uc1/drivers/net/wireless/base.c @@ -1,1783 +1,1783 @@ -/*------------------------------------------------------------------------------*/ -/* Wireless driver base functions for winbond W90N745 */ -/* version 1.0.2(used only for Station) */ -/*------------------------------------------------------------------------------*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "W90N745Prism.h" -#include "Queue.h" - -#if 0 -#define PRISM_SSIDLEN_DEFAULT ((UINT16)0x0008) -char PRISM_DesireSSID_DEFAULT[] = {(char)'P', (char)'C', (char)'3',(char)'0',(char)'W', - (char)'L', (char)'A', (char)'N'}; -#else -#define PRISM_SSIDLEN_DEFAULT ((UINT16)0x000a) -char PRISM_DesireSSID_DEFAULT[] __attribute__ ((aligned (2))) - = {(char)'P', (char)'C', (char)'3', (char)'2',(char)'W', - (char)'e', (char)'b', (char)'C', (char)'a',(char)'m'}; -#endif// declararion desired SSID - -// Access Point's MAC address -char PRISM_BSSID[] = {(char)0x00,(char)0x05,(char)0x5D,(char)0xEB,(char)0x94,(char)0x24}; - -// 802.11 frame header type RFC1042 -char PRISM_LLC[] = {(char)0xaa,(char)0xaa,(char)0x03,(char)0x00,(char)0x00,(char)0x00}; - -#if 1 - //unsigned char Mac_address[6] = {0x00, 0x60, 0xB3, 0x73, 0x26, 0x3d}; - unsigned char Mac_address[6] = {0x00, 0x60, 0xB3, 0x73, 0x26, 0x3C}; -#else - unsigned char Mac_address[6] = {0x00, 0x60, 0xB3, 0x73, 0x26, 0x3E}; -#endif -/* Debug for now */ -UINT8 *DebugpBuffer = NULL; - -Queue_txfid TxQueueObj; - -/* The frequency of each channel in MHz */ -const long channel_frequency[] = { - 2412, 2417, 2422, 2427, 2432, 2437, 2442, - 2447, 2452, 2457, 2462, 2467, 2472, 2484 -}; - -#define NUM_CHANNELS ( sizeof(channel_frequency) / sizeof(channel_frequency[0]) ) - -/* This tables gives the actual meanings of the bitrate IDs returned by the firmware. */ -struct { - int bitrate; /* in 100s of kilbits */ - u16 prism_txratectrl; -} bitrate_table[] = { - {110, 15}, /* Entry 0 is the default */ - {10, 1}, - {20, 2}, - {20, 3}, - {55, 4}, - {55, 7}, - {110, 8}, -}; -#define BITRATE_TABLE_SIZE (sizeof(bitrate_table) / sizeof(bitrate_table[0])) -//#define PRSIM_DEBUG -int nums = 5; - -/*------------------------------Prism Base Functions ----------------------------------*/ -/* */ -int prism_cmd_access(UINT16 write, UINT16 rid) -{ - int result = 0; - UINT16 cmd; - - cmd = PRISM_CMD_CMDCODE_SET(PRISM_CMDCODE_ACCESS)|PRISM_CMD_WRITE_SET(write); - result = prism_docmd_wait(cmd, rid, 0, 0); - return result; -} - -/* prism transmit a buffer command, fid-->buffer */ -int prism_cmd_transmit(UINT16 reclaim, UINT16 fid) -{ - int result = 0; - UINT16 cmd; - - cmd = PRISM_CMD_CMDCODE_SET(PRISM_CMDCODE_TX)|PRISM_CMD_RECL_SET(reclaim); - result = prism_docmd_wait(cmd, fid, 0, 0); - return result; -} - -int prism_cmd_inquiry(UINT16 infoType) -{ - int result = 0; - UINT16 cmd; - - cmd = PRISM_CMD_CMDCODE_SET(PRISM_CMDCODE_INQ); - result = prism_docmd_nowait(cmd, infoType, 0, 0); - - return result; -} - -/* after init, the net device should be enabled */ -int prism_cmd_enable(UINT16 macport) -{ - int result = 0; - UINT16 cmd; - - cmd = PRISM_CMD_CMDCODE_SET(PRISM_CMDCODE_ENABLE)|PRISM_CMD_MACPORT_SET(macport); - result = prism_docmd_wait(cmd, 0,0,0); - return result; -} - -/* the net device disable function */ -int prism_cmd_disable(UINT16 macport) -{ - int result = 0; - UINT16 cmd; - - cmd = PRISM_CMD_CMDCODE_SET(PRISM_CMDCODE_DISABLE)| PRISM_CMD_MACPORT_SET(macport); - result = prism_docmd_wait(cmd, 0,0,0); - return result; -} - -/* when status register need us to diagnose, do it */ -int prism_cmd_diagnose() -{ - int result = 0; - UINT16 cmd; - - cmd = PRISM_CMD_CMDCODE_SET(PRISM_CMDCODE_DIAG); - result = prism_docmd_wait(cmd, DIAG_PATTERNA, DIAG_PATTERNB, 0); - return result; -} - -/* copy data to buffer access path */ -/* Note: only accept the buf which address is align 2 in our arm7 system */ -int prism_copy_to_bap(UINT16 bap, UINT16 id, UINT16 offset, void *buf, UINT32 len) -{ - int result = 0; - UINT8 *d = (UINT8*)buf; - UINT16 *dw = buf; - UINT32 selectreg; - UINT32 offsetreg; - UINT32 datareg; - UINT32 i; - volatile UINT16 reg; - UINT16 savereg; - int k = 0; - - selectreg = bap ? PRISM_SELECT1 : PRISM_SELECT0; - offsetreg = bap ? PRISM_OFFSET1 : PRISM_OFFSET0; - datareg = bap ? PRISM_DATA1 : PRISM_DATA0; - - - k = BAP_BUSY_TIMEOUT; - /* Write id to select reg */ - reg = READREG(offsetreg); - while(PRISM_OFFSET_ISBUSY(reg) && k) { - k--; - udelay(5); - reg = READREG(offsetreg); - } - - if(!k) { - result = -1; - LOGPRINT; - goto failed; - } - if (PRISM_OFFSET_ISERR(reg)) { - result = -1; - LOGPRINT; - return result; - } - - WRITEREG(selectreg, id); - - k = BAP_BUSY_TIMEOUT; - /* Write offset to offset reg */ - reg = READREG(offsetreg); - while (PRISM_OFFSET_ISBUSY(reg) && k) { - k--; - udelay(5); - reg = READREG(offsetreg); - } - if(!k) { - result = -1; - LOGPRINT; - goto failed; - } - if (PRISM_OFFSET_ISERR(reg)) { - result = -1; - LOGPRINT; - return result; - } - - WRITEREG(offsetreg, offset); - - k = BAP_BUSY_TIMEOUT; - /* Wait for offset[busy] to clear */ - reg = READREG(offsetreg); - while (PRISM_OFFSET_ISBUSY(reg) && k) { - k--; - udelay(5); - reg = READREG(offsetreg); - } - if (PRISM_OFFSET_ISERR(reg)) { - result = -1; - LOGPRINT; - return result; - } - /* Write even(len) buf contents to data reg */ - for ( i = 0; i < (len>>1); i++ ) { - WRITEREG(datareg, *dw++); - } - - /* If len odd, handle last byte */ - if ( len % 2 ) - { - savereg = READREG(datareg); - WRITEREG(offsetreg, (offset+(len&0xfffe))); - - /* Wait for offset[busy] to clear (see BAP_TIMEOUT) */ - k = BAP_BUSY_TIMEOUT; - reg = READREG(offsetreg); - while (PRISM_OFFSET_ISBUSY(reg) && k) { - k--; - udelay(5); - reg = READREG(offsetreg); - } - if(!k) { - result = -1; - LOGPRINT; - goto failed; - } - ((UINT8*)(&savereg))[0] = d[len-1]; - WRITEREG(datareg, savereg); - } -failed: - if (result) - printk("copy_to_bap failed\r\n"); - return result; -} - - -/* Set configuration / information record */ -int Write_RID_Config(UINT16 rid, void *buf, UINT16 len) -{ - int result = 0; - prism_rec_t rec; - - rec.rid = rid; - rec.reclen = (len/2)?((len+1)/2+1):((len/2) + 1); - - /* write the record header */ - result = prism_copy_to_bap(USER_BAP, rid, 0, &rec, 4); - if ( result ) - printk("Failure writing record header\n"); - - /* write the record data (if there is any) */ - if ( len > 0 ) - { - result = prism_copy_to_bap(USER_BAP, rid, 4, buf, len); - if ( result ) - printk("Failure writing record data\r\n"); - } - result = prism_cmd_access(1, rid); - return result; -} - -/* get configuration / information record */ -int Read_RID_Config(UINT16 rid, void *buf) -{ - int result = 0; - prism_rec_t rec; - short len; - - result = prism_cmd_access(0, rid); - - /* read the record header */ - result = prism_copy_from_bap(IRQ_BAP, rid, 0, &rec, 4); - if ( result ) { - result = -1; - printk("Failure writing record header\r\n"); - goto fail; - } - - len = (rec.reclen-1)*2; -#ifdef WDEBUG - printk("len:%d, rec.len: %d\n", len, rec.reclen); -#endif - - /* read the record data (if there is any) */ - if(len > 0); - { - result = prism_copy_from_bap(IRQ_BAP, rid, 4, buf, len); - if ( result ) { - result = -1; - printk("Failure writing record data\r\n"); - goto fail; - } - } - result = rec.reclen; -fail: - return result; -} - -/* get Communication Tallies record's type and length*/ -int Read_CT_InfoType(UINT16 Infofid, UINT16 *len) -{ - int result = 0; - prism_rec_t rec; - - result = prism_copy_from_bap(IRQ_BAP, Infofid, 0, &rec, 4); - if ( result ) { - result = -1; - printk("Failure writing record header\r\n"); - goto fail; - } - - *len = (rec.reclen-1)*2; - result = rec.rid; -fail: - return result; -} - -/* get Commnication Tallies record's data */ -int Read_CT_InfoData(UINT16 Infofid, void *buf, int len) -{ - - int result = 0; - - /* read the record data (if there is any) */ - if(len > 0); - { - result = prism_copy_from_bap(USER_BAP, Infofid, 4, buf, len);//??user_bap - if ( result ) { - result = -1; - printk("Failure writing record data\r\n"); - goto fail; - } - } - result = len; -fail: - - return result; -} - - -/*------------------------------------------------------------------*/ -/* send a command to device and wait for completion */ -int prism_docmd_wait(UINT16 cmd, UINT16 parm0, UINT16 parm1, UINT16 parm2) -{ - volatile UINT16 reg; - volatile UINT16 result; - volatile UINT16 counter, i; - - volatile UINT16 prismStatus; - volatile UINT16 prismResp0; - volatile UINT16 prismResp1; - volatile UINT16 prismResp2; - - i = CMD_BUSY_TIMEOUT; - /* wait for the busy bit to clear */ - reg = READREG(PRISM_CMD); - while (PRISM_CMD_ISBUSY(reg) && i) { - i--; - udelay(5); - reg = READREG(PRISM_CMD); - } - - if (!PRISM_CMD_ISBUSY(reg)) - { - /* busy bit clear, write command */ - WRITEREG(PRISM_PARAM0, parm0); - WRITEREG(PRISM_PARAM1, parm1); - WRITEREG(PRISM_PARAM2, parm2); - WRITEREG(PRISM_CMD, cmd); - - /* Now wait for completion */ - counter = 0; - reg = READREG(PRISM_EVSTAT); - /* if is TX cmd, timout/30 */ - if((cmd&0x1f) == PRISM_CMDCODE_TX) - i = CMD_COMPL_TIMEOUT/30; - else - i = CMD_COMPL_TIMEOUT; - while (!PRISM_EVSTAT_ISCMD(reg) && i) - { - i--; - udelay(10); - reg = READREG(PRISM_EVSTAT); - } - - if (PRISM_EVSTAT_ISCMD(reg)) - { - result = 0; - prismStatus = READREG(PRISM_STATUS); - prismResp0 = READREG(PRISM_RESP0); - prismResp1 = READREG(PRISM_RESP1); - prismResp2 = READREG(PRISM_RESP2); - WRITEREG(PRISM_EVACK, 0x0010); - result = PRISM_STATUS_RESULT_GET(prismStatus); - } - else - { - //printk("timeout:reg[%x]\n", reg); - result = prism_cmd_diagnose(); - //printk("result [%x]\n", result); - } - } - - return result; -} - -/* send a command to device and no wait for completion */ -int prism_docmd_nowait(UINT16 cmd, UINT16 parm0, UINT16 parm1, UINT16 parm2) -{ - volatile UINT16 reg; - volatile UINT16 result; - volatile UINT16 counter, i; - - volatile UINT16 prismStatus; - volatile UINT16 prismResp0; - volatile UINT16 prismResp1; - volatile UINT16 prismResp2; - - i = CMD_BUSY_TIMEOUT; - /* wait for the busy bit to clear */ - reg = READREG(PRISM_CMD); - while (PRISM_CMD_ISBUSY(reg) && i) { - i--; - udelay(5); - reg = READREG(PRISM_CMD); - } - - if (!PRISM_CMD_ISBUSY(reg)) - { - /* busy bit clear, write command */ - WRITEREG(PRISM_PARAM0, parm0); - WRITEREG(PRISM_PARAM1, parm1); - WRITEREG(PRISM_PARAM2, parm2); - WRITEREG(PRISM_CMD, cmd); - - /* Now wait for completion */ - counter = 0; - reg = READREG(PRISM_EVSTAT); - /* if is TX cmd, timout/30 */ - if((cmd&0x1f) == PRISM_CMDCODE_TX) - i = CMD_COMPL_TIMEOUT/30; - else - i = CMD_COMPL_TIMEOUT; - while (!PRISM_EVSTAT_ISCMD(reg) && i) - { - i--; - udelay(10); - reg = READREG(PRISM_EVSTAT); - } - - result = 0; - prismStatus = READREG(PRISM_STATUS); - prismResp0 = READREG(PRISM_RESP0); - prismResp1 = READREG(PRISM_RESP1); - prismResp2 = READREG(PRISM_RESP2); - WRITEREG(PRISM_EVACK, 0x0010); - result = PRISM_STATUS_RESULT_GET(prismStatus); - } - - return result; -} - - -/* prism command allocate mem */ -int prism_cmd_allocate(UINT16 len, unsigned short *txfid) -{ - int result = 0; - UINT16 cmd; - UINT16 reg; - UINT32 i; - - if (len % 2) - result = -1; - else - { - cmd = PRISM_CMD_CMDCODE_SET(PRISM_CMDCODE_ALLOC); - result = prism_docmd_wait(cmd, len, 0, 0); - } - - reg = READREG(PRISM_EVSTAT); - i = ALLOC_COMPL_TIMEOUT; - while (!PRISM_EVSTAT_ISALLOC(reg) && i) - { - i--; - udelay(10); - reg = READREG(PRISM_EVSTAT); - } - - if(!PRISM_EVSTAT_ISALLOC(reg)) { - printk("Alloc event timeout\n"); - return -ETIMEDOUT; - } - - *txfid = READREG(PRISM_ALLOCFID); - WRITEREG(PRISM_EVACK, PRISM_EVACK_ALLOC_SET(1)); - return result; -} - -/* prism command definition, for device initialization */ -int prism_cmd_initialize() -{ - int result = 0; - - result = prism_docmd_wait(PRISM_CMDCODE_INIT,0,0,0); - return result; -} - -/* this function wish the wireless device has been in slot , :P*/ -/* otherwize it will fail :(, map device register to memory, and */ -/* access memory to setup our device */ -int prism_initmac(struct net_device *dev) -{ - prism_cnfDesireSSID_t ssid; - unsigned short reg = 0; - volatile int i; - int result = 0; - struct w740prism_priv *priv = (struct w740prism_priv *)dev->priv; - - /*---------------------------------------------------------------------------*/ - /* should init for w90740 extern I/0 2 as programm interrupt, for tx, rx. */ - /* But our system has inited it :) */ - //*((volatile unsigned int *) 0xFFF83000) = 0x00054554; // config GPIO - //*((volatile unsigned int *) 0xFFF83000) = 0x00054554; // config GPIO -// i = *((volatile unsigned int *) 0xFFF83000); -// *((volatile unsigned int *) 0xFFF83000) = i & 0xffffcfff; // config GPIO - printk("GPIO: %x\n", *((volatile unsigned int *) 0xFFF83000)); - -// *((volatile unsigned int *) 0xFFF83004) = 0x00100000; // GPIO20 -> output -// *((volatile unsigned int *) 0xFFF83008) = 0x00000000; // GPIO20 -> 0 - *((volatile unsigned int *) 0xFFF83004) = 0x00000003; // GPIO0 and GPIO1 -> output - *((volatile unsigned int *) 0xFFF83008) = 0x00000002; // GPIO1 -> 1 - - /* System memory map. map external I/O bank 2 to start address:0x80000000 */ - /* length: 32M :P, is right no collusion */ - *((volatile unsigned int *) EXT2CON_REG) = 0x8007bffe; //ROM2 for Mem access - - // Set external click 0x00003ff8 - *((volatile unsigned int *) 0xFFF0000c) = 0x00003fe8; // PLL OFF, 15MHz - - /*--------------------------------------------------------------------------------*/ -#if 1 - *((volatile unsigned int *) 0xFFF83008) = 0x00000000; // GPIO1 -> 0 - - *((volatile unsigned short *) 0xC00003e0) = 0x80; // set Configuration Option Register - for(i = 0; i < 500000; i++); - if ((reg = *((volatile unsigned short *) 0xC00003e0)) != 0x80) { - printk("wireless driver reset failed, %x\n", reg); - result= -1; - goto out; - } - else - { - printk("wireless memory reset to system map adress: %x, length: %dM\n" , 0xc0000000, 32); - } - - /*be related with little endian,so value 0x4100 ??? */ - *((volatile unsigned short *) 0xC00003e0) = 0x41; //set Configuration Option Register - for(i = 0; i < 30000; i++); - if ((reg = *((volatile unsigned short *) 0xC00003e0)) != 0x41) { - printk("wireless driver map to system map failed, %x\n", reg); - result= -1; - goto out; - } - else - { - printk("wireless memory map to system map adress: %x, length: %dM\n" , 0xc0000000, 32); - } - *((volatile unsigned int *) 0xfff82010) = 0x01; - -#if 0 - WRITEREG(PRISM_SWSUPPORT0, HERMES_MAGIC); - printk("magic value: %x\n", READREG(PRISM_SWSUPPORT0)); - printk("magic value: %x\n", READREG(PRISM_SWSUPPORT0)); - printk("magic value: %x\n", READREG(PRISM_SWSUPPORT0)); -#endif - result = prism_cmd_initialize(); - if (result != 0) { - printk("Initialize command failed\r\n"); - result = -1; - goto out; - } - else - ;//printk("Initialize command sucess\r\n"); - - /* make sure interrupts are disabled and any layabout events cleared */ - WRITEREG(PRISM_INTEN, PRISM_INTEN_DISABLE); - WRITEREG(PRISM_EVACK, PRISM_EVENT_MASK); - - /* init fid queue */ - Init_Queue(); - Queue_dump(); - - /* sets 0xFC84 TxRates */ - priv->bitratemode = DEFAULT_TXRATE_MODE; - prism_hw_setiwrate(priv); - - /* sets Rxsthreshold */ - priv->rts_thresh = DEFAULT_RXSTHRESHOLD; - prism_hw_setrts(priv); - - /* set ap density */ - priv->ap_density = DEFAULT_SENSE; - prism_hw_setapdensity(priv); - - /* set up power */ - priv->pm_on = DEFAULT_POWMANAGE; - priv->pm_mcast = DEFAULT_MULITRECEIVE; - priv->pm_period = DEFAULT_MAXSLEEP; - priv->pm_timeout = DEFAULT_PMHOLDDURATION; - prism_hw_setpower(priv); - /* sets 0xFC2A auth type */ - reg = PRISM_Authentication; - Write_RID_Config(PRISM_RID_CNFAUTHENTICATION, ®, PRISM_RID_CNFAUTHENTICATION_LEN); - - /* sets link type */ - priv->iw_mode = IW_MODE_INFRA; - reg = priv->port_type = PRISM_MacPortType; - Write_RID_Config(PRISM_RID_CNFPORTTYPE, ®, PRISM_RID_CNFPORTTYPE_LEN); - - /* set 0xFC02 desired SSID */ -#if 1 - ssid.ssidLen = PRISM_SSIDLEN_DEFAULT; - memcpy(ssid.ssidName, PRISM_DesireSSID_DEFAULT, ssid.ssidLen); - Write_RID_Config(PRISM_RID_CNFOWNSSID, (UINT8 *)&ssid, PRISM_RID_CNFOWNSSID_LEN); - Write_RID_Config(PRISM_RID_CNFDESIREDSSID, (UINT8 *)&ssid, PRISM_RID_CNFDESIREDSSID_LEN); -#endif - - /* Retrieve the maximum frame size */ - reg = FRAME_DATA_MAXLEN; - Write_RID_Config(PRISM_RID_CNFMAXDATALEN, ®, PRISM_RID_CNFMAXDATALEN_LEN); - - WRITEREG(PRISM_EVSTAT, PRISM_EVENT_MASK); - WRITEREG(PRISM_INTEN, PRISM_INTEN_ENABLEBITS); - - /* enable MAC port 0 */ - prism_cmd_enable(0); - //printk("Enable the Mac port 0,?\n"); - - -#endif - result = Read_RID_Config(PRISM_RID_CNFOWNMACADDR, priv->mac_address); - for(i = 0; i < 6; i++) - printk("%x ", priv->mac_address[i]); - printk("\n"); - result = Read_RID_Config(PRISM_RID_CNFDESIREDSSID, &ssid); - - //printk("*************************************************\n"); - // printk("TX Size: %d\n", sizeof(struct hermes_tx_descriptor)); - memcpy(priv->desired_essid, ssid.ssidName, ssid.ssidLen); - priv->desired_essid[ssid.ssidLen] = '\0'; - - printk("essid: %s, addr: %x\n", priv->desired_essid, priv->desired_essid); - //printk("\n"); -out: - *((volatile unsigned int *) 0xFFF0000c) = 0x00003ff8; // 80MHz - return result; -} - -/* real device reset, called by prism_reset() */ -int prism_reset_device(struct net_device *dev) -{ - prism_cnfDesireSSID_t ssid; - struct w740prism_priv * priv = dev->priv; - u16 reg; - volatile int i; - int k = CMD_BUSY_TIMEOUT; - int ret = 0; - - priv = dev->priv; - *((volatile unsigned int *) 0xFFF0000c) = 0x00003fe8; // PLL OFF, 15MHz -#if 1 - i = *((volatile unsigned int *) 0xFFF83008); - *((volatile unsigned int *) 0xFFF83008) = i | 0x00000002; /* GPIO1 -> 1 */ - for (i=0; i<10; i++); - i = *((volatile unsigned int *) 0xFFF83008); - *((volatile unsigned int *) 0xFFF83008) = i & 0xfffffffd; /* GPIO1 -> 0 */ - //printk("<<>>\n"); - for(i = 0; i < 30000; i++); - *((volatile unsigned int *) 0xfff82124) = 0x10; // add by chp; disable interrupt - - *((volatile unsigned short *) 0xC00003e0) = 0x80; // set Configuration Option Register - - for(i = 0; i < 500000; i++); - if ((reg = *((volatile unsigned short *) 0xC00003e0)) != 0x80) { - printk("wireless driver reset failed, %x\n", reg); - ret = -1; - goto out; - } - else - { - printk("wireless memory reset to system map adress: %x, length: %dM\n" , 0xc0000000, 32); - } - - /*be related with little endian,so value 0x4100 ??? */ - *((volatile unsigned short *) 0xC00003e0) = 0x41; // set Configuration Option Register - for(i = 0; i < 30000; i++); - if ((reg = *((volatile unsigned short *) 0xC00003e0)) != 0x41) { - printk("wireless driver map to system map failed, %x\n", reg); - ret = -1; - goto out; - } - else - { - printk("wireless memory map to system map adress: %x, length: %dM\n" , 0xc0000000, 32); - } - *((volatile unsigned int *) 0xfff82010) = 0x01; -#endif - /* make sure interrupts are disabled and any layabout events cleared */ - WRITEREG(PRISM_INTEN, PRISM_INTEN_DISABLE); - WRITEREG(PRISM_EVACK, PRISM_EVENT_MASK); - - /* First wait for the command register to unbusy */ - reg = READREG(PRISM_CMD); - while ( (PRISM_CMD_ISBUSY(reg)) && k ) { - k--; - udelay(1); - reg = READREG(PRISM_CMD); - } - //printk("hermes_issue_cmd: did %d retries.\n", CMD_BUSY_TIMEOUT-k); - - reg = READREG(PRISM_EVSTAT); - WRITEREG(PRISM_EVACK, reg); - - - ret = prism_cmd_initialize(); - if (ret != 0) { - printk("Initialize command failed\r\n"); - ret = -1; - goto out; - } - else - ;//printk("Initialize command sucess\r\n"); - - Init_Queue(); - Queue_dump(); - - /* sets link type */ - reg = priv->port_type; - DEBUG("port type: %x\n", priv->port_type); - Write_RID_Config(PRISM_RID_CNFPORTTYPE, ®, PRISM_RID_CNFPORTTYPE_LEN); - DEBUG("allow ibss %x\n", priv->allow_ibss); -#if 0 - reg = PRISM_TxRate; - Write_RID_Config(PRISM_RID_TXRATECNTL, ®, PRISM_RID_TXRATECNTL_LEN); -#else - prism_hw_setiwrate(priv); -#endif - - /* set RxSthread */ - prism_hw_setrts(priv); - - - /* set ap density */ - prism_hw_setapdensity(priv); - - /* set power */ - prism_hw_setpower(priv); - - /* set 0xFC02 desired SSID */ - ssid.ssidLen = strlen(priv->desired_essid); - memcpy(ssid.ssidName, priv->desired_essid, ssid.ssidLen); - printk("essid: %s; addr: %x\n", priv->desired_essid, priv->desired_essid); - Write_RID_Config(PRISM_RID_CNFOWNSSID, (UINT8 *)&ssid, PRISM_RID_CNFOWNSSID_LEN); - Write_RID_Config(PRISM_RID_CNFDESIREDSSID, (UINT8 *)&ssid, PRISM_RID_CNFDESIREDSSID_LEN); - - /* Retrieve the maximum frame size */ - reg = FRAME_DATA_MAXLEN; - Write_RID_Config(PRISM_RID_CNFMAXDATALEN, ®, PRISM_RID_CNFMAXDATALEN_LEN); - - /* set the channel */ - reg = priv->channel; - Write_RID_Config(PRISM_RID_CNFOWNCHANNEL, ®, PRISM_RID_CNFOWNCHANNEL_LEN); - - /* Set up encryption */ -#if 1 - ret = prism_hw_setup_wep(priv); - if (ret) { - printk(KERN_ERR "%s: Error %d activating WEP.\n", - dev->name, ret); - goto out; - } -#endif - WRITEREG(PRISM_EVSTAT, PRISM_EVENT_MASK); - WRITEREG(PRISM_INTEN, PRISM_INTEN_ENABLEBITS); - - /* enable MAC port 0 */ - prism_cmd_enable(0); - //printk("Enable the Mac port 0,?\n"); - - *((volatile unsigned int *) 0xfff82120) = 0x10; // add by chp; enable interrupt - -out: - *((volatile unsigned int *) 0xFFF0000c) = 0x00003ff8; //80MHz - return ret; -} - -/*---------------------------------------------------------------- -* prism_txexc -* -* Handles the TxExc event. A Transmit Exception event indicates -* that the MAC's TX process was unsuccessful - so the packet did -* not get transmitted. -* -* Arguments: -* -* Returns: -* nothing -* -* Side effects: -* -* Call context: -* interrupt -----------------------------------------------------------------*/ -void prism_txexc() -{ - UINT16 status; - UINT16 fid; - int result = 0; - - /* Collect the status and display */ - fid = READREG(PRISM_TXCOMPLFID); - result = prism_copy_from_bap(IRQ_BAP, fid, 0, &status, sizeof(status)); - - //printk(" %x: [%x]\n", fid, status); - - if (result) - printk("prism_txexc:copy_from_bap failed\r\n"); -} - -/* copy data from buffer access path */ -/* Note: only accept the buf which address is align 2 */ -int prism_copy_from_bap(UINT16 bap, UINT16 id, UINT16 offset, void *buf, UINT32 len) -{ - int result = 0; - UINT8 *d = (UINT8*)buf; - UINT16 *dw = buf; - UINT32 selectreg; - UINT32 offsetreg; - UINT32 datareg; - UINT32 i; - volatile UINT16 reg = 0; - int k = 0; - - - - selectreg = bap ? PRISM_SELECT1 : PRISM_SELECT0; - offsetreg = bap ? PRISM_OFFSET1 : PRISM_OFFSET0; - datareg = bap ? PRISM_DATA1 : PRISM_DATA0; - - k = BAP_BUSY_TIMEOUT; - /* Write id to select reg */ - reg = READREG(offsetreg); - while (PRISM_OFFSET_ISBUSY(reg) && k) { - k--; - udelay(5); - reg = READREG(offsetreg); - } - if(!k) { - result = -1; - LOGPRINT; - goto failed; - } - WRITEREG(selectreg, id); - - k = BAP_BUSY_TIMEOUT; - /* Write offset to offset reg */ - reg = READREG(offsetreg); - while (PRISM_OFFSET_ISBUSY(reg) && k) - { - k--; - udelay(5); - reg = READREG(offsetreg); - } - if(!k) { - result = -1; - LOGPRINT; - goto failed; - } - WRITEREG(offsetreg, offset); - - k = BAP_BUSY_TIMEOUT; - /* Wait for offset[busy] to clear */ - reg=READREG(offsetreg); - while (PRISM_OFFSET_ISBUSY(reg) &&k ) - { - k--; - udelay(5); - reg=READREG(offsetreg); - } - if (PRISM_OFFSET_ISERR(reg)) { //?? - //result = reg; - LOGPRINT; - result = -1; - return result; - } - /* Read even(len) buf contents from data reg */ - for ( i = 0; i < (len>>1); i++ ) { - *dw++ = READREG(datareg); - } - /* If len odd, handle last byte */ - if ( len % 2 ) - { - reg = READREG(datareg); - d[len-1] = ((UINT8*)(®))[0]; - } - - if (result) { - LOGPRINT; - printk("copy_from_bap failed\r\n"); - } -failed: - return result; - -} - - -static int prism_hw_get_essid(struct w740prism_priv *priv, int *active, - char buf[IW_ESSID_MAX_SIZE+1]) -{ -#if 0 - hermes_t *hw = &priv->hw; - int err = 0; - struct hermes_idstring essidbuf; - char *p = (char *)(&essidbuf.val); - int len; - - - orinoco_lock(priv); - - if (strlen(priv->desired_essid) > 0) { - /* We read the desired SSID from the hardware rather - than from priv->desired_essid, just in case the - firmware is allowed to change it on us. I'm not - sure about this */ - /* My guess is that the OWNSSID should always be whatever - * we set to the card, whereas CURRENT_SSID is the one that - * may change... - Jean II */ - u16 rid; - - *active = 1; - - rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID : - HERMES_RID_CNFDESIREDSSID; - - err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf), - NULL, &essidbuf); - if (err) - goto fail_unlock; - } else { - *active = 0; - - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID, - sizeof(essidbuf), NULL, &essidbuf); - if (err) - goto fail_unlock; - } - - len = le16_to_cpu(essidbuf.len); - - memset(buf, 0, IW_ESSID_MAX_SIZE+1); - memcpy(buf, p, len); - buf[len] = '\0'; - - fail_unlock: - orinoco_unlock(priv); - - return err; -#endif - return 0; -} - -/* Get current connected AP's essid */ -int prism_ioctl_getessid(struct net_device *dev, struct iw_point *erq) -{ - struct w740prism_priv *priv = dev->priv; - char essidbuf[IW_ESSID_MAX_SIZE+1]; - prism_cnfDesireSSID_t our_ssid; - int err = 0; - - err = Read_RID_Config(PRISM_RID_CNFDESIREDSSID, &our_ssid); - DEBUG("essid len: %d\n", our_ssid.ssidLen); - if(our_ssid.ssidLen <= 0) { - erq->flags = 0; - return 0; - } - - erq->flags = 1; - erq->length = our_ssid.ssidLen; - memcpy(essidbuf, our_ssid.ssidName, our_ssid.ssidLen); - if (erq->pointer) - if ( copy_to_user(erq->pointer, essidbuf, erq->length) ) - return -EFAULT; - return 0; -} - -/* it should get net working freq or channel, we only get channel */ -/* if AD-Hoc mode, return OWNCHANNEL register's value */ -/* else if infrastructure mode, return CURRENT regiester's value */ -long prism_hw_get_freq(struct w740prism_priv *priv) -{ - int err = 0; - u16 channel; - long freq = 0; - prism_lock(priv); - DEBUG("Current Mode: %d\n", priv->iw_mode); - if(priv->iw_mode == IW_MODE_INFRA) { - err = Read_RID_Config(PRISM_RID_CURRENTCHANNEL, &channel); - } - else if(priv->iw_mode == IW_MODE_ADHOC) { - err = Read_RID_Config(PRISM_RID_CNFOWNCHANNEL, &channel); - } - else - err = -1; - if(err < 0) - { - printk("%s: read channel erro\n"); - err = -EBUSY; - goto out; - } - - if ( (channel < 1) || (channel > NUM_CHANNELS) ) { - struct net_device *dev = priv->ndev; - - printk("%s: Channel out of range (%d)!\n", dev->name, channel); - err = -EBUSY; - goto out; - - } - freq = channel; - //printk("channel: %d, %d\n", channel, freq); - err = 0; -out: - prism_unlock(priv); - return err ? err : freq; -} - -/* Set essid */ -int prism_ioctl_setessid(struct net_device *dev, struct iw_point *essid) -{ - int err = 0; - prism_lock(dev->priv); - memcpy(((struct w740prism_priv *)(dev->priv))->desired_essid, (unsigned char *)essid->pointer, essid->length); - DEBUG("essid: %s, len: %d\n", ((struct w740prism_priv *)dev->priv)->desired_essid, essid->length); - prism_unlock(dev->priv); - - return err; -} - -/* set freq(it refers to channel here) */ -int prism_ioctl_setfreq(struct net_device *dev, struct iw_freq *freq) -{ - int err = 0; - struct w740prism_priv *priv = dev->priv; - u16 reg; - - //printk("value: %x\n", freq->m); - if( (freq->m < 1) || (freq->m > NUM_CHANNELS)) { - printk("%s: Channel out of range (%d)!\n", dev->name, freq->m); - err = -EFAULT; - goto out; - } - priv->channel = freq->m; -out: - return err; -} - -/* get Wep key */ -int prism_ioctl_getiwencode(struct net_device *dev, struct iw_point *erq) -{ - struct w740prism_priv *priv = dev->priv; - int index = (erq->flags & IW_ENCODE_INDEX) - 1; - u16 xlen = 0; - char keybuf[PRISM_MAX_KEY_SIZE]; - int i, j; - u16 defaultkeyid, wepflags, authentication; - - prism_lock(priv); - if ((index < 0) || (index >= PRISM_MAX_KEYS)) - index = priv->tx_key; - - erq->flags = 0; - if (! priv->wep_on) - erq->flags |= IW_ENCODE_DISABLED; - erq->flags |= index + 1; - - xlen = le16_to_cpu(priv->keys[index].len); - erq->length = xlen; - - if (erq->pointer) { - memcpy(keybuf, priv->keys[index].data, PRISM_MAX_KEY_SIZE); - } - - prism_unlock(priv); - - if (erq->pointer) { - if (copy_to_user(erq->pointer, keybuf, xlen)) - return -EFAULT; - } -// for(i = 0; i < xlen; i++) { -// printk("%x", keybuf[i]); -// } -// printk("\n"); - for(j = 0; j < 4; j++) { - Read_RID_Config(PRISM_RID_CNFDEFAULTKEY0+j, keybuf); -// for(i = 0; i < xlen; i++) { -// printk("%x", keybuf[i]); -// } -// printk("\n"); - } - Read_RID_Config(PRISM_RID_CNFWEPDEFAULTKEYID, &defaultkeyid); - Read_RID_Config(PRISM_RID_CNFWEPFLAGS, &wepflags); - Read_RID_Config(PRISM_RID_CNFAUTHENTICATION, &authentication); -// printk("defaultkeyid: %x, wepflags: %x, authentication: %x\n", defaultkeyid, wepflags, authentication); - return 0; -} - -/* set Wep key */ -int prism_ioctl_setiwencode(struct net_device *dev, struct iw_point *erq) -{ - int i; - struct w740prism_priv *priv = dev->priv; - char buf[IW_ENCODING_TOKEN_MAX+1]; - int index = (erq->flags & IW_ENCODE_INDEX) - 1; - int setindex = priv->tx_key; - int enable = priv->wep_on; - int restricted = priv->wep_restrict; - int xlen = 0; - int err = 0; -//printk("index: %d, len: %d, nowlen: %d\n", index, erq->length, priv->keys[index].len); - if (erq->length > IW_ENCODING_TOKEN_MAX) - { - printk("Too long key\n"); - return -EFAULT; - } - - if (erq->pointer) { - if(copy_from_user(buf, erq->pointer, erq->length)) - return -EFAULT; - } - prism_lock(priv); - if (erq->pointer) { - if (erq->length > PRISM_MAX_KEY_SIZE) { - printk("Too long key string\n"); - err = -E2BIG; - goto out; - } - -// if ( (erq->length > LARGE_KEY_SIZE) -// || ( ! priv->has_big_wep && (erq->length > SMALL_KEY_SIZE)) ) { -// err = -EINVAL; -// goto out; -// } - - if ((index < 0) || (index >= PRISM_MAX_KEYS)) - index = priv->tx_key; - - if (erq->length > SMALL_KEY_SIZE) { - LOGPRINT; - xlen = LARGE_KEY_SIZE; - } else if (erq->length > 0) { - LOGPRINT; - xlen = SMALL_KEY_SIZE; - } else - xlen = 0; - - /* Switch on WEP if off */ - if ((!enable) && (xlen > 0)) { - setindex = index; - enable = 1; - } - } else { - /* Important note : if the user do "iwconfig eth0 enc off", - * we will arrive there with an index of -1. This is valid - * but need to be taken care off... Jean II */ - if ((index < 0) || (index >= PRISM_MAX_KEYS)) { - if((index != -1) || (erq->flags == 0)) { - err = -EINVAL; - goto out; - } - } else { - /* Set the index : Check that the key is valid */ - if(priv->keys[index].len == 0) { - err = -EINVAL; - goto out; - } - setindex = index; - } - } - - if (erq->flags & IW_ENCODE_DISABLED) - enable = 0; - /* Only for Prism2 & Symbol cards (so far) - Jean II */ - if (erq->flags & IW_ENCODE_OPEN) - restricted = 0; - if (erq->flags & IW_ENCODE_RESTRICTED) - restricted = 1; - - if (erq->pointer) { - priv->keys[index].len = cpu_to_le16(xlen); - memset(priv->keys[index].data, 0, sizeof(priv->keys[index].data)); - memcpy(priv->keys[index].data, buf, erq->length); - } - priv->tx_key = setindex; - priv->wep_on = enable; - priv->wep_restrict = restricted; - - out: - buf[erq->length] = '\0'; -// for(i = 0; i < erq->length; i++) -// printk("%x", buf[i]); -// printk("\n"); -// printk("tx_key: %d, wep_on: %d, wep_restrict: %d\n", priv->tx_key, priv->wep_on, priv->wep_restrict); -// printk("tx_key's length: %d\n", priv->keys[priv->tx_key].len); - prism_unlock(priv); - return err; -} - -/* real setup the Wep key to hardware */ -int prism_hw_setup_wep(struct w740prism_priv *priv) -{ - int err = 0; - int keylen; - int i, j; - int auth_flag; - int master_wep_flag = 0; //is off - -// printk("prism_hw_setup_wep\n"); - if (priv->wep_on) { - /* Write all 4 keys */ - keylen = le16_to_cpu(priv->keys[priv->tx_key].len); - for(i = 0; i < PRISM_MAX_KEYS; i++) { -// printk("keylen: %d, reallen: %d\n", keylen, priv->keys[i].len); - if (keylen > LARGE_KEY_SIZE) { - printk("%s: Key %d has oversize length %d.\n", - priv->ndev->name, i, keylen); - return -E2BIG; - } -// printk("%dkey's len: %d\n", i, keylen); -// for( j = 0; j < keylen; j++) -// printk("%x", priv->keys[i].data[j]); -// printk("\n"); - err = Write_RID_Config(PRISM_RID_CNFDEFAULTKEY0 + i, priv->keys[i].data, keylen); - if (err) - return err; - } - - err = Write_RID_Config(PRISM_RID_CNFWEPDEFAULTKEYID, &priv->tx_key, PRISM_RID_CNFWEPDEFAULTKEYID_LEN); - if (err) - return err; - - if (priv->wep_restrict) { - auth_flag = 2; - master_wep_flag = 3; - } else { - auth_flag = 1; - master_wep_flag = 1; /* Intersil */ - } - - err = Write_RID_Config(PRISM_RID_CNFAUTHENTICATION, &auth_flag, PRISM_RID_CNFAUTHENTICATION_LEN); - if (err) - return err; - } - Read_RID_Config(PRISM_RID_CNFAUTHENTICATION, &auth_flag); -// printk("Auth_flag: %x\n", auth_flag); - /* Master WEP setting : on/off */ - err = Write_RID_Config(PRISM_RID_CNFWEPFLAGS, &master_wep_flag, PRISM_RID_CNFWEPFLAGS_LEN); - if (err) - return err; - return 0; -} - -int prism_ioctl_setscan(struct net_device *dev, struct iw_point *erq) -{ - int err = 0; - unsigned short len; - unsigned int i, j, cnt; - struct w740prism_priv *priv = dev->priv; -// printk("erq->length: %d\n", erq->length); - prism_lock(priv); -#if 1 - prism_cmd_inquiry(PRISM_INQ_SCAN); - if(down_interruptible(&priv->sema)) - err = -1; - - - DEBUG("erq addr: %x\n", erq); - prism_ioctl_getaplist(dev, erq); -#endif - prism_unlock(priv); - return err; -} - -int prism_hw_get_bssid(struct net_device *dev, char buf[ETH_ALEN]) -{ - struct w740prism_priv *priv = dev->priv; - int err = 0; - int i = 0; - - err = Read_RID_Config(PRISM_RID_CURRENTBSSID, buf); - -// for(i = 0; i < 6; i++) -// printk("%x.", buf[i]); -// printk("\n"); - return err; -} - -int prism_ioctl_getstat(struct net_device *dev, struct iw_point *erq) -{ - int err = 0; - int status = 0; -// printk("%s: %d\n", __FILE__,__LINE__); - prism_cmd_inquiry(PRISM_INQ_ASSOCIATIONSTATUS); -// printk("%s: %d\n", __FILE__,__LINE__); - return err; -} - - -int prism_ioctl_getlinkstat(struct net_device *dev, struct iw_point *erq) -{ - int err = 0; - int status = 0; - struct w740prism_priv *priv = (struct w740prism_priv *)dev->priv; -// printk("%s: %d\n", __FILE__,__LINE__); - prism_lock(priv); - if (erq->pointer) { - if (copy_to_user(erq->pointer, &(priv->status), erq->length)) - return -EFAULT; - } - prism_unlock(priv); - //prism_cmd_inquiry(PRISM_INQ_LINKSTATUS); -// printk("%s: %d\n", __FILE__,__LINE__); - return err; -} - -int prism_ioctl_getiwrate(struct net_device *dev, struct iw_param *iwp) -{ - int err = 0; - int rate = 0; - int i; - err = Read_RID_Config(PRISM_RID_CURRENTTXRATE, &rate); - - for(i = 0; i < BITRATE_TABLE_SIZE; i++) - { - if (bitrate_table[i].prism_txratectrl == rate) { - break; - } - } - if(i >= BITRATE_TABLE_SIZE) - { - printk("Can't get correct rate\n"); - i = 0; - } - - iwp->value = bitrate_table[i].bitrate * 100000; -// printk("Current rate: %d\n", iwp->value); - iwp->disabled = 0; - return err; -} - -int prism_ioctl_setiwrate(struct net_device *dev, struct iw_param *iwp) -{ - struct w740prism_priv *priv = dev->priv; - int err = 0; - int ratemode = -1; - int bitrate; /* 100s of kilobits */ - int i; -//printk("rate: %d\n", iwp->value); - if (iwp->value == -1) - bitrate = 110; - else { - if (iwp->value % 100000) - return -EINVAL; - bitrate = iwp->value / 100000; - } - - if ( (bitrate != 10) && (bitrate != 20) && - (bitrate != 55) && (bitrate != 110) ) - return -EINVAL; - - for (i = 0; i < BITRATE_TABLE_SIZE; i++) - if ( (bitrate_table[i].bitrate == bitrate)) { - ratemode = i; - break; - } - - if (ratemode == -1) - return -EINVAL; - - prism_lock(priv); - priv->bitratemode = ratemode; - prism_unlock(priv); - - return err; -} - -int prism_hw_setiwrate(struct w740prism_priv *priv) -{ - int err = 0; -// printk("ratemode: %x\n", priv->bitratemode); -// - if (priv->bitratemode >= BITRATE_TABLE_SIZE) { - printk("%s: Invalid bitrate mode %d\n", - "wlan", priv->bitratemode); - return -EINVAL; - } - err = Write_RID_Config(PRISM_RID_TXRATECNTL, &bitrate_table[priv->bitratemode].prism_txratectrl, PRISM_RID_TXRATECNTL_LEN); - return err; -} - -int prism_ioctl_setrts(struct net_device *dev, struct iw_param *iwp) -{ - int err = 0; - struct w740prism_priv *priv = dev->priv; - int val = iwp->value; - - if (iwp->disabled) - val = 2347; - - if ( (val < 0) || (val > 3000) ) - return -EINVAL; - - prism_lock(priv); - priv->rts_thresh = val; - prism_unlock(priv); - - return err; -} - -int prism_hw_setrts(struct w740prism_priv *priv) -{ - int err = 0; - - /* Set RTS threshold */ - err = Write_RID_Config(PRISM_RID_RTSTHRESHOLD, &priv->rts_thresh, PRISM_RID_RTSTHRESHOLD_LEN); - - return err; -} - -int prism_ioctl_getsens(struct net_device *dev, struct iw_param *iwp) -{ - int err = 0; - int val = 0; - - Read_RID_Config(PRISM_RID_CNFSYSTEMSCALE, &val); -// printk("Current sense: %d\n", val); - iwp->value = val; - iwp->fixed = 0; /* auto */ - - return 0; -} - -int prism_ioctl_setsens(struct net_device *dev, struct iw_param *iwp) -{ - int err = 0; - struct w740prism_priv *priv = dev->priv; - int val = iwp->value; - - if ((val < 1) || (val > 3)) - return -EINVAL; - - prism_lock(priv); - priv->ap_density = val; - prism_unlock(priv); - - return err; -} - -int prism_hw_setapdensity(struct w740prism_priv *priv) -{ - int err = 0; - err = Write_RID_Config(PRISM_RID_CNFSYSTEMSCALE, &priv->ap_density, PRISM_RID_CNFSYSTEMSCALE_LEN); - if (err) - return err; - return err; -} - -int prism_ioctl_getpower(struct net_device *dev, struct iw_param *iwp) -{ - int err = 0; - struct w740prism_priv *priv = dev->priv; - u16 enable, period, timeout, mcast; - - prism_lock(priv); - - Read_RID_Config(PRISM_RID_CNFPMENABLED, &enable); - Read_RID_Config(PRISM_RID_CNFMAXSLEEPDURATION, &period); - Read_RID_Config(PRISM_RID_CNFPMHOLDOVERDURATION, &timeout); - Read_RID_Config(PRISM_RID_CNFMULTICASTRECEIVE, &mcast); - - iwp->disabled = !enable; - /* Note : by default, display the period */ - if ((iwp->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { - iwp->flags = IW_POWER_TIMEOUT; - iwp->value = timeout * 1000; - } else { - iwp->flags = IW_POWER_PERIOD; - iwp->value = period * 1000; - } - if (mcast) - iwp->flags |= IW_POWER_ALL_R; - else - iwp->flags |= IW_POWER_UNICAST_R; - - out: - prism_unlock(priv); - return err; -} - -int prism_ioctl_setpower(struct net_device *dev, struct iw_param *iwp) -{ - int err = 0; - struct w740prism_priv *priv = dev->priv; - - prism_lock(priv); - if (iwp->disabled) { - priv->pm_on = 0; - } else { - switch (iwp->flags & IW_POWER_MODE) { - case IW_POWER_UNICAST_R: - priv->pm_mcast = 0; - priv->pm_on = 1; - break; - case IW_POWER_ALL_R: - priv->pm_mcast = 1; - priv->pm_on = 1; - break; - case IW_POWER_ON: - break; - default: - err = -EINVAL; - } - - if (err) - goto out; - - if (iwp->flags & IW_POWER_TIMEOUT) { - priv->pm_on = 1; - priv->pm_timeout = iwp->value / 1000; - } - if (iwp->flags & IW_POWER_PERIOD) { - priv->pm_on = 1; - priv->pm_period = iwp->value / 1000; - } - if(!priv->pm_on) { - err = -EINVAL; - goto out; - } - } -out: - prism_unlock(priv); - return err; -} - - -int prism_hw_setpower(struct w740prism_priv *priv) -{ - int err = 0; - err = Write_RID_Config(PRISM_RID_CNFPMENABLED, &priv->pm_on, PRISM_RID_CNFPMENABLED_LEN); - if (err) - return err; - err = Write_RID_Config(PRISM_RID_CNFMAXSLEEPDURATION, &priv->pm_period, PRISM_RID_CNFMAXSLEEPDURATION_LEN); - if (err) - return err; - err = Write_RID_Config(PRISM_RID_CNFPMHOLDOVERDURATION, &priv->pm_timeout, PRISM_RID_CNFPMHOLDOVERDURATION_LEN); - if (err) - return err; - err = Write_RID_Config(PRISM_RID_CNFMULTICASTRECEIVE, &priv->pm_mcast, PRISM_RID_CNFMULTICASTRECEIVE_LEN); - if (err) - return err; - return err; -} - -int get_scan_result(UINT16 infoid, int lens, struct w740prism_priv *priv) -{ - int result = 0; - int len, j, i, cnt; -#ifdef SCAN_ENABLE - struct prism_ScanResult * scan; - prism_lock(priv); - - len = Read_CT_InfoData(infoid, &priv->scan_res, lens); - scan = &priv->scan_res; -// printk("len=%d\n", len); - len = len/2; - cnt = (len - 2) / 31; - priv->scan_res_len = cnt; -// printk("reason[%d], cnt: %d\n", scan->scanreason, cnt); - for (j=0; jresult[j].chid > 14) { - LOGPRINT; - break; - } -// printk("off: %d, j: %d\n", scan->result+j, j); -// printk("channel[%d]\n", scan->result[j].chid); -// -// printk("bssid ["); -// for (i=0; i<6; i+=2) -// printk(" %02x %02x", scan->result[j].bssid[i+1], scan->result[j].bssid[i]); -// printk("]\n"); -// printk("ssid ["); -// len = scan->result[j].ssid.ssidLen; -// if (len % 2) -// { -// for (i=0; iresult[j].ssid.ssidName[i+1], scan->result[j].ssid.ssidName[i]); -// printk(" %02x", scan->result[j].ssid.ssidName[len]); -// } -// else -// { -// for (i=0; iresult[j].ssid.ssidName[i+1], scan->result[j].ssid.ssidName[i]); -// } -// printk("]\n"); -#endif - } - up(&priv->sema); - prism_unlock(priv); -#endif - return result; -} - -int prism_ioctl_getaplist(struct net_device *dev, struct iw_point * iwp) -{ - int err = 0; - struct w740prism_priv *priv = dev->priv; - int num = 0; - int i, len; -#if 1 - int j; -#endif - prism_ScanResultSub_t *resultp = &(priv->scan_res.result[0]); -DEBUG("iwp: %x, iwp->length: %d\n", iwp, iwp->length); - prism_lock(priv); - - if(iwp->length == 0) - { - iwp->length = priv->scan_res_len; - DEBUG("iwp->length: %d\n", iwp->length); - } -#if 1 - else - { - len = (iwp->length > priv->scan_res_len ? priv->scan_res_len:iwp->length); - for(i = 0; i < len; i++) - { - if (iwp->pointer) - if ( copy_to_user(iwp->pointer + sizeof(prism_cnfDesireSSID_t)*i, - &((resultp+i)->ssid), - sizeof(prism_cnfDesireSSID_t) ) - ) - return -EFAULT; -#if 0 - for(j = 0; j < ((resultp+i)->ssid).ssidLen; j++) - { - printk("%c", ((resultp+i)->ssid).ssidName[j]); - } - printk("\n"); -#endif - } - } -#endif - prism_unlock(priv); - return err; -} - -void set_port_type(struct w740prism_priv *priv) -{ - switch (priv->iw_mode) { - case IW_MODE_INFRA: - priv->port_type = 1; - priv->allow_ibss = 0; - break; - case IW_MODE_ADHOC: - if (priv->prefer_port3) { - priv->port_type = 3; - priv->allow_ibss = 0; - } else { - priv->port_type = 0;//priv->ibss_port; - priv->allow_ibss = 1; - } - break; - default: - printk("%s: Invalid priv->iw_mode\n", - priv->ndev->name); - } -} - -int prism_ioctl_setspy(struct net_device *dev, struct iw_point *iwp) -{ - int result = 0; - struct w740prism_priv *priv = dev->priv; - struct sockaddr address[IW_MAX_SPY]; - int number = iwp->length; - int i; - - if (number > IW_MAX_SPY) - return -E2BIG; - - if (iwp->pointer) { - if (copy_from_user(address, iwp->pointer, - sizeof(struct sockaddr) * number)) - return -EFAULT; - } - - prism_lock(priv); - priv->spy_number = 0; - - if (number > 0) { - for (i = 0; i < number; i++) - memcpy(priv->spy_address[i], address[i].sa_data, - ETH_ALEN); - memset(priv->spy_stat, 0, - sizeof(struct iw_quality) * IW_MAX_SPY); - priv->spy_number = number; - } - - DEBUG("%s: New spy list:\n", dev->name); - for (i = 0; i < number; i++) { - DEBUG("%s: %d - %02x:%02x:%02x:%02x:%02x:%02x\n", - dev->name, i+1, - priv->spy_address[i][0], priv->spy_address[i][1], - priv->spy_address[i][2], priv->spy_address[i][3], - priv->spy_address[i][4], priv->spy_address[i][5]); - } - - prism_unlock(priv); - return result; -} - -int prism_ioctl_getspy(struct net_device *dev, struct iw_point *iwp) -{ - struct w740prism_priv *priv = dev->priv; - struct sockaddr address[IW_MAX_SPY]; - struct iw_quality spy_stat[IW_MAX_SPY]; - int number; - int i; - - prism_lock(priv); - - number = priv->spy_number; - if ((number > 0) && (iwp->pointer)) { - for (i = 0; i < number; i++) { - memcpy(address[i].sa_data, priv->spy_address[i], - ETH_ALEN); - address[i].sa_family = AF_UNIX; - } - /* Copy stats */ - memcpy(&spy_stat, priv->spy_stat, - sizeof(struct iw_quality) * IW_MAX_SPY); - for (i=0; i < number; i++) - priv->spy_stat[i].updated = 0; - } - - prism_unlock(priv); - - iwp->length = number; - if(copy_to_user(iwp->pointer, address, - sizeof(struct sockaddr) * number)) - return -EFAULT; - if(copy_to_user(iwp->pointer + (sizeof(struct sockaddr)*number), - &spy_stat, sizeof(struct iw_quality) * number)) - return -EFAULT; - - return 0; -} +/*------------------------------------------------------------------------------*/ +/* Wireless driver base functions for winbond W90N745 */ +/* version 1.0.2(used only for Station) */ +/*------------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "W90N745Prism.h" +#include "Queue.h" + +#if 0 +#define PRISM_SSIDLEN_DEFAULT ((UINT16)0x0008) +char PRISM_DesireSSID_DEFAULT[] = {(char)'P', (char)'C', (char)'3',(char)'0',(char)'W', + (char)'L', (char)'A', (char)'N'}; +#else +#define PRISM_SSIDLEN_DEFAULT ((UINT16)0x000a) +char PRISM_DesireSSID_DEFAULT[] __attribute__ ((aligned (2))) + = {(char)'P', (char)'C', (char)'3', (char)'2',(char)'W', + (char)'e', (char)'b', (char)'C', (char)'a',(char)'m'}; +#endif// declararion desired SSID + +// Access Point's MAC address +char PRISM_BSSID[] = {(char)0x00,(char)0x05,(char)0x5D,(char)0xEB,(char)0x94,(char)0x24}; + +// 802.11 frame header type RFC1042 +char PRISM_LLC[] = {(char)0xaa,(char)0xaa,(char)0x03,(char)0x00,(char)0x00,(char)0x00}; + +#if 1 + //unsigned char Mac_address[6] = {0x00, 0x60, 0xB3, 0x73, 0x26, 0x3d}; + unsigned char Mac_address[6] = {0x00, 0x60, 0xB3, 0x73, 0x26, 0x3C}; +#else + unsigned char Mac_address[6] = {0x00, 0x60, 0xB3, 0x73, 0x26, 0x3E}; +#endif +/* Debug for now */ +UINT8 *DebugpBuffer = NULL; + +Queue_txfid TxQueueObj; + +/* The frequency of each channel in MHz */ +const long channel_frequency[] = { + 2412, 2417, 2422, 2427, 2432, 2437, 2442, + 2447, 2452, 2457, 2462, 2467, 2472, 2484 +}; + +#define NUM_CHANNELS ( sizeof(channel_frequency) / sizeof(channel_frequency[0]) ) + +/* This tables gives the actual meanings of the bitrate IDs returned by the firmware. */ +struct { + int bitrate; /* in 100s of kilbits */ + u16 prism_txratectrl; +} bitrate_table[] = { + {110, 15}, /* Entry 0 is the default */ + {10, 1}, + {20, 2}, + {20, 3}, + {55, 4}, + {55, 7}, + {110, 8}, +}; +#define BITRATE_TABLE_SIZE (sizeof(bitrate_table) / sizeof(bitrate_table[0])) +//#define PRSIM_DEBUG +int nums = 5; + +/*------------------------------Prism Base Functions ----------------------------------*/ +/* */ +int prism_cmd_access(UINT16 write, UINT16 rid) +{ + int result = 0; + UINT16 cmd; + + cmd = PRISM_CMD_CMDCODE_SET(PRISM_CMDCODE_ACCESS)|PRISM_CMD_WRITE_SET(write); + result = prism_docmd_wait(cmd, rid, 0, 0); + return result; +} + +/* prism transmit a buffer command, fid-->buffer */ +int prism_cmd_transmit(UINT16 reclaim, UINT16 fid) +{ + int result = 0; + UINT16 cmd; + + cmd = PRISM_CMD_CMDCODE_SET(PRISM_CMDCODE_TX)|PRISM_CMD_RECL_SET(reclaim); + result = prism_docmd_wait(cmd, fid, 0, 0); + return result; +} + +int prism_cmd_inquiry(UINT16 infoType) +{ + int result = 0; + UINT16 cmd; + + cmd = PRISM_CMD_CMDCODE_SET(PRISM_CMDCODE_INQ); + result = prism_docmd_nowait(cmd, infoType, 0, 0); + + return result; +} + +/* after init, the net device should be enabled */ +int prism_cmd_enable(UINT16 macport) +{ + int result = 0; + UINT16 cmd; + + cmd = PRISM_CMD_CMDCODE_SET(PRISM_CMDCODE_ENABLE)|PRISM_CMD_MACPORT_SET(macport); + result = prism_docmd_wait(cmd, 0,0,0); + return result; +} + +/* the net device disable function */ +int prism_cmd_disable(UINT16 macport) +{ + int result = 0; + UINT16 cmd; + + cmd = PRISM_CMD_CMDCODE_SET(PRISM_CMDCODE_DISABLE)| PRISM_CMD_MACPORT_SET(macport); + result = prism_docmd_wait(cmd, 0,0,0); + return result; +} + +/* when status register need us to diagnose, do it */ +int prism_cmd_diagnose() +{ + int result = 0; + UINT16 cmd; + + cmd = PRISM_CMD_CMDCODE_SET(PRISM_CMDCODE_DIAG); + result = prism_docmd_wait(cmd, DIAG_PATTERNA, DIAG_PATTERNB, 0); + return result; +} + +/* copy data to buffer access path */ +/* Note: only accept the buf which address is align 2 in our arm7 system */ +int prism_copy_to_bap(UINT16 bap, UINT16 id, UINT16 offset, void *buf, UINT32 len) +{ + int result = 0; + UINT8 *d = (UINT8*)buf; + UINT16 *dw = buf; + UINT32 selectreg; + UINT32 offsetreg; + UINT32 datareg; + UINT32 i; + volatile UINT16 reg; + UINT16 savereg; + int k = 0; + + selectreg = bap ? PRISM_SELECT1 : PRISM_SELECT0; + offsetreg = bap ? PRISM_OFFSET1 : PRISM_OFFSET0; + datareg = bap ? PRISM_DATA1 : PRISM_DATA0; + + + k = BAP_BUSY_TIMEOUT; + /* Write id to select reg */ + reg = READREG(offsetreg); + while(PRISM_OFFSET_ISBUSY(reg) && k) { + k--; + udelay(5); + reg = READREG(offsetreg); + } + + if(!k) { + result = -1; + LOGPRINT; + goto failed; + } + if (PRISM_OFFSET_ISERR(reg)) { + result = -1; + LOGPRINT; + return result; + } + + WRITEREG(selectreg, id); + + k = BAP_BUSY_TIMEOUT; + /* Write offset to offset reg */ + reg = READREG(offsetreg); + while (PRISM_OFFSET_ISBUSY(reg) && k) { + k--; + udelay(5); + reg = READREG(offsetreg); + } + if(!k) { + result = -1; + LOGPRINT; + goto failed; + } + if (PRISM_OFFSET_ISERR(reg)) { + result = -1; + LOGPRINT; + return result; + } + + WRITEREG(offsetreg, offset); + + k = BAP_BUSY_TIMEOUT; + /* Wait for offset[busy] to clear */ + reg = READREG(offsetreg); + while (PRISM_OFFSET_ISBUSY(reg) && k) { + k--; + udelay(5); + reg = READREG(offsetreg); + } + if (PRISM_OFFSET_ISERR(reg)) { + result = -1; + LOGPRINT; + return result; + } + /* Write even(len) buf contents to data reg */ + for ( i = 0; i < (len>>1); i++ ) { + WRITEREG(datareg, *dw++); + } + + /* If len odd, handle last byte */ + if ( len % 2 ) + { + savereg = READREG(datareg); + WRITEREG(offsetreg, (offset+(len&0xfffe))); + + /* Wait for offset[busy] to clear (see BAP_TIMEOUT) */ + k = BAP_BUSY_TIMEOUT; + reg = READREG(offsetreg); + while (PRISM_OFFSET_ISBUSY(reg) && k) { + k--; + udelay(5); + reg = READREG(offsetreg); + } + if(!k) { + result = -1; + LOGPRINT; + goto failed; + } + ((UINT8*)(&savereg))[0] = d[len-1]; + WRITEREG(datareg, savereg); + } +failed: + if (result) + printk("copy_to_bap failed\r\n"); + return result; +} + + +/* Set configuration / information record */ +int Write_RID_Config(UINT16 rid, void *buf, UINT16 len) +{ + int result = 0; + prism_rec_t rec; + + rec.rid = rid; + rec.reclen = (len/2)?((len+1)/2+1):((len/2) + 1); + + /* write the record header */ + result = prism_copy_to_bap(USER_BAP, rid, 0, &rec, 4); + if ( result ) + printk("Failure writing record header\n"); + + /* write the record data (if there is any) */ + if ( len > 0 ) + { + result = prism_copy_to_bap(USER_BAP, rid, 4, buf, len); + if ( result ) + printk("Failure writing record data\r\n"); + } + result = prism_cmd_access(1, rid); + return result; +} + +/* get configuration / information record */ +int Read_RID_Config(UINT16 rid, void *buf) +{ + int result = 0; + prism_rec_t rec; + short len; + + result = prism_cmd_access(0, rid); + + /* read the record header */ + result = prism_copy_from_bap(IRQ_BAP, rid, 0, &rec, 4); + if ( result ) { + result = -1; + printk("Failure writing record header\r\n"); + goto fail; + } + + len = (rec.reclen-1)*2; +#ifdef WDEBUG + printk("len:%d, rec.len: %d\n", len, rec.reclen); +#endif + + /* read the record data (if there is any) */ + if(len > 0); + { + result = prism_copy_from_bap(IRQ_BAP, rid, 4, buf, len); + if ( result ) { + result = -1; + printk("Failure writing record data\r\n"); + goto fail; + } + } + result = rec.reclen; +fail: + return result; +} + +/* get Communication Tallies record's type and length*/ +int Read_CT_InfoType(UINT16 Infofid, UINT16 *len) +{ + int result = 0; + prism_rec_t rec; + + result = prism_copy_from_bap(IRQ_BAP, Infofid, 0, &rec, 4); + if ( result ) { + result = -1; + printk("Failure writing record header\r\n"); + goto fail; + } + + *len = (rec.reclen-1)*2; + result = rec.rid; +fail: + return result; +} + +/* get Commnication Tallies record's data */ +int Read_CT_InfoData(UINT16 Infofid, void *buf, int len) +{ + + int result = 0; + + /* read the record data (if there is any) */ + if(len > 0); + { + result = prism_copy_from_bap(USER_BAP, Infofid, 4, buf, len);//??user_bap + if ( result ) { + result = -1; + printk("Failure writing record data\r\n"); + goto fail; + } + } + result = len; +fail: + + return result; +} + + +/*------------------------------------------------------------------*/ +/* send a command to device and wait for completion */ +int prism_docmd_wait(UINT16 cmd, UINT16 parm0, UINT16 parm1, UINT16 parm2) +{ + volatile UINT16 reg; + volatile UINT16 result; + volatile UINT16 counter, i; + + volatile UINT16 prismStatus; + volatile UINT16 prismResp0; + volatile UINT16 prismResp1; + volatile UINT16 prismResp2; + + i = CMD_BUSY_TIMEOUT; + /* wait for the busy bit to clear */ + reg = READREG(PRISM_CMD); + while (PRISM_CMD_ISBUSY(reg) && i) { + i--; + udelay(5); + reg = READREG(PRISM_CMD); + } + + if (!PRISM_CMD_ISBUSY(reg)) + { + /* busy bit clear, write command */ + WRITEREG(PRISM_PARAM0, parm0); + WRITEREG(PRISM_PARAM1, parm1); + WRITEREG(PRISM_PARAM2, parm2); + WRITEREG(PRISM_CMD, cmd); + + /* Now wait for completion */ + counter = 0; + reg = READREG(PRISM_EVSTAT); + /* if is TX cmd, timout/30 */ + if((cmd&0x1f) == PRISM_CMDCODE_TX) + i = CMD_COMPL_TIMEOUT/30; + else + i = CMD_COMPL_TIMEOUT; + while (!PRISM_EVSTAT_ISCMD(reg) && i) + { + i--; + udelay(10); + reg = READREG(PRISM_EVSTAT); + } + + if (PRISM_EVSTAT_ISCMD(reg)) + { + result = 0; + prismStatus = READREG(PRISM_STATUS); + prismResp0 = READREG(PRISM_RESP0); + prismResp1 = READREG(PRISM_RESP1); + prismResp2 = READREG(PRISM_RESP2); + WRITEREG(PRISM_EVACK, 0x0010); + result = PRISM_STATUS_RESULT_GET(prismStatus); + } + else + { + //printk("timeout:reg[%x]\n", reg); + result = prism_cmd_diagnose(); + //printk("result [%x]\n", result); + } + } + + return result; +} + +/* send a command to device and no wait for completion */ +int prism_docmd_nowait(UINT16 cmd, UINT16 parm0, UINT16 parm1, UINT16 parm2) +{ + volatile UINT16 reg; + volatile UINT16 result; + volatile UINT16 counter, i; + + volatile UINT16 prismStatus; + volatile UINT16 prismResp0; + volatile UINT16 prismResp1; + volatile UINT16 prismResp2; + + i = CMD_BUSY_TIMEOUT; + /* wait for the busy bit to clear */ + reg = READREG(PRISM_CMD); + while (PRISM_CMD_ISBUSY(reg) && i) { + i--; + udelay(5); + reg = READREG(PRISM_CMD); + } + + if (!PRISM_CMD_ISBUSY(reg)) + { + /* busy bit clear, write command */ + WRITEREG(PRISM_PARAM0, parm0); + WRITEREG(PRISM_PARAM1, parm1); + WRITEREG(PRISM_PARAM2, parm2); + WRITEREG(PRISM_CMD, cmd); + + /* Now wait for completion */ + counter = 0; + reg = READREG(PRISM_EVSTAT); + /* if is TX cmd, timout/30 */ + if((cmd&0x1f) == PRISM_CMDCODE_TX) + i = CMD_COMPL_TIMEOUT/30; + else + i = CMD_COMPL_TIMEOUT; + while (!PRISM_EVSTAT_ISCMD(reg) && i) + { + i--; + udelay(10); + reg = READREG(PRISM_EVSTAT); + } + + result = 0; + prismStatus = READREG(PRISM_STATUS); + prismResp0 = READREG(PRISM_RESP0); + prismResp1 = READREG(PRISM_RESP1); + prismResp2 = READREG(PRISM_RESP2); + WRITEREG(PRISM_EVACK, 0x0010); + result = PRISM_STATUS_RESULT_GET(prismStatus); + } + + return result; +} + + +/* prism command allocate mem */ +int prism_cmd_allocate(UINT16 len, unsigned short *txfid) +{ + int result = 0; + UINT16 cmd; + UINT16 reg; + UINT32 i; + + if (len % 2) + result = -1; + else + { + cmd = PRISM_CMD_CMDCODE_SET(PRISM_CMDCODE_ALLOC); + result = prism_docmd_wait(cmd, len, 0, 0); + } + + reg = READREG(PRISM_EVSTAT); + i = ALLOC_COMPL_TIMEOUT; + while (!PRISM_EVSTAT_ISALLOC(reg) && i) + { + i--; + udelay(10); + reg = READREG(PRISM_EVSTAT); + } + + if(!PRISM_EVSTAT_ISALLOC(reg)) { + printk("Alloc event timeout\n"); + return -ETIMEDOUT; + } + + *txfid = READREG(PRISM_ALLOCFID); + WRITEREG(PRISM_EVACK, PRISM_EVACK_ALLOC_SET(1)); + return result; +} + +/* prism command definition, for device initialization */ +int prism_cmd_initialize() +{ + int result = 0; + + result = prism_docmd_wait(PRISM_CMDCODE_INIT,0,0,0); + return result; +} + +/* this function wish the wireless device has been in slot , :P*/ +/* otherwize it will fail :(, map device register to memory, and */ +/* access memory to setup our device */ +int prism_initmac(struct net_device *dev) +{ + prism_cnfDesireSSID_t ssid; + unsigned short reg = 0; + volatile int i; + int result = 0; + struct w740prism_priv *priv = (struct w740prism_priv *)dev->priv; + + /*---------------------------------------------------------------------------*/ + /* should init for w90740 extern I/0 2 as programm interrupt, for tx, rx. */ + /* But our system has inited it :) */ + //*((volatile unsigned int *) 0xFFF83000) = 0x00054554; // config GPIO + //*((volatile unsigned int *) 0xFFF83000) = 0x00054554; // config GPIO +// i = *((volatile unsigned int *) 0xFFF83000); +// *((volatile unsigned int *) 0xFFF83000) = i & 0xffffcfff; // config GPIO + printk("GPIO: %x\n", *((volatile unsigned int *) 0xFFF83000)); + +// *((volatile unsigned int *) 0xFFF83004) = 0x00100000; // GPIO20 -> output +// *((volatile unsigned int *) 0xFFF83008) = 0x00000000; // GPIO20 -> 0 + *((volatile unsigned int *) 0xFFF83004) = 0x00000003; // GPIO0 and GPIO1 -> output + *((volatile unsigned int *) 0xFFF83008) = 0x00000002; // GPIO1 -> 1 + + /* System memory map. map external I/O bank 2 to start address:0x80000000 */ + /* length: 32M :P, is right no collusion */ + *((volatile unsigned int *) EXT2CON_REG) = 0x8007bffe; //ROM2 for Mem access + + // Set external click 0x00003ff8 + *((volatile unsigned int *) 0xFFF0000c) = 0x00003fe8; // PLL OFF, 15MHz + + /*--------------------------------------------------------------------------------*/ +#if 1 + *((volatile unsigned int *) 0xFFF83008) = 0x00000000; // GPIO1 -> 0 + + *((volatile unsigned short *) 0xC00003e0) = 0x80; // set Configuration Option Register + for(i = 0; i < 500000; i++); + if ((reg = *((volatile unsigned short *) 0xC00003e0)) != 0x80) { + printk("wireless driver reset failed, %x\n", reg); + result= -1; + goto out; + } + else + { + printk("wireless memory reset to system map adress: %x, length: %dM\n" , 0xc0000000, 32); + } + + /*be related with little endian,so value 0x4100 ??? */ + *((volatile unsigned short *) 0xC00003e0) = 0x41; //set Configuration Option Register + for(i = 0; i < 30000; i++); + if ((reg = *((volatile unsigned short *) 0xC00003e0)) != 0x41) { + printk("wireless driver map to system map failed, %x\n", reg); + result= -1; + goto out; + } + else + { + printk("wireless memory map to system map adress: %x, length: %dM\n" , 0xc0000000, 32); + } + *((volatile unsigned int *) 0xfff82010) = 0x01; + +#if 0 + WRITEREG(PRISM_SWSUPPORT0, HERMES_MAGIC); + printk("magic value: %x\n", READREG(PRISM_SWSUPPORT0)); + printk("magic value: %x\n", READREG(PRISM_SWSUPPORT0)); + printk("magic value: %x\n", READREG(PRISM_SWSUPPORT0)); +#endif + result = prism_cmd_initialize(); + if (result != 0) { + printk("Initialize command failed\r\n"); + result = -1; + goto out; + } + else + ;//printk("Initialize command sucess\r\n"); + + /* make sure interrupts are disabled and any layabout events cleared */ + WRITEREG(PRISM_INTEN, PRISM_INTEN_DISABLE); + WRITEREG(PRISM_EVACK, PRISM_EVENT_MASK); + + /* init fid queue */ + Init_Queue(); + Queue_dump(); + + /* sets 0xFC84 TxRates */ + priv->bitratemode = DEFAULT_TXRATE_MODE; + prism_hw_setiwrate(priv); + + /* sets Rxsthreshold */ + priv->rts_thresh = DEFAULT_RXSTHRESHOLD; + prism_hw_setrts(priv); + + /* set ap density */ + priv->ap_density = DEFAULT_SENSE; + prism_hw_setapdensity(priv); + + /* set up power */ + priv->pm_on = DEFAULT_POWMANAGE; + priv->pm_mcast = DEFAULT_MULITRECEIVE; + priv->pm_period = DEFAULT_MAXSLEEP; + priv->pm_timeout = DEFAULT_PMHOLDDURATION; + prism_hw_setpower(priv); + /* sets 0xFC2A auth type */ + reg = PRISM_Authentication; + Write_RID_Config(PRISM_RID_CNFAUTHENTICATION, ®, PRISM_RID_CNFAUTHENTICATION_LEN); + + /* sets link type */ + priv->iw_mode = IW_MODE_INFRA; + reg = priv->port_type = PRISM_MacPortType; + Write_RID_Config(PRISM_RID_CNFPORTTYPE, ®, PRISM_RID_CNFPORTTYPE_LEN); + + /* set 0xFC02 desired SSID */ +#if 1 + ssid.ssidLen = PRISM_SSIDLEN_DEFAULT; + memcpy(ssid.ssidName, PRISM_DesireSSID_DEFAULT, ssid.ssidLen); + Write_RID_Config(PRISM_RID_CNFOWNSSID, (UINT8 *)&ssid, PRISM_RID_CNFOWNSSID_LEN); + Write_RID_Config(PRISM_RID_CNFDESIREDSSID, (UINT8 *)&ssid, PRISM_RID_CNFDESIREDSSID_LEN); +#endif + + /* Retrieve the maximum frame size */ + reg = FRAME_DATA_MAXLEN; + Write_RID_Config(PRISM_RID_CNFMAXDATALEN, ®, PRISM_RID_CNFMAXDATALEN_LEN); + + WRITEREG(PRISM_EVSTAT, PRISM_EVENT_MASK); + WRITEREG(PRISM_INTEN, PRISM_INTEN_ENABLEBITS); + + /* enable MAC port 0 */ + prism_cmd_enable(0); + //printk("Enable the Mac port 0,?\n"); + + +#endif + result = Read_RID_Config(PRISM_RID_CNFOWNMACADDR, priv->mac_address); + for(i = 0; i < 6; i++) + printk("%x ", priv->mac_address[i]); + printk("\n"); + result = Read_RID_Config(PRISM_RID_CNFDESIREDSSID, &ssid); + + //printk("*************************************************\n"); + // printk("TX Size: %d\n", sizeof(struct hermes_tx_descriptor)); + memcpy(priv->desired_essid, ssid.ssidName, ssid.ssidLen); + priv->desired_essid[ssid.ssidLen] = '\0'; + + printk("essid: %s, addr: %x\n", priv->desired_essid, priv->desired_essid); + //printk("\n"); +out: + *((volatile unsigned int *) 0xFFF0000c) = 0x00003ff8; // 80MHz + return result; +} + +/* real device reset, called by prism_reset() */ +int prism_reset_device(struct net_device *dev) +{ + prism_cnfDesireSSID_t ssid; + struct w740prism_priv * priv = dev->priv; + u16 reg; + volatile int i; + int k = CMD_BUSY_TIMEOUT; + int ret = 0; + + priv = dev->priv; + *((volatile unsigned int *) 0xFFF0000c) = 0x00003fe8; // PLL OFF, 15MHz +#if 1 + i = *((volatile unsigned int *) 0xFFF83008); + *((volatile unsigned int *) 0xFFF83008) = i | 0x00000002; /* GPIO1 -> 1 */ + for (i=0; i<10; i++); + i = *((volatile unsigned int *) 0xFFF83008); + *((volatile unsigned int *) 0xFFF83008) = i & 0xfffffffd; /* GPIO1 -> 0 */ + //printk("<<>>\n"); + for(i = 0; i < 30000; i++); + *((volatile unsigned int *) 0xfff82124) = 0x10; // add by chp; disable interrupt + + *((volatile unsigned short *) 0xC00003e0) = 0x80; // set Configuration Option Register + + for(i = 0; i < 500000; i++); + if ((reg = *((volatile unsigned short *) 0xC00003e0)) != 0x80) { + printk("wireless driver reset failed, %x\n", reg); + ret = -1; + goto out; + } + else + { + printk("wireless memory reset to system map adress: %x, length: %dM\n" , 0xc0000000, 32); + } + + /*be related with little endian,so value 0x4100 ??? */ + *((volatile unsigned short *) 0xC00003e0) = 0x41; // set Configuration Option Register + for(i = 0; i < 30000; i++); + if ((reg = *((volatile unsigned short *) 0xC00003e0)) != 0x41) { + printk("wireless driver map to system map failed, %x\n", reg); + ret = -1; + goto out; + } + else + { + printk("wireless memory map to system map adress: %x, length: %dM\n" , 0xc0000000, 32); + } + *((volatile unsigned int *) 0xfff82010) = 0x01; +#endif + /* make sure interrupts are disabled and any layabout events cleared */ + WRITEREG(PRISM_INTEN, PRISM_INTEN_DISABLE); + WRITEREG(PRISM_EVACK, PRISM_EVENT_MASK); + + /* First wait for the command register to unbusy */ + reg = READREG(PRISM_CMD); + while ( (PRISM_CMD_ISBUSY(reg)) && k ) { + k--; + udelay(1); + reg = READREG(PRISM_CMD); + } + //printk("hermes_issue_cmd: did %d retries.\n", CMD_BUSY_TIMEOUT-k); + + reg = READREG(PRISM_EVSTAT); + WRITEREG(PRISM_EVACK, reg); + + + ret = prism_cmd_initialize(); + if (ret != 0) { + printk("Initialize command failed\r\n"); + ret = -1; + goto out; + } + else + ;//printk("Initialize command sucess\r\n"); + + Init_Queue(); + Queue_dump(); + + /* sets link type */ + reg = priv->port_type; + DEBUG("port type: %x\n", priv->port_type); + Write_RID_Config(PRISM_RID_CNFPORTTYPE, ®, PRISM_RID_CNFPORTTYPE_LEN); + DEBUG("allow ibss %x\n", priv->allow_ibss); +#if 0 + reg = PRISM_TxRate; + Write_RID_Config(PRISM_RID_TXRATECNTL, ®, PRISM_RID_TXRATECNTL_LEN); +#else + prism_hw_setiwrate(priv); +#endif + + /* set RxSthread */ + prism_hw_setrts(priv); + + + /* set ap density */ + prism_hw_setapdensity(priv); + + /* set power */ + prism_hw_setpower(priv); + + /* set 0xFC02 desired SSID */ + ssid.ssidLen = strlen(priv->desired_essid); + memcpy(ssid.ssidName, priv->desired_essid, ssid.ssidLen); + printk("essid: %s; addr: %x\n", priv->desired_essid, priv->desired_essid); + Write_RID_Config(PRISM_RID_CNFOWNSSID, (UINT8 *)&ssid, PRISM_RID_CNFOWNSSID_LEN); + Write_RID_Config(PRISM_RID_CNFDESIREDSSID, (UINT8 *)&ssid, PRISM_RID_CNFDESIREDSSID_LEN); + + /* Retrieve the maximum frame size */ + reg = FRAME_DATA_MAXLEN; + Write_RID_Config(PRISM_RID_CNFMAXDATALEN, ®, PRISM_RID_CNFMAXDATALEN_LEN); + + /* set the channel */ + reg = priv->channel; + Write_RID_Config(PRISM_RID_CNFOWNCHANNEL, ®, PRISM_RID_CNFOWNCHANNEL_LEN); + + /* Set up encryption */ +#if 1 + ret = prism_hw_setup_wep(priv); + if (ret) { + printk(KERN_ERR "%s: Error %d activating WEP.\n", + dev->name, ret); + goto out; + } +#endif + WRITEREG(PRISM_EVSTAT, PRISM_EVENT_MASK); + WRITEREG(PRISM_INTEN, PRISM_INTEN_ENABLEBITS); + + /* enable MAC port 0 */ + prism_cmd_enable(0); + //printk("Enable the Mac port 0,?\n"); + + *((volatile unsigned int *) 0xfff82120) = 0x10; // add by chp; enable interrupt + +out: + *((volatile unsigned int *) 0xFFF0000c) = 0x00003ff8; //80MHz + return ret; +} + +/*---------------------------------------------------------------- +* prism_txexc +* +* Handles the TxExc event. A Transmit Exception event indicates +* that the MAC's TX process was unsuccessful - so the packet did +* not get transmitted. +* +* Arguments: +* +* Returns: +* nothing +* +* Side effects: +* +* Call context: +* interrupt +----------------------------------------------------------------*/ +void prism_txexc() +{ + UINT16 status; + UINT16 fid; + int result = 0; + + /* Collect the status and display */ + fid = READREG(PRISM_TXCOMPLFID); + result = prism_copy_from_bap(IRQ_BAP, fid, 0, &status, sizeof(status)); + + //printk(" %x: [%x]\n", fid, status); + + if (result) + printk("prism_txexc:copy_from_bap failed\r\n"); +} + +/* copy data from buffer access path */ +/* Note: only accept the buf which address is align 2 */ +int prism_copy_from_bap(UINT16 bap, UINT16 id, UINT16 offset, void *buf, UINT32 len) +{ + int result = 0; + UINT8 *d = (UINT8*)buf; + UINT16 *dw = buf; + UINT32 selectreg; + UINT32 offsetreg; + UINT32 datareg; + UINT32 i; + volatile UINT16 reg = 0; + int k = 0; + + + + selectreg = bap ? PRISM_SELECT1 : PRISM_SELECT0; + offsetreg = bap ? PRISM_OFFSET1 : PRISM_OFFSET0; + datareg = bap ? PRISM_DATA1 : PRISM_DATA0; + + k = BAP_BUSY_TIMEOUT; + /* Write id to select reg */ + reg = READREG(offsetreg); + while (PRISM_OFFSET_ISBUSY(reg) && k) { + k--; + udelay(5); + reg = READREG(offsetreg); + } + if(!k) { + result = -1; + LOGPRINT; + goto failed; + } + WRITEREG(selectreg, id); + + k = BAP_BUSY_TIMEOUT; + /* Write offset to offset reg */ + reg = READREG(offsetreg); + while (PRISM_OFFSET_ISBUSY(reg) && k) + { + k--; + udelay(5); + reg = READREG(offsetreg); + } + if(!k) { + result = -1; + LOGPRINT; + goto failed; + } + WRITEREG(offsetreg, offset); + + k = BAP_BUSY_TIMEOUT; + /* Wait for offset[busy] to clear */ + reg=READREG(offsetreg); + while (PRISM_OFFSET_ISBUSY(reg) &&k ) + { + k--; + udelay(5); + reg=READREG(offsetreg); + } + if (PRISM_OFFSET_ISERR(reg)) { //?? + //result = reg; + LOGPRINT; + result = -1; + return result; + } + /* Read even(len) buf contents from data reg */ + for ( i = 0; i < (len>>1); i++ ) { + *dw++ = READREG(datareg); + } + /* If len odd, handle last byte */ + if ( len % 2 ) + { + reg = READREG(datareg); + d[len-1] = ((UINT8*)(®))[0]; + } + + if (result) { + LOGPRINT; + printk("copy_from_bap failed\r\n"); + } +failed: + return result; + +} + + +static int prism_hw_get_essid(struct w740prism_priv *priv, int *active, + char buf[IW_ESSID_MAX_SIZE+1]) +{ +#if 0 + hermes_t *hw = &priv->hw; + int err = 0; + struct hermes_idstring essidbuf; + char *p = (char *)(&essidbuf.val); + int len; + + + orinoco_lock(priv); + + if (strlen(priv->desired_essid) > 0) { + /* We read the desired SSID from the hardware rather + than from priv->desired_essid, just in case the + firmware is allowed to change it on us. I'm not + sure about this */ + /* My guess is that the OWNSSID should always be whatever + * we set to the card, whereas CURRENT_SSID is the one that + * may change... - Jean II */ + u16 rid; + + *active = 1; + + rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID : + HERMES_RID_CNFDESIREDSSID; + + err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf), + NULL, &essidbuf); + if (err) + goto fail_unlock; + } else { + *active = 0; + + err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID, + sizeof(essidbuf), NULL, &essidbuf); + if (err) + goto fail_unlock; + } + + len = le16_to_cpu(essidbuf.len); + + memset(buf, 0, IW_ESSID_MAX_SIZE+1); + memcpy(buf, p, len); + buf[len] = '\0'; + + fail_unlock: + orinoco_unlock(priv); + + return err; +#endif + return 0; +} + +/* Get current connected AP's essid */ +int prism_ioctl_getessid(struct net_device *dev, struct iw_point *erq) +{ + struct w740prism_priv *priv = dev->priv; + char essidbuf[IW_ESSID_MAX_SIZE+1]; + prism_cnfDesireSSID_t our_ssid; + int err = 0; + + err = Read_RID_Config(PRISM_RID_CNFDESIREDSSID, &our_ssid); + DEBUG("essid len: %d\n", our_ssid.ssidLen); + if(our_ssid.ssidLen <= 0) { + erq->flags = 0; + return 0; + } + + erq->flags = 1; + erq->length = our_ssid.ssidLen; + memcpy(essidbuf, our_ssid.ssidName, our_ssid.ssidLen); + if (erq->pointer) + if ( copy_to_user(erq->pointer, essidbuf, erq->length) ) + return -EFAULT; + return 0; +} + +/* it should get net working freq or channel, we only get channel */ +/* if AD-Hoc mode, return OWNCHANNEL register's value */ +/* else if infrastructure mode, return CURRENT regiester's value */ +long prism_hw_get_freq(struct w740prism_priv *priv) +{ + int err = 0; + u16 channel; + long freq = 0; + prism_lock(priv); + DEBUG("Current Mode: %d\n", priv->iw_mode); + if(priv->iw_mode == IW_MODE_INFRA) { + err = Read_RID_Config(PRISM_RID_CURRENTCHANNEL, &channel); + } + else if(priv->iw_mode == IW_MODE_ADHOC) { + err = Read_RID_Config(PRISM_RID_CNFOWNCHANNEL, &channel); + } + else + err = -1; + if(err < 0) + { + printk("%s: read channel erro\n"); + err = -EBUSY; + goto out; + } + + if ( (channel < 1) || (channel > NUM_CHANNELS) ) { + struct net_device *dev = priv->ndev; + + printk("%s: Channel out of range (%d)!\n", dev->name, channel); + err = -EBUSY; + goto out; + + } + freq = channel; + //printk("channel: %d, %d\n", channel, freq); + err = 0; +out: + prism_unlock(priv); + return err ? err : freq; +} + +/* Set essid */ +int prism_ioctl_setessid(struct net_device *dev, struct iw_point *essid) +{ + int err = 0; + prism_lock(dev->priv); + memcpy(((struct w740prism_priv *)(dev->priv))->desired_essid, (unsigned char *)essid->pointer, essid->length); + DEBUG("essid: %s, len: %d\n", ((struct w740prism_priv *)dev->priv)->desired_essid, essid->length); + prism_unlock(dev->priv); + + return err; +} + +/* set freq(it refers to channel here) */ +int prism_ioctl_setfreq(struct net_device *dev, struct iw_freq *freq) +{ + int err = 0; + struct w740prism_priv *priv = dev->priv; + u16 reg; + + //printk("value: %x\n", freq->m); + if( (freq->m < 1) || (freq->m > NUM_CHANNELS)) { + printk("%s: Channel out of range (%d)!\n", dev->name, freq->m); + err = -EFAULT; + goto out; + } + priv->channel = freq->m; +out: + return err; +} + +/* get Wep key */ +int prism_ioctl_getiwencode(struct net_device *dev, struct iw_point *erq) +{ + struct w740prism_priv *priv = dev->priv; + int index = (erq->flags & IW_ENCODE_INDEX) - 1; + u16 xlen = 0; + char keybuf[PRISM_MAX_KEY_SIZE]; + int i, j; + u16 defaultkeyid, wepflags, authentication; + + prism_lock(priv); + if ((index < 0) || (index >= PRISM_MAX_KEYS)) + index = priv->tx_key; + + erq->flags = 0; + if (! priv->wep_on) + erq->flags |= IW_ENCODE_DISABLED; + erq->flags |= index + 1; + + xlen = le16_to_cpu(priv->keys[index].len); + erq->length = xlen; + + if (erq->pointer) { + memcpy(keybuf, priv->keys[index].data, PRISM_MAX_KEY_SIZE); + } + + prism_unlock(priv); + + if (erq->pointer) { + if (copy_to_user(erq->pointer, keybuf, xlen)) + return -EFAULT; + } +// for(i = 0; i < xlen; i++) { +// printk("%x", keybuf[i]); +// } +// printk("\n"); + for(j = 0; j < 4; j++) { + Read_RID_Config(PRISM_RID_CNFDEFAULTKEY0+j, keybuf); +// for(i = 0; i < xlen; i++) { +// printk("%x", keybuf[i]); +// } +// printk("\n"); + } + Read_RID_Config(PRISM_RID_CNFWEPDEFAULTKEYID, &defaultkeyid); + Read_RID_Config(PRISM_RID_CNFWEPFLAGS, &wepflags); + Read_RID_Config(PRISM_RID_CNFAUTHENTICATION, &authentication); +// printk("defaultkeyid: %x, wepflags: %x, authentication: %x\n", defaultkeyid, wepflags, authentication); + return 0; +} + +/* set Wep key */ +int prism_ioctl_setiwencode(struct net_device *dev, struct iw_point *erq) +{ + int i; + struct w740prism_priv *priv = dev->priv; + char buf[IW_ENCODING_TOKEN_MAX+1]; + int index = (erq->flags & IW_ENCODE_INDEX) - 1; + int setindex = priv->tx_key; + int enable = priv->wep_on; + int restricted = priv->wep_restrict; + int xlen = 0; + int err = 0; +//printk("index: %d, len: %d, nowlen: %d\n", index, erq->length, priv->keys[index].len); + if (erq->length > IW_ENCODING_TOKEN_MAX) + { + printk("Too long key\n"); + return -EFAULT; + } + + if (erq->pointer) { + if(copy_from_user(buf, erq->pointer, erq->length)) + return -EFAULT; + } + prism_lock(priv); + if (erq->pointer) { + if (erq->length > PRISM_MAX_KEY_SIZE) { + printk("Too long key string\n"); + err = -E2BIG; + goto out; + } + +// if ( (erq->length > LARGE_KEY_SIZE) +// || ( ! priv->has_big_wep && (erq->length > SMALL_KEY_SIZE)) ) { +// err = -EINVAL; +// goto out; +// } + + if ((index < 0) || (index >= PRISM_MAX_KEYS)) + index = priv->tx_key; + + if (erq->length > SMALL_KEY_SIZE) { + LOGPRINT; + xlen = LARGE_KEY_SIZE; + } else if (erq->length > 0) { + LOGPRINT; + xlen = SMALL_KEY_SIZE; + } else + xlen = 0; + + /* Switch on WEP if off */ + if ((!enable) && (xlen > 0)) { + setindex = index; + enable = 1; + } + } else { + /* Important note : if the user do "iwconfig eth0 enc off", + * we will arrive there with an index of -1. This is valid + * but need to be taken care off... Jean II */ + if ((index < 0) || (index >= PRISM_MAX_KEYS)) { + if((index != -1) || (erq->flags == 0)) { + err = -EINVAL; + goto out; + } + } else { + /* Set the index : Check that the key is valid */ + if(priv->keys[index].len == 0) { + err = -EINVAL; + goto out; + } + setindex = index; + } + } + + if (erq->flags & IW_ENCODE_DISABLED) + enable = 0; + /* Only for Prism2 & Symbol cards (so far) - Jean II */ + if (erq->flags & IW_ENCODE_OPEN) + restricted = 0; + if (erq->flags & IW_ENCODE_RESTRICTED) + restricted = 1; + + if (erq->pointer) { + priv->keys[index].len = cpu_to_le16(xlen); + memset(priv->keys[index].data, 0, sizeof(priv->keys[index].data)); + memcpy(priv->keys[index].data, buf, erq->length); + } + priv->tx_key = setindex; + priv->wep_on = enable; + priv->wep_restrict = restricted; + + out: + buf[erq->length] = '\0'; +// for(i = 0; i < erq->length; i++) +// printk("%x", buf[i]); +// printk("\n"); +// printk("tx_key: %d, wep_on: %d, wep_restrict: %d\n", priv->tx_key, priv->wep_on, priv->wep_restrict); +// printk("tx_key's length: %d\n", priv->keys[priv->tx_key].len); + prism_unlock(priv); + return err; +} + +/* real setup the Wep key to hardware */ +int prism_hw_setup_wep(struct w740prism_priv *priv) +{ + int err = 0; + int keylen; + int i, j; + int auth_flag; + int master_wep_flag = 0; //is off + +// printk("prism_hw_setup_wep\n"); + if (priv->wep_on) { + /* Write all 4 keys */ + keylen = le16_to_cpu(priv->keys[priv->tx_key].len); + for(i = 0; i < PRISM_MAX_KEYS; i++) { +// printk("keylen: %d, reallen: %d\n", keylen, priv->keys[i].len); + if (keylen > LARGE_KEY_SIZE) { + printk("%s: Key %d has oversize length %d.\n", + priv->ndev->name, i, keylen); + return -E2BIG; + } +// printk("%dkey's len: %d\n", i, keylen); +// for( j = 0; j < keylen; j++) +// printk("%x", priv->keys[i].data[j]); +// printk("\n"); + err = Write_RID_Config(PRISM_RID_CNFDEFAULTKEY0 + i, priv->keys[i].data, keylen); + if (err) + return err; + } + + err = Write_RID_Config(PRISM_RID_CNFWEPDEFAULTKEYID, &priv->tx_key, PRISM_RID_CNFWEPDEFAULTKEYID_LEN); + if (err) + return err; + + if (priv->wep_restrict) { + auth_flag = 2; + master_wep_flag = 3; + } else { + auth_flag = 1; + master_wep_flag = 1; /* Intersil */ + } + + err = Write_RID_Config(PRISM_RID_CNFAUTHENTICATION, &auth_flag, PRISM_RID_CNFAUTHENTICATION_LEN); + if (err) + return err; + } + Read_RID_Config(PRISM_RID_CNFAUTHENTICATION, &auth_flag); +// printk("Auth_flag: %x\n", auth_flag); + /* Master WEP setting : on/off */ + err = Write_RID_Config(PRISM_RID_CNFWEPFLAGS, &master_wep_flag, PRISM_RID_CNFWEPFLAGS_LEN); + if (err) + return err; + return 0; +} + +int prism_ioctl_setscan(struct net_device *dev, struct iw_point *erq) +{ + int err = 0; + unsigned short len; + unsigned int i, j, cnt; + struct w740prism_priv *priv = dev->priv; +// printk("erq->length: %d\n", erq->length); + prism_lock(priv); +#if 1 + prism_cmd_inquiry(PRISM_INQ_SCAN); + if(down_interruptible(&priv->sema)) + err = -1; + + + DEBUG("erq addr: %x\n", erq); + prism_ioctl_getaplist(dev, erq); +#endif + prism_unlock(priv); + return err; +} + +int prism_hw_get_bssid(struct net_device *dev, char buf[ETH_ALEN]) +{ + struct w740prism_priv *priv = dev->priv; + int err = 0; + int i = 0; + + err = Read_RID_Config(PRISM_RID_CURRENTBSSID, buf); + +// for(i = 0; i < 6; i++) +// printk("%x.", buf[i]); +// printk("\n"); + return err; +} + +int prism_ioctl_getstat(struct net_device *dev, struct iw_point *erq) +{ + int err = 0; + int status = 0; +// printk("%s: %d\n", __FILE__,__LINE__); + prism_cmd_inquiry(PRISM_INQ_ASSOCIATIONSTATUS); +// printk("%s: %d\n", __FILE__,__LINE__); + return err; +} + + +int prism_ioctl_getlinkstat(struct net_device *dev, struct iw_point *erq) +{ + int err = 0; + int status = 0; + struct w740prism_priv *priv = (struct w740prism_priv *)dev->priv; +// printk("%s: %d\n", __FILE__,__LINE__); + prism_lock(priv); + if (erq->pointer) { + if (copy_to_user(erq->pointer, &(priv->status), erq->length)) + return -EFAULT; + } + prism_unlock(priv); + //prism_cmd_inquiry(PRISM_INQ_LINKSTATUS); +// printk("%s: %d\n", __FILE__,__LINE__); + return err; +} + +int prism_ioctl_getiwrate(struct net_device *dev, struct iw_param *iwp) +{ + int err = 0; + int rate = 0; + int i; + err = Read_RID_Config(PRISM_RID_CURRENTTXRATE, &rate); + + for(i = 0; i < BITRATE_TABLE_SIZE; i++) + { + if (bitrate_table[i].prism_txratectrl == rate) { + break; + } + } + if(i >= BITRATE_TABLE_SIZE) + { + printk("Can't get correct rate\n"); + i = 0; + } + + iwp->value = bitrate_table[i].bitrate * 100000; +// printk("Current rate: %d\n", iwp->value); + iwp->disabled = 0; + return err; +} + +int prism_ioctl_setiwrate(struct net_device *dev, struct iw_param *iwp) +{ + struct w740prism_priv *priv = dev->priv; + int err = 0; + int ratemode = -1; + int bitrate; /* 100s of kilobits */ + int i; +//printk("rate: %d\n", iwp->value); + if (iwp->value == -1) + bitrate = 110; + else { + if (iwp->value % 100000) + return -EINVAL; + bitrate = iwp->value / 100000; + } + + if ( (bitrate != 10) && (bitrate != 20) && + (bitrate != 55) && (bitrate != 110) ) + return -EINVAL; + + for (i = 0; i < BITRATE_TABLE_SIZE; i++) + if ( (bitrate_table[i].bitrate == bitrate)) { + ratemode = i; + break; + } + + if (ratemode == -1) + return -EINVAL; + + prism_lock(priv); + priv->bitratemode = ratemode; + prism_unlock(priv); + + return err; +} + +int prism_hw_setiwrate(struct w740prism_priv *priv) +{ + int err = 0; +// printk("ratemode: %x\n", priv->bitratemode); +// + if (priv->bitratemode >= BITRATE_TABLE_SIZE) { + printk("%s: Invalid bitrate mode %d\n", + "wlan", priv->bitratemode); + return -EINVAL; + } + err = Write_RID_Config(PRISM_RID_TXRATECNTL, &bitrate_table[priv->bitratemode].prism_txratectrl, PRISM_RID_TXRATECNTL_LEN); + return err; +} + +int prism_ioctl_setrts(struct net_device *dev, struct iw_param *iwp) +{ + int err = 0; + struct w740prism_priv *priv = dev->priv; + int val = iwp->value; + + if (iwp->disabled) + val = 2347; + + if ( (val < 0) || (val > 3000) ) + return -EINVAL; + + prism_lock(priv); + priv->rts_thresh = val; + prism_unlock(priv); + + return err; +} + +int prism_hw_setrts(struct w740prism_priv *priv) +{ + int err = 0; + + /* Set RTS threshold */ + err = Write_RID_Config(PRISM_RID_RTSTHRESHOLD, &priv->rts_thresh, PRISM_RID_RTSTHRESHOLD_LEN); + + return err; +} + +int prism_ioctl_getsens(struct net_device *dev, struct iw_param *iwp) +{ + int err = 0; + int val = 0; + + Read_RID_Config(PRISM_RID_CNFSYSTEMSCALE, &val); +// printk("Current sense: %d\n", val); + iwp->value = val; + iwp->fixed = 0; /* auto */ + + return 0; +} + +int prism_ioctl_setsens(struct net_device *dev, struct iw_param *iwp) +{ + int err = 0; + struct w740prism_priv *priv = dev->priv; + int val = iwp->value; + + if ((val < 1) || (val > 3)) + return -EINVAL; + + prism_lock(priv); + priv->ap_density = val; + prism_unlock(priv); + + return err; +} + +int prism_hw_setapdensity(struct w740prism_priv *priv) +{ + int err = 0; + err = Write_RID_Config(PRISM_RID_CNFSYSTEMSCALE, &priv->ap_density, PRISM_RID_CNFSYSTEMSCALE_LEN); + if (err) + return err; + return err; +} + +int prism_ioctl_getpower(struct net_device *dev, struct iw_param *iwp) +{ + int err = 0; + struct w740prism_priv *priv = dev->priv; + u16 enable, period, timeout, mcast; + + prism_lock(priv); + + Read_RID_Config(PRISM_RID_CNFPMENABLED, &enable); + Read_RID_Config(PRISM_RID_CNFMAXSLEEPDURATION, &period); + Read_RID_Config(PRISM_RID_CNFPMHOLDOVERDURATION, &timeout); + Read_RID_Config(PRISM_RID_CNFMULTICASTRECEIVE, &mcast); + + iwp->disabled = !enable; + /* Note : by default, display the period */ + if ((iwp->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { + iwp->flags = IW_POWER_TIMEOUT; + iwp->value = timeout * 1000; + } else { + iwp->flags = IW_POWER_PERIOD; + iwp->value = period * 1000; + } + if (mcast) + iwp->flags |= IW_POWER_ALL_R; + else + iwp->flags |= IW_POWER_UNICAST_R; + + out: + prism_unlock(priv); + return err; +} + +int prism_ioctl_setpower(struct net_device *dev, struct iw_param *iwp) +{ + int err = 0; + struct w740prism_priv *priv = dev->priv; + + prism_lock(priv); + if (iwp->disabled) { + priv->pm_on = 0; + } else { + switch (iwp->flags & IW_POWER_MODE) { + case IW_POWER_UNICAST_R: + priv->pm_mcast = 0; + priv->pm_on = 1; + break; + case IW_POWER_ALL_R: + priv->pm_mcast = 1; + priv->pm_on = 1; + break; + case IW_POWER_ON: + break; + default: + err = -EINVAL; + } + + if (err) + goto out; + + if (iwp->flags & IW_POWER_TIMEOUT) { + priv->pm_on = 1; + priv->pm_timeout = iwp->value / 1000; + } + if (iwp->flags & IW_POWER_PERIOD) { + priv->pm_on = 1; + priv->pm_period = iwp->value / 1000; + } + if(!priv->pm_on) { + err = -EINVAL; + goto out; + } + } +out: + prism_unlock(priv); + return err; +} + + +int prism_hw_setpower(struct w740prism_priv *priv) +{ + int err = 0; + err = Write_RID_Config(PRISM_RID_CNFPMENABLED, &priv->pm_on, PRISM_RID_CNFPMENABLED_LEN); + if (err) + return err; + err = Write_RID_Config(PRISM_RID_CNFMAXSLEEPDURATION, &priv->pm_period, PRISM_RID_CNFMAXSLEEPDURATION_LEN); + if (err) + return err; + err = Write_RID_Config(PRISM_RID_CNFPMHOLDOVERDURATION, &priv->pm_timeout, PRISM_RID_CNFPMHOLDOVERDURATION_LEN); + if (err) + return err; + err = Write_RID_Config(PRISM_RID_CNFMULTICASTRECEIVE, &priv->pm_mcast, PRISM_RID_CNFMULTICASTRECEIVE_LEN); + if (err) + return err; + return err; +} + +int get_scan_result(UINT16 infoid, int lens, struct w740prism_priv *priv) +{ + int result = 0; + int len, j, i, cnt; +#ifdef SCAN_ENABLE + struct prism_ScanResult * scan; + prism_lock(priv); + + len = Read_CT_InfoData(infoid, &priv->scan_res, lens); + scan = &priv->scan_res; +// printk("len=%d\n", len); + len = len/2; + cnt = (len - 2) / 31; + priv->scan_res_len = cnt; +// printk("reason[%d], cnt: %d\n", scan->scanreason, cnt); + for (j=0; jresult[j].chid > 14) { + LOGPRINT; + break; + } +// printk("off: %d, j: %d\n", scan->result+j, j); +// printk("channel[%d]\n", scan->result[j].chid); +// +// printk("bssid ["); +// for (i=0; i<6; i+=2) +// printk(" %02x %02x", scan->result[j].bssid[i+1], scan->result[j].bssid[i]); +// printk("]\n"); +// printk("ssid ["); +// len = scan->result[j].ssid.ssidLen; +// if (len % 2) +// { +// for (i=0; iresult[j].ssid.ssidName[i+1], scan->result[j].ssid.ssidName[i]); +// printk(" %02x", scan->result[j].ssid.ssidName[len]); +// } +// else +// { +// for (i=0; iresult[j].ssid.ssidName[i+1], scan->result[j].ssid.ssidName[i]); +// } +// printk("]\n"); +#endif + } + up(&priv->sema); + prism_unlock(priv); +#endif + return result; +} + +int prism_ioctl_getaplist(struct net_device *dev, struct iw_point * iwp) +{ + int err = 0; + struct w740prism_priv *priv = dev->priv; + int num = 0; + int i, len; +#if 1 + int j; +#endif + prism_ScanResultSub_t *resultp = &(priv->scan_res.result[0]); +DEBUG("iwp: %x, iwp->length: %d\n", iwp, iwp->length); + prism_lock(priv); + + if(iwp->length == 0) + { + iwp->length = priv->scan_res_len; + DEBUG("iwp->length: %d\n", iwp->length); + } +#if 1 + else + { + len = (iwp->length > priv->scan_res_len ? priv->scan_res_len:iwp->length); + for(i = 0; i < len; i++) + { + if (iwp->pointer) + if ( copy_to_user(iwp->pointer + sizeof(prism_cnfDesireSSID_t)*i, + &((resultp+i)->ssid), + sizeof(prism_cnfDesireSSID_t) ) + ) + return -EFAULT; +#if 0 + for(j = 0; j < ((resultp+i)->ssid).ssidLen; j++) + { + printk("%c", ((resultp+i)->ssid).ssidName[j]); + } + printk("\n"); +#endif + } + } +#endif + prism_unlock(priv); + return err; +} + +void set_port_type(struct w740prism_priv *priv) +{ + switch (priv->iw_mode) { + case IW_MODE_INFRA: + priv->port_type = 1; + priv->allow_ibss = 0; + break; + case IW_MODE_ADHOC: + if (priv->prefer_port3) { + priv->port_type = 3; + priv->allow_ibss = 0; + } else { + priv->port_type = 0;//priv->ibss_port; + priv->allow_ibss = 1; + } + break; + default: + printk("%s: Invalid priv->iw_mode\n", + priv->ndev->name); + } +} + +int prism_ioctl_setspy(struct net_device *dev, struct iw_point *iwp) +{ + int result = 0; + struct w740prism_priv *priv = dev->priv; + struct sockaddr address[IW_MAX_SPY]; + int number = iwp->length; + int i; + + if (number > IW_MAX_SPY) + return -E2BIG; + + if (iwp->pointer) { + if (copy_from_user(address, iwp->pointer, + sizeof(struct sockaddr) * number)) + return -EFAULT; + } + + prism_lock(priv); + priv->spy_number = 0; + + if (number > 0) { + for (i = 0; i < number; i++) + memcpy(priv->spy_address[i], address[i].sa_data, + ETH_ALEN); + memset(priv->spy_stat, 0, + sizeof(struct iw_quality) * IW_MAX_SPY); + priv->spy_number = number; + } + + DEBUG("%s: New spy list:\n", dev->name); + for (i = 0; i < number; i++) { + DEBUG("%s: %d - %02x:%02x:%02x:%02x:%02x:%02x\n", + dev->name, i+1, + priv->spy_address[i][0], priv->spy_address[i][1], + priv->spy_address[i][2], priv->spy_address[i][3], + priv->spy_address[i][4], priv->spy_address[i][5]); + } + + prism_unlock(priv); + return result; +} + +int prism_ioctl_getspy(struct net_device *dev, struct iw_point *iwp) +{ + struct w740prism_priv *priv = dev->priv; + struct sockaddr address[IW_MAX_SPY]; + struct iw_quality spy_stat[IW_MAX_SPY]; + int number; + int i; + + prism_lock(priv); + + number = priv->spy_number; + if ((number > 0) && (iwp->pointer)) { + for (i = 0; i < number; i++) { + memcpy(address[i].sa_data, priv->spy_address[i], + ETH_ALEN); + address[i].sa_family = AF_UNIX; + } + /* Copy stats */ + memcpy(&spy_stat, priv->spy_stat, + sizeof(struct iw_quality) * IW_MAX_SPY); + for (i=0; i < number; i++) + priv->spy_stat[i].updated = 0; + } + + prism_unlock(priv); + + iwp->length = number; + if(copy_to_user(iwp->pointer, address, + sizeof(struct sockaddr) * number)) + return -EFAULT; + if(copy_to_user(iwp->pointer + (sizeof(struct sockaddr)*number), + &spy_stat, sizeof(struct iw_quality) * number)) + return -EFAULT; + + return 0; +} -- cgit v0.12