summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Schinagl <oliver@schinagl.nl>2011-03-16 09:16:45 (GMT)
committerOliver Schinagl <oliver@schinagl.nl>2011-03-16 09:16:45 (GMT)
commit5a25bf2d3ebeccbc07bada8f78306616e1ec0f1b (patch)
treeade1a4da49cc169e10d0487e9753ad6f662825bf
parentd66024a03c43952bc230fa9d0133f545d9caab00 (diff)
downloadopenipcam-5a25bf2d3ebeccbc07bada8f78306616e1ec0f1b.zip
openipcam-5a25bf2d3ebeccbc07bada8f78306616e1ec0f1b.tar.gz
openipcam-5a25bf2d3ebeccbc07bada8f78306616e1ec0f1b.tar.bz2
W90N745 networking patches
-rw-r--r--uClinux-2.4.20-uc1/drivers/net/Config.in5
-rw-r--r--uClinux-2.4.20-uc1/drivers/net/Makefile1
-rwxr-xr-xuClinux-2.4.20-uc1/drivers/net/w90n745_mac.c1390
-rwxr-xr-xuClinux-2.4.20-uc1/drivers/net/w90n745_mac.h354
-rw-r--r--uClinux-2.4.20-uc1/drivers/net/wireless/Config.in4
-rw-r--r--uClinux-2.4.20-uc1/drivers/net/wireless/Makefile1
-rwxr-xr-xuClinux-2.4.20-uc1/drivers/net/wireless/Queue.c90
-rwxr-xr-xuClinux-2.4.20-uc1/drivers/net/wireless/Queue.h37
-rwxr-xr-xuClinux-2.4.20-uc1/drivers/net/wireless/W90N745Prism.c998
-rwxr-xr-xuClinux-2.4.20-uc1/drivers/net/wireless/W90N745Prism.h863
-rwxr-xr-xuClinux-2.4.20-uc1/drivers/net/wireless/base.c1783
11 files changed, 5526 insertions, 0 deletions
diff --git a/uClinux-2.4.20-uc1/drivers/net/Config.in b/uClinux-2.4.20-uc1/drivers/net/Config.in
index 14c84ae..20bbd69 100644
--- a/uClinux-2.4.20-uc1/drivers/net/Config.in
+++ b/uClinux-2.4.20-uc1/drivers/net/Config.in
@@ -33,6 +33,11 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
string 'S3C4530 MAC Address' S3C4530_HWADDR 00:00:00:00:00:00
fi
fi
+ if [ "$CONFIG_CPU_W90N745" = "y" ]; then
+ if [ "$CONFIG_W90N745_KEYPAD" != "y" ]; then
+ bool ' Winbond W90N745 Embedded Ethernet support' CONFIG_ETH_W90N745
+ fi
+ fi
if [ "$CONFIG_ARM" = "y" ]; then
dep_bool ' ARM EBSA110 AM79C961A support' CONFIG_ARM_AM79C961A $CONFIG_ARCH_EBSA110
if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
diff --git a/uClinux-2.4.20-uc1/drivers/net/Makefile b/uClinux-2.4.20-uc1/drivers/net/Makefile
index 3b92fb7..277b61b 100644
--- a/uClinux-2.4.20-uc1/drivers/net/Makefile
+++ b/uClinux-2.4.20-uc1/drivers/net/Makefile
@@ -149,6 +149,7 @@ obj-$(CONFIG_NET_SB1250_MAC) += sb1250-mac.o
#
obj-$(CONFIG_ETH_S3C4510) += s3c4510.o
obj-$(CONFIG_ETH_S3C4530) += s3c4530.o
+obj-$(CONFIG_ETH_W90N745) += w90n745_mac.o
obj-$(CONFIG_SMC91111) += smc91111.o
obj-$(CONFIG_FEC) += fec.o
obj-$(CONFIG_ETHER_NETARM) += netarmeth.o
diff --git a/uClinux-2.4.20-uc1/drivers/net/w90n745_mac.c b/uClinux-2.4.20-uc1/drivers/net/w90n745_mac.c
new file mode 100755
index 0000000..fb70095
--- /dev/null
+++ b/uClinux-2.4.20-uc1/drivers/net/w90n745_mac.c
@@ -0,0 +1,1390 @@
+/*
+ * linux/deriver/net/w90n745_mac.c
+ * Ethernet driver for winbond W90N745 ( PC34 Lsshi )
+*/
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+
+#include <linux/in.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/skbuff.h>
+#include <asm/semaphore.h>
+#include <asm/irq.h>
+#include "w90n745_mac.h"
+#include <asm/arch/flash.h>
+
+
+#define HAVE_PHY
+#define RX_TIMEOUT 1
+//#define IC_PLUS
+//#define TEST_REST
+#undef DEBUG
+//#define DEBUG
+#define TRACE_ERROR printk
+#ifdef DEBUG
+ #define TRACE(str, args...) printk("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;i<len;i+=10)
+ printk("%2x %2x %2x %2x %2x %2x %2x %2x %2x %2x\n",*(data+i),*(data+i+1),
+ *(data+i+2),*(data+i+3),*(data+i+4),*(data+i+5),*(data+i+6),
+ *(data+i+7),*(data+i+8),*(data+i+9));
+ printk("\n");
+#endif
+//printk("n745_start_xmit:dev:%x\n",dev);
+ if(!(send_frame(dev,skb->data,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;i<TX_DESC_SIZE;i++)
+ printk("%x mode:%lx,2 SL:%lx\n",&n745_priv->tx_desc[i],n745_priv->tx_desc[i].mode,n745_priv->tx_desc[i].SL);
+ for(i=0;i<RX_DESC_SIZE;i++)
+ printk("%x SL:%x\n",&n745_priv->rx_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
new file mode 100755
index 0000000..684f7bd
--- /dev/null
+++ b/uClinux-2.4.20-uc1/drivers/net/w90n745_mac.h
@@ -0,0 +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
diff --git a/uClinux-2.4.20-uc1/drivers/net/wireless/Config.in b/uClinux-2.4.20-uc1/drivers/net/wireless/Config.in
index 9f85072..d0a9a5a 100644
--- a/uClinux-2.4.20-uc1/drivers/net/wireless/Config.in
+++ b/uClinux-2.4.20-uc1/drivers/net/wireless/Config.in
@@ -8,6 +8,10 @@ fi
tristate ' Hermes chipset 802.11b support (Orinoco/Prism2/Symbol)' CONFIG_HERMES
+if [ "$CONFIG_CPU_W90N745" = "y" ]; then
+ bool ' W90745 PRISM2 chipset 802.11b support ' CONFIG_N745PRISM
+fi
+
if [ "$CONFIG_ALL_PPC" = "y" ]; then
dep_tristate ' Apple Airport support (built-in)' CONFIG_APPLE_AIRPORT $CONFIG_HERMES
fi
diff --git a/uClinux-2.4.20-uc1/drivers/net/wireless/Makefile b/uClinux-2.4.20-uc1/drivers/net/wireless/Makefile
index 7c76eb6..cd611c2 100644
--- a/uClinux-2.4.20-uc1/drivers/net/wireless/Makefile
+++ b/uClinux-2.4.20-uc1/drivers/net/wireless/Makefile
@@ -15,6 +15,7 @@ obj- :=
export-objs := airo.o orinoco.o hermes.o
obj-$(CONFIG_HERMES) += orinoco.o hermes.o
+obj-$(CONFIG_N745PRISM) += W90N745Prism.o base.o Queue.o
obj-$(CONFIG_PCMCIA_HERMES) += orinoco_cs.o
obj-$(CONFIG_APPLE_AIRPORT) += airport.o
obj-$(CONFIG_PLX_HERMES) += orinoco_plx.o
diff --git a/uClinux-2.4.20-uc1/drivers/net/wireless/Queue.c b/uClinux-2.4.20-uc1/drivers/net/wireless/Queue.c
new file mode 100755
index 0000000..3df0044
--- /dev/null
+++ b/uClinux-2.4.20-uc1/drivers/net/wireless/Queue.c
@@ -0,0 +1,90 @@
+#include "W90N745Prism.h"
+#include "Queue.h"
+
+
+extern Queue_txfid TxQueueObj;
+/* private txfid queue function, for interval use */
+INT16 Init_Queue()
+{
+ INT16 i;
+ INT16 result = 0;
+ INT16 retry = 0;
+
+ memset(&TxQueueObj, 0, sizeof(Queue_txfid));
+ for (i = 0; i < PRISM2_TX_FIDSTACKLEN_MAX; i++)
+ {
+retryalloc:
+ result = prism_cmd_allocate(PRISM2_TXBUF_MAX, &(TxQueueObj.cells[i].fid));
+ if (result != 0) {
+ printk("Allocate(tx) command failed\n");
+ result = -1;
+ if(retry < 4) {
+ retry++;
+ goto retryalloc;
+ }
+ goto out;
+ }
+ retry = 0;
+ TxQueueObj.cells[i].flag |=0x1;
+ }
+out:
+ TxQueueObj.capability = i;
+ return i;
+}
+
+/* Dump for debuging queue */
+void Queue_dump()
+{
+#ifdef WDEBUG
+ int i;
+
+ printk("Number of Cells in Queue: %d\n", TxQueueObj.capability);
+ for(i = 0; i < TxQueueObj.capability; i++)
+ {
+ printk("%dth: txfid: %x, flag: %d\n", i, (TxQueueObj.cells[i].fid), TxQueueObj.cells[i].flag);
+ }
+#endif
+}
+
+/* public txfid queue function, for geting a tx fid */
+INT16 Get_txfid()
+{
+ int i;
+
+ if(GetAvailableCellNum(TxQueueObj) <= 0) {
+ printk("No available cell for tx\n");
+ return -1;
+ }
+
+ for(i = 0; (i < PRISM2_TX_FIDSTACKLEN_MAX)&&(!TxQueueObj.cells[i].flag); i++);
+ if(i >= PRISM2_TX_FIDSTACKLEN_MAX) {
+ printk("Erro:No available cell for tx\n");
+ return -1;
+ }
+ TxQueueObj.cells[i].flag = 0;
+ ReduceAvailableCellNum(TxQueueObj);
+ return TxQueueObj.cells[i].fid;
+}
+
+/* public txfid queue function, for puting a tx fid */
+INT16 Put_txfid(UINT16 val)
+{
+ INT16 result = 0;
+ int i;
+
+ if(GetAvailableCellNum(TxQueueObj) >= PRISM2_TX_FIDSTACKLEN_MAX) {
+ //printk("queue have full\n");
+ return -1;
+ }
+
+ for(i = 0; (i < PRISM2_TX_FIDSTACKLEN_MAX)&&(TxQueueObj.cells[i].fid != val); i++);
+ if(i >= PRISM2_TX_FIDSTACKLEN_MAX) {
+ printk("Illegal txfid for tx: %d \n", val);
+ return -1;
+ }
+ if(!TxQueueObj.cells[i].flag) {
+ TxQueueObj.cells[i].flag = 1;
+ AddAvailableCellNum(TxQueueObj);
+ }
+ return result;
+}
diff --git a/uClinux-2.4.20-uc1/drivers/net/wireless/Queue.h b/uClinux-2.4.20-uc1/drivers/net/wireless/Queue.h
new file mode 100755
index 0000000..adab295
--- /dev/null
+++ b/uClinux-2.4.20-uc1/drivers/net/wireless/Queue.h
@@ -0,0 +1,37 @@
+#ifndef __QUEUE_H__
+#define __QUEUE_H__
+
+#define UINT16 short
+#define INT16 short
+#define UINT8 unsigned char
+#define UINT32 unsigned int
+
+/*--------------fids queue-----------------*/
+typedef struct prism_txfid_cell
+{
+ UINT8 flag; //whether in use
+ UINT16 fid; //fid value
+}txfid_cell;
+
+typedef struct prism_txfid_queue
+{
+ txfid_cell cells[PRISM2_TX_FIDSTACKLEN_MAX];
+ UINT8 capability; //queue size
+}Queue_txfid;
+/*-------------fid queue operations--------------*/
+#define GetAvailableCellNum(x) (x.capability)
+#define ReduceAvailableCellNum(x) (--(x.capability))
+#define AddAvailableCellNum(x) (++(x.capability))
+
+
+/*-----------------function phototype----------------*/
+/* private txfid queue function, for interval use */
+INT16 Init_Queue();
+/* Dump for debuging queue */
+void Queue_dump();
+/* public txfid queue function, for geting a tx fid */
+INT16 Get_txfid();
+/* public txfid queue function, for puting a tx fid */
+INT16 Put_txfid(UINT16 val);
+
+#endif
diff --git a/uClinux-2.4.20-uc1/drivers/net/wireless/W90N745Prism.c b/uClinux-2.4.20-uc1/drivers/net/wireless/W90N745Prism.c
new file mode 100755
index 0000000..de76f6d
--- /dev/null
+++ b/uClinux-2.4.20-uc1/drivers/net/wireless/W90N745Prism.c
@@ -0,0 +1,998 @@
+/*-------------------------------------------------------------------------------*/
+/* Wireless driver for winbond W90N745 */
+/* version 1.0.2 (used only for Station) */
+/* ------------------------------------------------------------------------------*/
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/pagemap.h>
+#include <linux/vmalloc.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+
+#include "W90N745Prism.h"
+/* tx buffer queue, you can replace it as what you designed */
+#include "Queue.h"
+
+
+
+extern char PRISM_DesireSSID_DEFAULT[];
+extern char PRISM_BSSID[];
+extern char PRISM_LLC[];
+extern unsigned char Mac_address[6];
+extern Queue_txfid TxQueueObj;
+/* Debug for now */
+extern UINT8 *DebugpBuffer;
+//#define PRSIM_DEBUG
+extern int nums;
+
+/* -------------------------all functions--------------------------- */
+
+/* Here handle the tx ,rx and other events*/
+void prism_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ UINT16 reg;
+ struct net_device *dev = (struct net_device *)dev_id;
+ struct w740prism_priv *priv;
+ UINT16 txfid;
+ int count = MAX_IRQLOOPS_PER_IRQ;
+ static int last_irq_jiffy = 0; // jiffies value the last time we were called
+ static int loops_this_jiffy = 0;
+
+ if (!dev /*paranoid*/ ) return;
+
+ /* Lock the device */
+ priv = (struct w740prism_priv *) dev->priv;
+
+ /* read the EvStat register for interrupt enabled events */
+ reg = READREG(PRISM_EVSTAT);
+
+#ifdef WDEBUG
+ //printk("Event: %x\n", reg);
+#endif
+ if (jiffies != last_irq_jiffy)
+ loops_this_jiffy = 0;
+ last_irq_jiffy = jiffies;
+
+ while(reg && count--) {
+ if (++loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY) {
+ printk("%s: IRQ handler is looping too much! Shutting down.\n",dev->name);
+ WRITEREG(PRISM_INTEN, 0);
+ break;
+ }
+
+ if(PRISM_EVSTAT_ISTICK(reg)) {
+ ; //printk("TICK\n");
+ }
+
+ if(PRISM_EVSTAT_ISWTERR(reg)) {
+#ifdef WDEBUG
+ printk("WTERR\n"); //It shoudn't occur.
+#endif
+ }
+
+ if(PRISM_EVSTAT_ISINFDROP(reg)) {
+ ; //printk("INFDROP\n");
+ }
+
+ if(PRISM_EVSTAT_ISINFO(reg)) {
+ //printk("INFO\n");
+ prism_info(dev);
+ }
+
+ if(PRISM_EVSTAT_ISRX(reg)) {
+ prism_rx(dev);
+ }
+
+ if(PRISM_EVSTAT_ISTXEXC(reg)) {
+// printk("txexc ");
+ prism_txexc();
+ }
+
+ if(PRISM_EVSTAT_ISTX(reg)) {
+ prism_tx(dev);
+ }
+
+ if(PRISM_EVSTAT_ISALLOC(reg)) {
+ txfid = READREG(PRISM_ALLOCFID);
+ if(Put_txfid(txfid) < 0)
+ {
+ ;
+ }
+ else {
+ netif_wake_queue(dev);
+ WRITEREG(PRISM_ALLOCFID, DUMMY_FID);
+ }
+ }
+ WRITEREG(PRISM_EVACK, reg);
+
+ reg = READREG(PRISM_EVSTAT);
+ }
+}
+
+
+/*------------------------------------------------------------------*/
+int prism_open(struct net_device *dev)
+{
+ int result = 0;
+ MOD_INC_USE_COUNT;
+ /* change the interupt source from high-level sensitive to low-level sensitive */
+ if(((struct w740prism_priv *)(dev->priv))->status < 0) {
+ result = prism_initmac(dev);
+ if(result >= 0)
+ ((struct w740prism_priv *)(dev->priv))->status = 0; //clean it
+ }
+ /* chanel 4 of IRQ2 */
+ if(request_irq(dev->irq, &prism_interrupt,SA_INTERRUPT,"",dev))
+ {
+ printk("W740 wireless driver register irq failed\n");
+ return -EAGAIN;
+ }
+
+ netif_start_queue(dev);
+#ifdef WDEBUG
+ printk("enable interrupt handle,:)\n");
+#endif
+
+ return result;
+}
+
+int prism_release(struct net_device *dev)
+{
+ MOD_DEC_USE_COUNT;
+ netif_stop_queue(dev);
+ free_irq(dev->irq,dev);
+ return 0;
+}
+
+int prism_config(struct net_device *dev, struct ifmap *map)
+{
+ if (dev->flags & IFF_UP) /* can't act on a running interface */
+ return -EBUSY;
+ return 0;
+}
+
+/* real receive function */
+void prism_rx(struct net_device *dev)
+{
+ int result = 0;
+ UINT16 rxfid, dataLen;
+ struct sk_buff *skb;
+ struct w740prism_priv *priv;
+ //prism_rx_frame_t
+
+ if(!dev)
+ {
+ printk("Null dev in rx\n");
+ return;
+ }
+ priv = (struct w740prism_priv *) dev->priv;
+
+ /* Get the RxFID */
+ rxfid = READREG(PRISM_RXFID);
+ /* Get the data length */
+ result = prism_copy_from_bap(IRQ_BAP, rxfid, 44, &dataLen, 2);
+ if (result) {
+ LOGPRINT;
+ goto fail_reset;
+ }
+
+ skb = dev_alloc_skb(dataLen+12-6 + 2);
+ if (!skb) {
+ LOGPRINT;
+ priv->stats.rx_dropped++;
+ return;
+ }
+
+ skb_reserve(skb, 2); // align IP on 16B boundary
+ skb_put(skb, dataLen + 6);
+ result = prism_copy_from_bap(IRQ_BAP, rxfid, 18, skb->data, 6);
+ if (result) {
+ LOGPRINT;
+ priv->stats.rx_dropped++;
+ dev_kfree_skb(skb);
+ goto fail_reset;
+ }
+ result = prism_copy_from_bap(IRQ_BAP, rxfid, 30, skb->data+6, 6);
+ if (result) {
+ LOGPRINT;
+ priv->stats.rx_dropped++;
+ dev_kfree_skb(skb);
+ goto fail_reset;
+ }
+
+ /* Get the 802.3 body */
+ result = prism_copy_from_bap(IRQ_BAP, rxfid, 66, skb->data+12, dataLen - 6);
+ if (result) {
+ LOGPRINT;
+ priv->stats.rx_dropped++;
+ dev_kfree_skb(skb);
+ LOGPRINT;
+ goto fail_reset;
+ }
+
+ /* Write metadata, and then pass to the receive level */
+ skb->dev = dev;
+ skb->protocol = eth_type_trans(skb, dev);
+ //skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */
+ priv->stats.rx_packets++;
+ priv->stats.rx_bytes += (dataLen+6);
+#ifdef WIRELESS_SPY
+ ;//prism_wireless_stat(dev, skb, &desc);
+#endif
+ //DEBUG("Receive a packet\n");
+ netif_rx(skb);
+ return;
+fail_reset:
+ netif_stop_queue(dev);
+ prism_reset(dev->priv);
+ netif_wake_queue(dev);
+ return;
+}
+
+int prism_info(struct net_device *dev)
+{
+ UINT16 infoid;
+ UINT16 len;
+ UINT16 infotype = 0;
+ UINT16 status = 0;
+ struct w740prism_priv *priv = (struct w740prism_priv *)dev->priv;
+
+ infoid = READREG(PRISM_INFOFID);
+// printk("infoid: %x\n", infoid);
+ infotype = Read_CT_InfoType(infoid, &len);
+ if(infotype == -1)
+ {
+ printk("Meet erro when reading info\n");
+ return -1;
+ }
+
+ switch(infotype)
+ {
+ case PRISM_INQ_TALLIES:
+ //DEBUG("%s: PRISM_INQ_TALLIES: len: %d\n", dev->name, len);
+
+ break;
+ case PRISM_INQ_SCAN:
+ DEBUG("%s: PRISM_INQ_SCAN: len:%d\n", dev->name, len);
+ get_scan_result(infoid, len, priv);
+ break;
+ case PRISM_INQ_LINKSTATUS:
+ DEBUG("%s: PRISM_INQ_LINKSTATUS: len: %d\n", dev->name, len);
+ Read_CT_InfoData(infoid, &status, len); //2 bytes
+ prism_lock(priv);
+ priv->status = status;
+ prism_unlock(priv);
+ DEBUG("%s: current link status: %x\n",dev->name, status);
+ break;
+ default:
+ DEBUG("%s: Unkown infotype: %x\n", dev->name, infotype);
+ return -1;
+ }
+
+ return 0;
+}
+
+#define PRSIM_DEBUG0
+#define PRSIM_DEBUG1
+/*
+ * Transmit a packet (called by the kernel)
+ */
+int prism_start_tx(struct sk_buff *skb, struct net_device *dev)
+{
+ int result = 0;
+
+ result = send_frame(dev, skb->data, skb->len);
+ if(!result)
+ {
+ dev_kfree_skb(skb);
+ return result;
+ }
+ return result;
+}
+
+/* interval transmit function */
+static int send_frame(struct net_device *dev ,unsigned char *data,int length)
+{
+ struct hermes_tx_descriptor txdesc;
+ UINT16 fid;
+ int result = 0;
+ int retrycount = 0;
+ UINT8 *pData;
+ UINT32 data_off, data_len, len;
+ struct ethhdr *eh;
+ struct header_struct hdr;
+ struct net_device_stats *stats = &(((struct w740prism_priv *) dev->priv)->stats);
+
+ //DEBUG("Send a packet\n");
+ /* check stop */
+ if (! netif_running(dev)) {
+ printk("%s: Tx on stopped device!\n",dev->name);
+ return 1;
+ }
+
+ /* check busy */
+ if (netif_queue_stopped(dev)) {
+ printk("%s: Tx while transmitter busy!\n", dev->name);
+ return 1;
+ }
+
+ prism_lock((struct w740prism_priv *)dev->priv);
+ disable_irq(dev->irq);
+ fid = Get_txfid();
+ enable_irq(dev->irq);
+ if((signed short)fid < 0) {
+ printk("%s: Tx on erro fid:%x\n", dev->name, fid);
+ goto fail_reset;
+ }
+ /* Length of the packet body */
+ /* FIXME: what if the skb is smaller than this? */
+ len = max_t(int,length - ETH_HLEN, ETH_ZLEN);
+
+ eh = (struct ethhdr *)data;
+
+ /* Build Tx frame structure */
+ /* Set up the control field */
+ memset(&txdesc, 0, sizeof(txdesc));
+
+ /* set the control to 802.11 */
+ txdesc.tx_control = cpu_to_le16(PRISM_TX_TXEX_SET(1) | PRISM_TX_TXOK_SET(1));
+ disable_irq(dev->irq);
+ result = prism_copy_to_bap(USER_BAP, fid, 0, &txdesc, sizeof(txdesc));
+ enable_irq(dev->irq);
+ if ( result ) {
+ printk("MAC tx copy_to_bap failed, %d\n", __LINE__);
+ if(result == -1)
+ goto fail_reset;
+ else
+ goto fail;
+ }
+
+ /* Encapsulate Ethernet-II frames */
+ if (ntohs(eh->h_proto) > 1500) { // Ethernet-II frame
+ data_len = len;
+ data_off = HERMES_802_3_OFFSET + sizeof(hdr);
+ pData = data + ETH_HLEN;
+
+ memcpy(hdr.dest, eh->h_dest, ETH_ALEN);
+ memcpy(hdr.src, eh->h_source, ETH_ALEN);
+
+ hdr.len = htons(data_len + ENCAPS_OVERHEAD);
+ /* 802.2 header */
+ memcpy(&hdr.dsap, &PRISM_LLC, sizeof(char)*6);
+ hdr.ethertype = eh->h_proto;
+ disable_irq(dev->irq);
+ result = prism_copy_to_bap(USER_BAP, fid, HERMES_802_3_OFFSET, &hdr, sizeof(hdr));
+ enable_irq(dev->irq);
+ if (result) {
+ printk("%s: Error %d writing packet header to BAP\n", dev->name, result);
+ if(result == -1)
+ goto fail_reset;
+ else
+ goto fail;
+ }
+ }
+ else {
+ data_len = len + ETH_HLEN;
+ data_off = HERMES_802_3_OFFSET;
+ pData = data;
+ }
+ disable_irq(dev->irq);
+ result = prism_copy_to_bap(USER_BAP, fid, data_off, pData, RUP_EVEN(data_len));
+ enable_irq(dev->irq);
+ if ( result ) {
+ printk("MAC tx copy_to_bap failed: %d\r\n", __LINE__);
+ goto fail;
+ }
+
+ /* Finally, we actually initiate the send */
+ if(GetAvailableCellNum(TxQueueObj) <= 0)
+ netif_stop_queue(dev);
+ retrycount = 4;
+retry:
+ /* Issue Tx command */
+ result = prism_cmd_transmit(1, fid);
+ if (result != 0) {
+ if(--retrycount > 0)
+ goto retry;
+ goto fail;
+ }
+ dev->trans_start = jiffies;
+ prism_unlock((struct w740prism_priv *)dev->priv);
+
+ return 0;
+fail_reset:
+ netif_stop_queue(dev);
+ prism_reset(dev->priv);
+ netif_wake_queue(dev);
+fail:
+ stats->tx_errors++;
+ disable_irq(dev->irq);
+ Put_txfid(fid);
+ enable_irq(dev->irq);
+ prism_unlock((struct w740prism_priv *)dev->priv);
+ return -1;
+
+}
+
+/* tx reponse function */
+int prism_tx(struct net_device *dev)
+{
+ UINT16 fid;
+ UINT16 status;
+ int result = 0;
+
+ fid = READREG(PRISM_TXCOMPLFID);
+ result = prism_copy_from_bap(IRQ_BAP, fid, 0, &status, sizeof(status));
+ if (result) {
+ printk("prism_tx:copy_from_bap failed\r\n");
+ return -1;
+ }
+ ((struct w740prism_priv *)dev->priv)->stats.tx_packets++;
+ return result; /* Our simple device can not fail */
+}
+
+/* tx timeout function, timeout is set in init() */
+void prism_tx_timeout (struct net_device *dev)
+{
+ printk("tx timeout. :(\n");
+ struct w740prism_priv *priv = (struct w740prism_priv *)dev->priv;
+ struct net_device_stats *stats = &priv->stats;
+ int err = 0;
+
+ printk("Tx timeout! Reset Device\n");
+
+ stats->tx_errors++;
+ err = prism_reset(priv);
+ if(err)
+ printk("Erro:%d on resetting Device:%s\n", err, dev->name);
+ else {
+ dev->trans_start = jiffies;
+ netif_wake_queue(dev);
+ }
+
+}
+
+/* device reset, nothing to say, :( */
+int prism_reset(struct w740prism_priv *priv)
+{
+ int err = 0;
+#ifdef WDEBUG
+ printk("prism_reset :( \n");
+#endif
+ spin_lock_bh(priv->lock);
+ disable_irq(priv->ndev->irq);
+ err = prism_reset_device(priv->ndev);
+ enable_irq(priv->ndev->irq);
+ spin_unlock_bh(priv->lock);
+ return err;
+}
+
+/* Device ioctl for setting wlan configuration */
+int prism_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ int err = 0;
+ struct iwreq *wrq = (struct iwreq *)rq;
+ int changed = 0;
+ struct w740prism_priv *priv = dev->priv;
+ DEBUG("cmd: %x,iwreq:%d\n", cmd,sizeof(struct iwreq));
+ switch (cmd) {
+ case SIOCGIWNAME:
+ DEBUG("%s: SIOCGIWNAME\n", dev->name);
+ strcpy(wrq->u.name, "IEEE 802.11b");
+ break;
+
+ case SIOCGIWAP:
+ DEBUG("%s: SIOCGIWAP\n", dev->name);
+ wrq->u.ap_addr.sa_family = ARPHRD_ETHER;
+// printk("mac buf addr: %x\n", wrq->u.ap_addr.sa_data);
+ err = prism_hw_get_bssid(dev, wrq->u.ap_addr.sa_data);
+ break;
+
+ case SIOCGIWRANGE:
+ DEBUG("%s: SIOCGIWRANGE\n", dev->name);
+ break;
+
+ case SIOCSIWMODE:
+ DEBUG("%s: SIOCSIWMODE\n", dev->name);
+ prism_lock(priv);
+ DEBUG("MOD: %x\n", wrq->u.mode);
+ switch (wrq->u.mode) {
+ case IW_MODE_ADHOC:
+ case IW_MODE_INFRA:
+ priv->iw_mode = wrq->u.mode;
+ changed = 1;
+ break;
+
+ default:
+ err = -EINVAL;
+ break;
+ }
+ set_port_type(priv);
+ prism_unlock(priv);
+ break;
+
+ case SIOCGIWMODE:
+ DEBUG("%s: SIOCGIWMODE\n", dev->name);
+ prism_lock(priv);
+ wrq->u.mode = priv->iw_mode;
+ prism_unlock(priv);
+ break;
+
+ case SIOCSIWENCODE:
+ DEBUG("%s: SIOCSIWENCODE\n", dev->name);
+
+ err = prism_ioctl_setiwencode(dev, &wrq->u.encoding);
+ if (! err)
+ changed = 1;
+
+ break;
+
+ case SIOCGIWENCODE:
+ DEBUG("%s: SIOCGIWENCODE\n", dev->name);
+ err = prism_ioctl_getiwencode(dev, &wrq->u.encoding);
+ break;
+
+ case SIOCSIWESSID:
+ DEBUG("%s: SIOCSIWESSID\n", dev->name);
+
+ err = prism_ioctl_setessid(dev, &wrq->u.essid);
+ if (! err)
+ changed = 1;
+
+ break;
+
+ case SIOCGIWESSID:
+ DEBUG("%s: SIOCGIWESSID\n", dev->name);
+ DEBUG("k wrq: %x\n", wrq);
+ err = prism_ioctl_getessid(dev, &wrq->u.essid);
+
+ break;
+
+ case SIOCSIWNICKN:
+ DEBUG("%s: SIOCSIWNICKN\n", dev->name);
+ break;
+
+ case SIOCGIWNICKN:
+ DEBUG("%s: SIOCGIWNICKN\n", dev->name);
+ break;
+
+ case SIOCGIWFREQ:
+ DEBUG("%s: SIOCGIWFREQ\n", dev->name);
+ err = prism_hw_get_freq(dev->priv);
+ DEBUG("%d: %d\n", __LINE__, err);
+ if(err >= 0)
+ wrq->u.freq.m = err;
+ else
+#if 1
+ wrq->u.freq.m = 1; //default to 1
+#else
+ wrq->u.freq.m = err;
+#endif
+// printk("freq: %x, %d\n", wrq->u.freq.m, __LINE__);
+ wrq->u.freq.e = 0;
+ break;
+
+ case SIOCSIWFREQ:
+ DEBUG("%s: SIOCSIWFREQ\n", dev->name);
+ err = prism_ioctl_setfreq(dev, &wrq->u.freq);
+ if (! err)
+ changed = 1;
+ break;
+
+ case SIOCGIWSENS:
+ DEBUG("%s: SIOCGIWSENS\n", dev->name);
+ err = prism_ioctl_getsens(dev, &wrq->u.sens);
+ break;
+
+ case SIOCSIWSENS:
+ DEBUG("%s: SIOCSIWSENS\n", dev->name);
+ err = prism_ioctl_setsens(dev, &wrq->u.sens);
+ if(!err)
+ changed = 1;
+ break;
+
+ case SIOCGIWRTS:
+ DEBUG("%s: SIOCGIWRTS\n", dev->name);
+ wrq->u.rts.value =((struct w740prism_priv *)(dev->priv))->rts_thresh;
+ wrq->u.rts.disabled = (wrq->u.rts.value == 2347);
+ wrq->u.rts.fixed = 1;
+ break;
+
+ case SIOCSIWRTS:
+ DEBUG("%s: SIOCSIWRTS\n", dev->name);
+ err = prism_ioctl_setrts(dev, &wrq->u.rts);
+ if( !err )
+ changed = 1;
+ break;
+
+ case SIOCSIWFRAG:
+ DEBUG("%s: SIOCSIWFRAG\n", dev->name);
+ break;
+
+ case SIOCGIWFRAG:
+ DEBUG("%s: SIOCGIWFRAG\n", dev->name);
+ break;
+
+ case SIOCSIWRATE:
+ DEBUG("%s: SIOCSIWRATE\n", dev->name);
+ err = prism_ioctl_setiwrate(dev, &wrq->u.bitrate);
+ if (! err)
+ changed = 1;
+ break;
+
+ case SIOCGIWRATE:
+ DEBUG("%s: SIOCGIWRATE\n", dev->name);
+ err = prism_ioctl_getiwrate(dev, &wrq->u.bitrate);
+ break;
+
+ case SIOCSIWPOWER:
+ DEBUG("%s: SIOCSIWPOWER\n", dev->name);
+ err = prism_ioctl_setpower(dev, &wrq->u.power);
+ if(!err)
+ changed = 1;
+ break;
+
+ case SIOCGIWPOWER:
+ DEBUG("%s: SIOCGIWPOWER\n", dev->name);
+ err = prism_ioctl_getpower(dev, &wrq->u.power);
+ break;
+
+ case SIOCGIWTXPOW:
+ DEBUG("%s: SIOCGIWTXPOW\n", dev->name);
+ /* The card only supports one tx power, so this is easy */
+ break;
+
+#if WIRELESS_EXT > 10
+ case SIOCSIWRETRY:
+ DEBUG("%s: SIOCSIWRETRY\n", dev->name);
+ break;
+
+ case SIOCGIWRETRY:
+ DEBUG("%s: SIOCGIWRETRY\n", dev->name);
+ break;
+#endif /* WIRELESS_EXT > 10 */
+
+ case SIOCSIWSPY:
+ DEBUG("%s: SIOCSIWSPY\n", dev->name);
+ err = prism_ioctl_setspy(dev, &wrq->u.data);
+ break;
+
+ case SIOCGIWSPY:
+ DEBUG("%s: SIOCGIWSPY\n", dev->name);
+ err = prism_ioctl_getspy(dev, &wrq->u.data);
+ break;
+
+ case SIOCGIWAPLIST:
+ DEBUG("%s: SIOCGIWAPLIST\n", dev->name);
+ err = prism_ioctl_getaplist(dev, &wrq->u.data);
+ break;
+
+ case SIOCGIWPRIV:
+ DEBUG("%s: SIOCGIWPRIV\n", dev->name);
+#if 0
+ if (wrq->u.data.pointer) {
+ struct iw_priv_args privtab[] = {
+ { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" },
+ { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" },
+ { SIOCIWFIRSTPRIV + 0x2,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0, "set_port3" },
+ { SIOCIWFIRSTPRIV + 0x3, 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "get_port3" },
+ { SIOCIWFIRSTPRIV + 0x4,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0, "set_preamble" },
+ { SIOCIWFIRSTPRIV + 0x5, 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "get_preamble" },
+ { SIOCIWFIRSTPRIV + 0x6,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0, "set_ibssport" },
+ { SIOCIWFIRSTPRIV + 0x7, 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "get_ibssport" }
+ };
+
+ err = verify_area(VERIFY_WRITE, wrq->u.data.pointer, sizeof(privtab));
+ if (err)
+ break;
+
+ wrq->u.data.length = sizeof(privtab) / sizeof(privtab[0]);
+ if (copy_to_user(wrq->u.data.pointer, privtab, sizeof(privtab)))
+ err = -EFAULT;
+ }
+#endif
+ break;
+
+ case SIOCIWFIRSTPRIV + 0x0: /* force_reset */
+ case SIOCIWFIRSTPRIV + 0x1: /* card_reset */
+ DEBUG("%s: SIOCIWFIRSTPRIV + 0x0 (force_reset)\n",
+ dev->name);
+ netif_stop_queue(dev);
+ err = prism_reset(dev->priv);
+ netif_wake_queue(dev);
+ break;
+
+ case SIOCIWFIRSTPRIV + 0x2: /* set_port3 */
+ DEBUG("%s: SIOCIWFIRSTPRIV + 0x2 (set_port3)\n",
+ dev->name);
+ break;
+
+ case SIOCIWFIRSTPRIV + 0x3: /* get_port3 */
+ DEBUG("%s: SIOCIWFIRSTPRIV + 0x3 (get_port3)\n",
+ dev->name);
+ break;
+
+ case SIOCIWFIRSTPRIV + 0x4: /* set_preamble */
+ DEBUG("%s: SIOCIWFIRSTPRIV + 0x4 (set_preamble)\n",
+ dev->name);
+ break;
+
+ case SIOCIWFIRSTPRIV + 0x5: /* get_preamble */
+ DEBUG("%s: SIOCIWFIRSTPRIV + 0x5 (get_preamble)\n",
+ dev->name);
+
+ break;
+ case SIOCIWFIRSTPRIV + 0x6: /* set_ibssport */
+ DEBUG("%s: SIOCIWFIRSTPRIV + 0x6 (set_ibssport)\n",
+ dev->name);
+ break;
+
+ case SIOCIWFIRSTPRIV + 0x7: /* get_ibssport */
+ DEBUG("%s: SIOCIWFIRSTPRIV + 0x7 (get_ibssport)\n",
+ dev->name);
+ break;
+
+ case SIOCIWFIRSTPRIV + 0x8:
+ DEBUG("%s: SIOCGIWSTATS\n",
+ dev->name);
+ err = prism_ioctl_getstat(dev, wrq);
+// printk("%s: %d\n", __FILE__,__LINE__);
+ break;
+ case SIOCIWFIRSTPRIV + 0x9:
+ DEBUG("%s: SIOCGIWLINKSTATS\n",
+ dev->name);
+ err = prism_ioctl_getlinkstat(dev, &wrq->u.data);
+// printk("%s: %d\n", __FILE__,__LINE__);
+ break;
+ case SIOCSIWSCAN:
+ DEBUG("%s: SIOCSIWSCAN\n",
+ dev->name);
+ if(netif_running(dev)) {
+#ifdef SCAN_ENABLE
+ err = prism_ioctl_setscan(dev, &wrq->u.data);
+#endif
+ }
+ DEBUG("addr: %x\n", wrq);
+ break;
+
+ case SIOCGIWSCAN:
+ DEBUG("%s: SIOCGIWSCAN\n",
+ dev->name);
+ DEBUG("kwrq: %x\n", wrq);
+ break;
+
+
+ default:
+ printk("%s:No such cmd: %d\n", dev->name, cmd);
+ err = -EOPNOTSUPP;
+ }
+
+ if (! err && changed && netif_running(dev)) {
+ /* We need the xmit lock because it protects the
+ multicast list which orinoco_reset() reads */
+ spin_lock_bh(&dev->xmit_lock);
+
+ netif_stop_queue(dev);
+ err = prism_reset(dev->priv);
+ netif_wake_queue(dev);
+
+ spin_unlock_bh(&dev->xmit_lock);
+ if (err) {
+ /* Ouch ! What are we supposed to do ? */
+ printk("prism: Failed to set parameters on %s\n",
+ dev->name);
+ netif_device_detach(dev);
+ }
+ }
+
+
+
+
+ return 0;
+}
+
+/* device status */
+struct net_device_stats *prism_stats(struct net_device *dev)
+{
+ struct w740prism_priv *priv = (struct w740prism_priv *) dev->priv;
+ prism_lock(priv);
+ prism_unlock(priv);
+ return &priv->stats;
+}
+
+struct iw_statistics *prism_wireless_stats(struct net_device *dev)
+{
+ struct w740prism_priv *priv = (struct w740prism_priv *) dev->priv;
+ struct iw_statistics *wstats = &priv->wstats;
+ int err = 0;
+ int temp1, temp2;
+
+ prism_lock(priv);
+ if (priv->iw_mode == IW_MODE_ADHOC) {
+ memset(&wstats->qual, 0, sizeof(wstats->qual));
+ /* If a spy address is defined, we report stats of the
+ * first spy address - Jean II */
+ if (SPY_NUMBER(priv)) {
+ wstats->qual.qual = priv->spy_stat[0].qual;
+ wstats->qual.level = priv->spy_stat[0].level;
+ wstats->qual.noise = priv->spy_stat[0].noise;
+ wstats->qual.updated = priv->spy_stat[0].updated;
+ }
+ } else {
+ struct {
+ u16 qual, signal, noise;
+ } __attribute__ ((packed)) cq;
+
+ Read_RID_Config(PRISM_RID_COMMSQUALITY, &cq);
+
+ DEBUG("%s: Global stats = %X-%X-%X\n", dev->name,
+ cq.qual, cq.signal, cq.noise);
+ wstats->qual.qual = cq.qual;
+ wstats->qual.level = cq.signal;
+ wstats->qual.noise = cq.noise;
+ wstats->qual.updated = 7;
+ DEBUG("%s: Global stats = %X-%X-%X\n", dev->name,
+ cq.qual, cq.signal, cq.noise);
+
+ }
+ /* FIXME: Hmm.. seems a bit ugly, I wonder if there's a way to
+ do better - dgibson */
+ prism_cmd_inquiry(PRISM_INQ_TALLIES);
+
+ prism_unlock(priv);
+
+ if (err)
+ return NULL;
+
+ return wstats;
+}
+
+static void prism_set_multicast_list(struct net_device *dev)
+{
+}
+
+/* it shouldn't be useful, setting mac address from inside */
+static int prism_set_mac_address(struct net_device *dev, void *addr)
+{
+#if 0
+ struct w740_priv * priv=(struct w740_priv *)dev->priv;
+
+ if(netif_running(dev))
+ return -EBUSY;
+ memcpy(&priv->mac_address[0],addr+2,ETH_ALEN);
+
+ memcpy(dev->dev_addr,priv->mac_address,ETH_ALEN);
+ if(priv->which)
+ memcpy(w740_mac_address1,dev->dev_addr,ETH_ALEN);
+ else
+ memcpy(w740_mac_address0,dev->dev_addr,ETH_ALEN);
+
+ TRACE_ERROR("\nSet MaC Address %u:%u:%u:%u:%u:%u\n",
+ dev->dev_addr[0],\
+ dev->dev_addr[1],\
+ dev->dev_addr[2],\
+ dev->dev_addr[3],\
+ dev->dev_addr[4],\
+ dev->dev_addr[5]);
+
+ //w740_WriteReg(CAMEN,w740_ReadReg(CAMEN,priv->which) & ~1,priv->which);
+
+ return 0;
+#endif
+ return 0;
+}
+
+/* Driver init() */
+int prism_init(struct net_device *dev)
+{
+ int result = 0;
+
+ //ether_setup(dev); /* assign some of the fields *///??
+ dev->open = prism_open;
+ dev->stop = prism_release;
+ dev->set_config = prism_config;
+ dev->hard_start_xmit = prism_start_tx;
+ dev->do_ioctl = prism_ioctl;
+ dev->get_stats = prism_stats;
+ dev->get_wireless_stats = prism_wireless_stats;
+ //dev->change_mtu = snull_change_mtu;
+ //dev->rebuild_header = snull_rebuild_header;
+ //dev->hard_header = snull_header;
+ dev->irq = 4; //:)
+ dev->tx_timeout = prism_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+
+ /* keep the default flags, just add NOARP */
+ //dev->flags |= IFF_NOARP;
+ dev->hard_header_cache = NULL; /* Disable caching */
+ SET_MODULE_OWNER(dev);
+
+ /*
+ * Then, allocate the priv field. This encloses the statistics
+ * and a few private fields.
+ */
+ dev->priv = kmalloc(sizeof(struct w740prism_priv), GFP_KERNEL);
+ if (dev->priv == NULL)
+ return -ENOMEM;
+ memset(dev->priv, 0, sizeof(struct w740prism_priv));
+
+ result = prism_initmac(dev);
+ if(result<0)
+ return result;
+ memcpy(dev->dev_addr, ((struct w740prism_priv *) dev->priv)->mac_address, ETH_ALEN);
+ ((struct w740prism_priv *)(dev->priv))->ndev = dev;
+
+ spin_lock_init(& ((struct w740prism_priv *) dev->priv)->lock);
+ init_MUTEX_LOCKED(&((struct w740prism_priv *) dev->priv)->sema);
+
+ /* debug data */
+ DebugpBuffer = kmalloc(sizeof(UINT8)*6, GFP_KERNEL);
+ if (DebugpBuffer == NULL)
+ return -ENOMEM;
+
+ if(result < 0) /* init fail, and need try again */
+ {
+ ((struct w740prism_priv *)(dev->priv))->status = -1;
+ }
+
+ memcpy(((struct w740prism_priv *)(dev->priv))->desired_essid, "PC32WebCam", strlen("PC32WebCam")+1);
+ ether_setup(dev); /* assign some of the fields */
+
+// printk("address length: %d\n", dev->addr_len);
+
+ return (result>=0?0:-1);
+}
+
+/* Our device struct */
+struct net_device prism_dev =
+{
+ name: "wlan0",
+ init: prism_init, /* init function */
+};
+
+/* module init call function */
+int prism_init_module(void)
+{
+ int result = 0;
+ printk("Welcome wireless network! :)\n");
+ if ( (result = register_netdev(&prism_dev)) ) {
+ printk("prism: error %i registering device \"%s\"\n",
+ result, prism_dev.name);
+ return -ENODEV;
+ }
+#ifndef PRSIM_DEBUG
+ EXPORT_NO_SYMBOLS;
+#endif
+
+ return 0;
+}
+
+/* module cleanup function, our don't clean up in our system now */
+void prism_cleanup(void)
+{
+ kfree(prism_dev.priv);
+ unregister_netdev(&prism_dev);
+ return;
+}
+
+module_init(prism_init_module);
+module_exit(prism_cleanup);
diff --git a/uClinux-2.4.20-uc1/drivers/net/wireless/W90N745Prism.h b/uClinux-2.4.20-uc1/drivers/net/wireless/W90N745Prism.h
new file mode 100755
index 0000000..18130f1
--- /dev/null
+++ b/uClinux-2.4.20-uc1/drivers/net/wireless/W90N745Prism.h
@@ -0,0 +1,863 @@
+#ifndef __W90N745PRISM_H__
+#define __W90N745PRISM_H__
+
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/in.h>
+#include <linux/skbuff.h>
+#include <linux/wireless.h>
+
+#if LINUX_VERSION_CODE < 132116
+ #define SIOCSIWSCAN 0x8B18 /* trigger scanning */
+ #define SIOCGIWSCAN 0x8B19 /* get scanning results */
+#endif
+
+//#define WDEBUG
+
+#define UINT16 short
+#define INT16 short
+#define UINT8 unsigned char
+#define UINT32 unsigned int
+
+#define __WLAN_ATTRIB_PACK__ __attribute__ ((packed))
+
+/* read / write prism register macro */
+#define WRITEREG(reg, data) (*(volatile unsigned short *)(EBI_BASE + reg)) = data
+#define READREG(reg) *(volatile unsigned short *)(EBI_BASE + reg)
+
+// ASIC Address Definitions
+#define VPint *(volatile unsigned int *)
+#define VPshort *(volatile unsigned short *)
+#define VPchar *(volatile unsigned char *)
+
+// external I/O 2 control register
+#define EXT0CON_REG 0xFFF01018
+#define EXT1CON_REG 0xFFF0101C
+#define EXT2CON_REG 0xFFF01020
+
+// Special Register Start Address After System Reset
+#define EBI_BASE 0xC0800000 // on W90N745 board PCMCIA
+
+// Advanced Interrupt Controller Registers
+#define AIC_SCR_nIRQ0 (VPint(Base_Addr+0x00082008))
+#define AIC_SCR_nIRQ2 (VPint(Base_Addr+0x00082010))
+
+// MAC Interrupt Source
+#define nIRQ0 2
+#define nIRQ2 4
+
+#define DIAG_PATTERNA ((UINT16)0xaaaa)
+#define DIAG_PATTERNB ((UINT16)~0xaaaa)
+
+#define HERMES_MAGIC (0x7d1f)
+
+#define USER_BAP 0
+#define IRQ_BAP 1
+
+/* operation mode */
+#define IW_MODE_AUTO 0 /* Let the driver decides */
+#define IW_MODE_ADHOC 1 /* Single cell network */
+#define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */
+/*---- follow no support now -----*/
+#define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */
+#define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */
+#define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */
+
+/*------------------------------------------------------------------------*/
+/* PRISM MAC registers */
+/* Command/Status */
+/*------------------------------------------------------------------------*/
+#define PRISM_CMD 0x00
+#define PRISM_PARAM0 0x02
+#define PRISM_PARAM1 0x04
+#define PRISM_PARAM2 0x06
+#define PRISM_STATUS 0x08
+#define PRISM_RESP0 0x0A
+#define PRISM_RESP1 0x0C
+#define PRISM_RESP2 0x0E
+// FID Management
+#define PRISM_INFOFID 0x10
+#define PRISM_RXFID 0x20
+#define PRISM_ALLOCFID 0x22
+#define PRISM_TXCOMPLFID 0x24
+// BAP0
+#define PRISM_SELECT0 0x18
+#define PRISM_OFFSET0 0x1C
+#define PRISM_DATA0 0x36
+// BAP1
+#define PRISM_SELECT1 0x1A
+#define PRISM_OFFSET1 0x1E
+#define PRISM_DATA1 0x38
+// Event
+#define PRISM_EVSTAT 0x30
+#define PRISM_INTEN 0x32
+#define PRISM_EVACK 0x34
+// Control
+#define PRISM_CONTROL 0x14
+// Host Software
+#define PRISM_SWSUPPORT0 0x28
+#define PRISM_SWSUPPORT1 0x2A
+#define PRISM_SWSUPPORT2 0x2C
+// Auxiliary Port
+#define PRISM_AUXPAGE 0x3A
+#define PRISM_AUXOFFSET 0x3C
+#define PRISM_AUXDATA 0x3E
+
+// Command Code Constants
+// Controller Commands
+#define PRISM_CMDCODE_INIT (0x00)
+#define PRISM_CMDCODE_ENABLE (0x01)
+#define PRISM_CMDCODE_DISABLE (0x02)
+#define PRISM_CMDCODE_DIAG (0x03)
+
+// Buffer Mgmt Commands
+#define PRISM_CMDCODE_ALLOC (0x0A)
+#define PRISM_CMDCODE_TX (0x0B)
+
+// Regulate Commands
+#define PRISM_CMDCODE_NOTIFY (0x10)
+#define PRISM_CMDCODE_INQ (0x11)
+
+// Configure Commands
+#define PRISM_CMDCODE_ACCESS (0x21)
+#define PRISM_CMDCODE_DOWNLD (0x22)
+
+// Serial I/O Commands
+#define PRISM_CMDCODE_READMIF (0x30)
+#define PRISM_CMDCODE_WRITEMIF (0x31)
+
+/*--- Result Codes --------------------------*/
+#define PRISM_SUCCESS ((0x00))
+#define PRISM_CARD_FAIL ((0x01))
+#define PRISM_NO_BUFF ((0x05))
+#define PRISM_CMD_ERR ((0x7F))
+
+
+
+/*------------- Programming Modes ------------------------*/
+/* MODE 0: Disable programming */
+/* MODE 1: Enable volatile memory programming */
+/* MODE 2: Enable non-volatile memory programming */
+/* MODE 3: Program non-volatile memory section */
+/*--------------------------------------------------------*/
+#define PRISM_PROGMODE_DISABLE (0x00) //no used
+#define PRISM_PROGMODE_RAM (0x01) //no used
+#define PRISM_PROGMODE_NV (0x02) //no used
+#define PRISM_PROGMODE_NVWRITE (0x03) //no used
+
+/*------------------ Register Test/Get/Set Field macros ------------------------*/
+#define PRISM_CMD_ISBUSY(value) ((UINT16)(((UINT16)value) & 0x8000))
+#define PRISM_CMD_AINFO_GET(value) ((UINT16)(((UINT16)(value) & 0x7F00) >> 8))
+#define PRISM_CMD_AINFO_SET(value) ((UINT16)((UINT16)(value) << 8))
+#define PRISM_CMD_MACPORT_GET(value) ((UINT16)(PRISM_CMD_AINFO_GET((UINT16)(value) & 0x0700)))
+#define PRISM_CMD_MACPORT_SET(value) ((UINT16)PRISM_CMD_AINFO_SET(value))
+#define PRISM_CMD_ISRECL(value) ((UINT16)(PRISM_CMD_AINFO_GET((UINT16)(value) & 0x0100)))
+#define PRISM_CMD_RECL_SET(value) ((UINT16)PRISM_CMD_AINFO_SET(value))
+#define PRISM_CMD_ISWRITE(value) ((UINT16)(PRISM_CMD_AINFO_GET((UINT16)(value) & 0x0100)))
+#define PRISM_CMD_WRITE_SET(value) ((UINT16)PRISM_CMD_AINFO_SET((UINT16)value))
+#define PRISM_CMD_PROGMODE_GET(value) ((UINT16)(PRISM_CMD_AINFO_GET((UINT16)(value) & 0x0300)))
+#define PRISM_CMD_PROGMODE_SET(value) ((UINT16)PRISM_CMD_AINFO_SET((UINT16)value))
+#define PRISM_CMD_CMDCODE_GET(value) ((UINT16)(((UINT16)(value)) & 0x003F))
+#define PRISM_CMD_CMDCODE_SET(value) ((UINT16)(value))
+
+#define PRISM_STATUS_RESULT_GET(value) ((UINT16)((((UINT16)(value)) & 0x7F00) >> 8))
+#define PRISM_STATUS_RESULT_SET(value) (((UINT16)(value)) << 8)
+#define PRISM_STATUS_CMDCODE_GET(value) (((UINT16)(value)) & 0x003F)
+#define PRISM_STATUS_CMDCODE_SET(value) ((UINT16)(value))
+
+#define PRISM_OFFSET_ISBUSY(value) ((UINT16)(((UINT16)(value)) & 0x8000))
+#define PRISM_OFFSET_ISERR(value) ((UINT16)(((UINT16)(value)) & 0x4000))
+#define PRISM_OFFSET_DATAOFF_GET(value) ((UINT16)(((UINT16)(value)) & 0x0FFE))
+#define PRISM_OFFSET_DATAOFF_SET(value) ((UINT16)(value))
+
+#define PRISM_EVSTAT_ISTICK(value) ((UINT16)(((UINT16)(value)) & 0x8000))
+#define PRISM_EVSTAT_ISWTERR(value) ((UINT16)(((UINT16)(value)) & 0x4000))
+#define PRISM_EVSTAT_ISINFDROP(value) ((UINT16)(((UINT16)(value)) & 0x2000))
+#define PRISM_EVSTAT_ISINFO(value) ((UINT16)(((UINT16)(value)) & 0x0080))
+#define PRISM_EVSTAT_ISDTIM(value) ((UINT16)(((UINT16)(value)) & 0x0020))
+#define PRISM_EVSTAT_ISCMD(value) ((UINT16)(((UINT16)(value)) & 0x0010))
+#define PRISM_EVSTAT_ISALLOC(value) ((UINT16)(((UINT16)(value)) & 0x0008))
+#define PRISM_EVSTAT_ISTXEXC(value) ((UINT16)(((UINT16)(value)) & 0x0004))
+#define PRISM_EVSTAT_ISTX(value) ((UINT16)(((UINT16)(value)) & 0x0002))
+#define PRISM_EVSTAT_ISRX(value) ((UINT16)(((UINT16)(value)) & 0x0001))
+
+#define PRISM_EVENT_MASK ((UINT16)0xFFFF)
+#define PRISM_INTEN_ENABLEBITS ((UINT16)0x008F)
+#define PRISM_INTEN_DISABLE ((UINT16)0x0000)
+
+#define PRISM_INTEN_ISTICK(value) ((UINT16)(((UINT16)(value)) & 0x8000))
+#define PRISM_INTEN_TICK_SET(value) ((UINT16)(((UINT16)(value)) << 15))
+#define PRISM_INTEN_ISWTERR(value) ((UINT16)(((UINT16)(value)) & 0x4000))
+#define PRISM_INTEN_WTERR_SET(value) ((UINT16)(((UINT16)(value)) << 14))
+#define PRISM_INTEN_ISINFDROP(value) ((UINT16)(((UINT16)(value)) & 0x2000))
+#define PRISM_INTEN_INFDROP_SET(value) ((UINT16)(((UINT16)(value)) << 13))
+#define PRISM_INTEN_ISINFO(value) ((UINT16)(((UINT16)(value)) & 0x0080))
+#define PRISM_INTEN_INFO_SET(value) ((UINT16)(((UINT16)(value)) << 7))
+#define PRISM_INTEN_ISDTIM(value) ((UINT16)(((UINT16)(value)) & 0x0020))
+#define PRISM_INTEN_DTIM_SET(value) ((UINT16)(((UINT16)(value)) << 5))
+#define PRISM_INTEN_ISCMD(value) ((UINT16)(((UINT16)(value)) & 0x0010))
+#define PRISM_INTEN_CMD_SET(value) ((UINT16)(((UINT16)(value)) << 4))
+#define PRISM_INTEN_ISALLOC(value) ((UINT16)(((UINT16)(value)) & 0x0008))
+#define PRISM_INTEN_ALLOC_SET(value) ((UINT16)(((UINT16)(value)) << 3))
+#define PRISM_INTEN_ISTXEXC(value) ((UINT16)(((UINT16)(value)) & 0x0004))
+#define PRISM_INTEN_TXEXC_SET(value) ((UINT16)(((UINT16)(value)) << 2))
+#define PRISM_INTEN_ISTX(value) ((UINT16)(((UINT16)(value)) & 0x0002))
+#define PRISM_INTEN_TX_SET(value) ((UINT16)(((UINT16)(value)) << 1))
+#define PRISM_INTEN_ISRX(value) ((UINT16)(((UINT16)(value)) & 0x0001))
+#define PRISM_INTEN_RX_SET(value) ((UINT16)(((UINT16)(value)) << 0))
+
+#define PRISM_EVACK_ISTICK(value) ((UINT16)(((UINT16)(value)) & 0x8000))
+#define PRISM_EVACK_TICK_SET(value) ((UINT16)(((UINT16)(value)) << 15))
+#define PRISM_EVACK_ISWTERR(value) ((UINT16)(((UINT16)(value)) & 0x4000))
+#define PRISM_EVACK_WTERR_SET(value) ((UINT16)(((UINT16)(value)) << 14))
+#define PRISM_EVACK_ISINFDROP(value) ((UINT16)(((UINT16)(value)) & 0x2000))
+#define PRISM_EVACK_INFDROP_SET(value) ((UINT16)(((UINT16)(value)) << 13))
+#define PRISM_EVACK_ISINFO(value) ((UINT16)(((UINT16)(value)) & 0x0080))
+#define PRISM_EVACK_INFO_SET(value) ((UINT16)(((UINT16)(value)) << 7))
+#define PRISM_EVACK_ISDTIM(value) ((UINT16)(((UINT16)(value)) & 0x0020))
+#define PRISM_EVACK_DTIM_SET(value) ((UINT16)(((UINT16)(value)) << 5))
+#define PRISM_EVACK_ISCMD(value) ((UINT16)(((UINT16)(value)) & 0x0010))
+#define PRISM_EVACK_CMD_SET(value) ((UINT16)(((UINT16)(value)) << 4))
+#define PRISM_EVACK_ISALLOC(value) ((UINT16)(((UINT16)(value)) & 0x0008))
+#define PRISM_EVACK_ALLOC_SET(value) ((UINT16)(((UINT16)(value)) << 3))
+#define PRISM_EVACK_ISTXEXC(value) ((UINT16)(((UINT16)(value)) & 0x0004))
+#define PRISM_EVACK_TXEXC_SET(value) ((UINT16)(((UINT16)(value)) << 2))
+#define PRISM_EVACK_ISTX(value) ((UINT16)(((UINT16)(value)) & 0x0002))
+#define PRISM_EVACK_TX_SET(value) ((UINT16)(((UINT16)(value)) << 1))
+#define PRISM_EVACK_ISRX(value) ((UINT16)(((UINT16)(value)) & 0x0001))
+#define PRISM_EVACK_RX_SET(value) ((UINT16)(((UINT16)(value)) << 0))
+
+#define PRISM_CONTROL_AUXEN_SET(value) ((UINT16)(((UINT16)(value)) << 14))
+#define PRISM_CONTROL_AUXEN_GET(value) ((UINT16)(((UINT16)(value)) >> 14))
+
+/* Communication Tallies' inquiry constants and data types */
+
+#define PRISM_INQ_TALLIES (0xF100)
+#define PRISM_INQ_SCAN (0xF101)
+#define PRISM_INQ_LINKSTATUS (0xF200)
+#define PRISM_INQ_ASSOCIATIONSTATUS (0xF201)
+/*-------------------- Record ID Constants ----------------------------------------*/
+
+/*----------------------------------------------------------------------------------*/
+/* Configuration RIDs: Network Parameters, Static Configuration Entities */
+/*----------------------------------------------------------------------------------*/
+#define PRISM_RID_CNFPORTTYPE ((UINT16)0xFC00)
+#define PRISM_RID_CNFPORTTYPE_LEN ((UINT16)2)
+#define PRISM_RID_CNFOWNMACADDR ((UINT16)0xFC01)
+#define PRISM_RID_CNFOWNMACADDR_LEN ((UINT16)6)
+#define PRISM_RID_CNFDESIREDSSID ((UINT16)0xFC02)
+#define PRISM_RID_CNFDESIREDSSID_LEN ((UINT16)34)
+#define PRISM_RID_CNFOWNCHANNEL ((UINT16)0xFC03)
+#define PRISM_RID_CNFOWNCHANNEL_LEN ((UINT16)2)
+#define PRISM_RID_CNFOWNSSID ((UINT16)0xFC04)
+#define PRISM_RID_CNFOWNSSID_LEN ((UINT16)34)
+#define PRISM_RID_CNFSYSTEMSCALE ((UINT16)0xFC06)
+#define PRISM_RID_CNFSYSTEMSCALE_LEN ((UINT16)2)
+#define PRISM_RID_CNFMAXDATALEN ((UINT16)0xFC07)
+#define PRISM_RID_CNFMAXDATALEN_LEN ((UINT16)2)
+#define PRISM_RID_CNFPMENABLED ((UINT16)0xFC09)
+#define PRISM_RID_CNFPMENABLED_LEN ((UINT16)2)
+#define PRISM_RID_CNFMULTICASTRECEIVE ((UINT16)0xFC0B)
+#define PRISM_RID_CNFMULTICASTRECEIVE_LEN ((UINT16)2)
+#define PRISM_RID_CNFMAXSLEEPDURATION ((UINT16)0xFC0C)
+#define PRISM_RID_CNFMAXSLEEPDURATION_LEN ((UINT16)2)
+#define PRISM_RID_CNFPMHOLDOVERDURATION ((UINT16)0xFC0D)
+#define PRISM_RID_CNFPMHOLDOVERDURATION_LEN ((UINT16)2)
+#define PRISM_RID_CNFWEPDEFAULTKEYID ((UINT16)0xFC23)
+#define PRISM_RID_CNFWEPDEFAULTKEYID_LEN ((UINT16)sizeof(UINT16))
+#define PRISM_RID_CNFDEFAULTKEY0 ((UINT16)0xFC24)
+#define PRISM_RID_CNFDEFAULTKEY1 ((UINT16)0xFC25)
+#define PRISM_RID_CNFDEFAULTKEY2 ((UINT16)0xFC26)
+#define PRISM_RID_CNFDEFAULTKEY3 ((UINT16)0xFC27)
+#define PRISM_RID_CNFWEPFLAGS ((UINT16)0xFC28)
+#define PRISM_RID_CNFWEPFLAGS_LEN ((UINT16)sizeof(UINT16))
+#define PRISM_RID_CNFAUTHENTICATION ((UINT16)0xFC2A)
+#define PRISM_RID_CNFAUTHENTICATION_LEN ((UINT16)sizeof(UINT16))
+#define PRISM_RID_CNFBASICRATES ((UINT16)0xFCB3)
+#define PRISM_RID_CNFBASICRATES_LEN ((UINT16)2)
+#define PRISM_RID_CNFSUPPRATES ((UINT16)0xFCB4)
+#define PRISM_RID_CNFSUPPRATES_LEN ((UINT16)2)
+#define PRISM_RID_TXRATECNTL0 ((UINT16)0xFC9E)
+#define PRISM_RID_TXRATECNTL0_LEN ((UINT16)2)
+
+#define PRISM_RID_CNFBEACONINTERVAL ((UINT16)0xFC33)
+#define PRISM_RID_CNFBEACONINTERVAL_LEN ((UINT16)2)
+#define PRISM_RID_CNFOWNDTIMPERIOD ((UINT16)0xFC10)
+#define PRISM_RID_CNFOWNDTIMPERIOD_LEN ((UINT16)2)
+
+
+/* Power management flags available (along with the value, if any) */
+#define IW_POWER_ON 0x0000 /* No details... */
+#define IW_POWER_TYPE 0xF000 /* Type of parameter */
+#define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */
+#define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */
+#define IW_POWER_MODE 0x0F00 /* Power Management mode */
+#define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */
+#define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */
+#define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */
+#define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */
+#define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */
+#define IW_POWER_MODIFIER 0x000F /* Modify a parameter */
+#define IW_POWER_MIN 0x0001 /* Value is a minimum */
+#define IW_POWER_MAX 0x0002 /* Value is a maximum */
+#define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */
+
+/*--------------------------------------------------------------------------------*/
+/* Configuration RIDs: Network Parameters, Dynamic Configuration Entities */
+/*--------------------------------------------------------------------------------*/
+#define PRISM_RID_GROUPADDRESSES ((UINT16)0xFC80)
+#define PRISM_RID_NFCREATEIBSS ((UINT16)0xFC81)
+#define PRISM_RID_NFCREATEIBSS_LEN ((UINT16)2)
+#define PRISM_RID_RTSTHRESHOLD ((UINT16)0xFC83)
+#define PRISM_RID_RTSTHRESHOLD_LEN ((UINT16)2)
+#define PRISM_RID_TXRATECNTL ((UINT16)0xFC84)
+#define PRISM_RID_TXRATECNTL_LEN ((UINT16)2)
+
+#define PRISM_RID_PROMISCUOUS ((UINT16)0xFC85)
+#define PRISM_RID_PROMISCUOUS_LEN ((UINT16)2)
+#define PRISM_Promoscuous_Enable ((UINT16)0x0001)
+#define PRISM_Promoscuous_Disable ((UINT16)0x0000)
+
+
+/*------------------------------------------------------------------------------*/
+/* Information RIDs: NIC Information */
+/*------------------------------------------------------------------------------*/
+#define PRSIM_NIC_DOWNLOADBUFFER ((UINT16)0xFD01)
+#define PRISM_RID_CIS ((UINT16)0xFD13)
+#define PRISM_RID_CIS_LEN ((UINT16)480)
+
+
+/*-------------------------------------------------------------------------*/
+/* Information RIDs: MAC Information */
+/*-------------------------------------------------------------------------*/
+#define PRISM_RID_PORTSTATUS ((UINT16)0xFD40)
+#define PRISM_RID_PORTSTATUS_LEN ((UINT16)0)
+#define PRISM_RID_CURRENTSSID ((UINT16)0xFD41)
+#define PRISM_RID_CURRENTSSID_LEN ((UINT16)34)
+#define PRISM_RID_CURRENTBSSID ((UINT16)0xFD42)
+#define PRISM_RID_CURRENTBSSID_LEN ((UINT16)6)
+#define PRISM_RID_COMMSQUALITY ((UINT16)0xFD43)
+#define PRISM_RID_COMMSQUALITY_LEN ((UINT16)6)
+#define PRISM_RID_CURRENTTXRATE ((UINT16)0xFD44)
+#define PRISM_RID_CURRENTTXRATE_LEN ((UINT16)2)
+#define PRISM_RID_OWNMACADDRESS ((UINT16)0xFD86)
+#define PRISM_RID_SCANRESULT ((UINT16)0xFD88)
+/*------------------------------------------------------------------------------*/
+/* Information RIDs: Modem information */
+/*------------------------------------------------------------------------------*/
+#define PRISM_RID_CURRENTCHANNEL ((UINT16)0xFDC1) /* used */
+
+/*----------------------------------------------------------------------*/
+/* Information Frames */
+/*----------------------------------------------------------------------*/
+#define PRISM_CT_LINKSTATUS ((UINT16)0xF200)
+#define PRISM_CT_SCANRESUTL ((UINT16)0xF101)
+
+/*--------------------------------------------------------------------------------------*/
+/* Communication Frames: Test/Get/Set Field Values for Transmit Frames */
+/*--------------------------------------------------------------------------------------*/
+/*--------------- Status Field ---------------*/
+#define PRISM_TXSTATUS_ISFORMERR(v) ((UINT16)(((UINT16)(v)) & 0x0008))
+#define PRISM_TXSTATUS_ISDISCON(v) ((UINT16)(((UINT16)(v)) & 0x0004))
+#define PRISM_TXSTATUS_ISAGEDERR(v) ((UINT16)(((UINT16)(v)) & 0x0002))
+#define PRISM_TXSTATUS_ISRETRYERR(v) ((UINT16)(((UINT16)(v)) & 0x0001))
+
+#define PRISM_TX_GET(v,m,s) ((((UINT16)(v))&((UINT16)(m)))>>((UINT16)(s)))
+#define PRISM_TX_SET(v,m,s) ((((UINT16)(v))<<((UINT16)(s)))&((UINT16)(m)))
+
+#define PRISM_TX_MACPORT_GET(v) PRISM_TX_GET(v, 0x0700, 8)
+#define PRISM_TX_MACPORT_SET(v) PRISM_TX_SET(v, 0x0700, 8)
+#define PRISM_TX_NOENCRYPT_GET(v) PRISM_TX_GET(v, 0x0080, 7)
+#define PRISM_TX_NOENCRYPT_SET(v) PRISM_TX_SET(v, 0x0080, 7)
+#define PRISM_TX_RETRYSTRAT_GET(v) PRISM_TX_GET(v, 0x0020, 5)
+#define PRISM_TX_RETRYSTRAT_SET(v) PRISM_TX_SET(v, 0x0020, 5)
+#define PRISM_TX_STRUCTYPE_GET(v) PRISM_TX_GET(v, 0x0018, 3)
+#define PRISM_TX_STRUCTYPE_SET(v) PRISM_TX_SET(v, 0x0018, 3)
+#define PRISM_TX_TXEX_GET(v) PRISM_TX_GET(v, 0x0004, 2)
+#define PRISM_TX_TXEX_SET(v) PRISM_TX_SET(v, 0x0004, 2)
+#define PRISM_TX_TXOK_GET(v) PRISM_TX_GET(v, 0x0002, 1)
+#define PRISM_TX_TXOK_SET(v) PRISM_TX_SET(v, 0x0002, 1)
+
+
+/*----------------------------------------------------------------------*/
+/* FRAME DESCRIPTORS AND FRAME STRUCTURES */
+/* FRAME DESCRIPTORS: Offsets */
+/*----------------------------------------------------------------------*/
+/*-------------Control Info---------------*/
+#define PRISM_FD_STATUS ((UINT16)0x00)
+#define PRISM_FD_SWSUPPORT ((UINT16)0x03)
+#define PRISM_FD_SILENCE ((UINT16)0x03)
+#define PRISM_FD_SIGNAL ((UINT16)0x03)
+#define PRISM_FD_RATE ((UINT16)0x04)
+#define PRISM_FD_TXRATE ((UINT16)0x05)
+#define PRISM_FD_RETRYCOUNT ((UINT16)0x05)
+#define PRISM_FD_TXCONTROL ((UINT16)0x06)
+
+/*-------------802.11 Header---------------*/
+#define PRISM_FD_FRAMECONTROL ((UINT16)0x07)
+#define PRISM_FD_DURATIONID ((UINT16)0x08)
+#define PRISM_FD_ADDRESS1 ((UINT16)0x09)
+#define PRISM_FD_ADDRESS2 ((UINT16)0x12)
+#define PRISM_FD_ADDRESS3 ((UINT16)0x15)
+#define PRISM_FD_SEQCONTROL ((UINT16)0x18)
+#define PRISM_FD_ADDRESS4 ((UINT16)0x19)
+#define PRISM_FD_DATALEN ((UINT16)0x22)
+
+/*--------------802.3 Header----------------*/
+#define PRISM_FD_DESTADDRESS ((UINT16)0x23)
+#define PRISM_FD_SRCADDRESS ((UINT16)0x26)
+#define PRISM_FD_DATALENGTH ((UINT16)0x29)
+
+/*--------------prism defines----------------*/
+#define PRISM2_TX_FIDSTACKLEN_MAX 6
+#define PRISM2_FIDSTACKLEN_MAX 16
+
+#define HERMES_EV_CMD (0x0010)
+#define HERMES_STATUS_RESULT (0x7f00)
+
+#define TX_TIMEOUT (HZ)
+
+/*-------------------------for encode---------------------------------*/
+/* Maximum number of size of encoding token available
+ * they are listed in the range structure */
+#define IW_MAX_ENCODING_SIZES 8
+
+/* Maximum size of the encoding token in bytes */
+#define IW_ENCODING_TOKEN_MAX 32 /* 256 bits (for now) */
+
+/* Flags for encoding (along with the token) */
+#define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */
+#define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */
+#define IW_ENCODE_MODE 0xF000 /* Modes defined below */
+#define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */
+#define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */
+#define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */
+#define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */
+#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */
+
+
+/*---------------------------------------------------------------------------*/
+/* Communication Frame: Transmit Frame Structure */
+/*---------------------------------------------------------------------------*/
+struct hermes_tx_descriptor {
+ u16 status;
+ u16 reserved1;
+ u16 reserved2;
+ u32 sw_support;
+ u8 retry_count;
+ u8 tx_rate;
+ u16 tx_control;
+} __attribute__ ((packed));
+
+struct header_struct {
+ /* 802.3 */
+ u8 dest[ETH_ALEN];
+ u8 src[ETH_ALEN];
+ u16 len;
+ /* 802.2 */
+ u8 dsap;
+ u8 ssap;
+ u8 ctrl;
+ /* SNAP */
+ u8 oui[3];
+ u16 ethertype;
+} __attribute__ ((packed));
+
+struct prism_tx_frame
+{
+ UINT16 status;
+ UINT16 reserved1;
+ UINT16 reserved2;
+ UINT16 sw_support0;
+ UINT16 sw_support1;
+ UINT16 reserved3;
+ UINT16 tx_control;
+
+ /*-- 802.11 Header Information --*/
+
+ UINT16 frame_control;
+ UINT16 duration_id;
+ UINT8 address1[6];
+ UINT8 address2[6];
+ UINT8 address3[6];
+ UINT16 sequence_control;
+ UINT8 address4[6];
+ UINT16 data_len; /* little endian format */
+
+ /*-- 802.3 Header Information --*/
+
+ UINT8 dest_addr[6];
+ UINT8 src_addr[6];
+ UINT16 data_length; /* big endian format */
+ UINT8 llc_data[6];
+} __attribute__ ((packed));;
+
+typedef struct prism_tx_frame prism_tx_frame_t;
+
+/*----------------------------------------------------------------*/
+/* Communication Frame: Receive Frame Structure */
+/*----------------------------------------------------------------*/
+struct prism_rx_frame
+{
+ /*-- MAC rx descriptor (prism byte order) --*/
+ UINT16 status;
+ UINT16 reserved0;
+ UINT16 reserved1;
+ UINT8 silence;
+ UINT8 signal;
+ UINT8 rate;
+ UINT8 reserved2;
+ UINT16 reserved3;
+ UINT16 reserved4;
+
+ /*-- 802.11 Header Information (802.11 byte order) --*/
+ UINT16 frame_control;
+ UINT16 duration_id;
+ UINT8 address1[6];
+ UINT8 address2[6];
+ UINT8 address3[6];
+ UINT16 sequence_control;
+ UINT8 address4[6];
+ UINT16 data_len; /* little endian format */
+
+ /*-- 802.3 Header Information --*/
+ UINT8 dest_addr[6];
+ UINT8 src_addr[6];
+ UINT16 data_length; /* big endian format */
+} __attribute__ ((packed));
+typedef struct prism_rx_frame prism_rx_frame_t;
+
+/*------------------------------------------------------------------*/
+/* MAC state structure, argument to all functions */
+/*------------------------------------------------------------------*/
+/*--prism hardware record----*/
+typedef struct prism_record
+{
+ UINT16 reclen;
+ UINT16 rid;
+} prism_rec_t;
+
+/*------ RID Structure---------*/
+typedef struct prism_cnfDesireSSID
+{
+ UINT16 ssidLen __WLAN_ATTRIB_PACK__;
+ UINT8 ssidName[32] __WLAN_ATTRIB_PACK__;
+}__WLAN_ATTRIB_PACK__ prism_cnfDesireSSID_t;
+
+
+typedef struct prism_pdaRec
+{
+ unsigned short len;
+ unsigned short id;
+ unsigned short buf[60];
+} prism_pdaRec_t;
+
+#define SCAN_ENABLE
+#ifdef SCAN_ENABLE
+
+typedef struct prism_ScanResultSub
+{
+ UINT16 chid __WLAN_ATTRIB_PACK__;
+ UINT16 anl __WLAN_ATTRIB_PACK__;
+ UINT16 sl __WLAN_ATTRIB_PACK__;
+ UINT8 bssid[6] __WLAN_ATTRIB_PACK__;
+ UINT16 bcnint __WLAN_ATTRIB_PACK__;
+ UINT16 capinfo __WLAN_ATTRIB_PACK__;
+ struct prism_cnfDesireSSID ssid __WLAN_ATTRIB_PACK__;
+ UINT8 supprates[10] __WLAN_ATTRIB_PACK__; /* 802.11 info element */
+ UINT16 proberesp_rate __WLAN_ATTRIB_PACK__;
+}__WLAN_ATTRIB_PACK__ prism_ScanResultSub_t;
+
+typedef struct prism_ScanResult
+{
+ UINT16 rsvd __WLAN_ATTRIB_PACK__;
+ UINT16 scanreason __WLAN_ATTRIB_PACK__;
+ struct prism_ScanResultSub result[35] __WLAN_ATTRIB_PACK__;
+}__WLAN_ATTRIB_PACK__ prism_ScanResult_t;
+
+#endif
+
+
+/*-------prism cmd responses-------*/
+typedef struct hermes_response {
+ UINT16 status, resp0, resp1, resp2;
+} hermes_response_t;
+
+#define PRISM_MAX_KEY_SIZE 14
+#define PRISM_MAX_KEYS 4
+
+#define SMALL_KEY_SIZE 5
+#define LARGE_KEY_SIZE 13
+
+typedef struct prism_key {
+ u16 len; /* always store little-endian */
+ char data[PRISM_MAX_KEY_SIZE];
+} __attribute__ ((packed)) prism_key_t;
+
+typedef prism_key_t prism_keys_t[PRISM_MAX_KEYS];
+
+/*-----------------driver wireless default setting---------------------*/
+#define DEFAULT_TXRATE_MODE 0x00
+#define DEFAULT_RXSTHRESHOLD 2432
+#define DEFAULT_SENSE 1
+#define DEFAULT_POWMANAGE 0
+#define DEFAULT_MULITRECEIVE 1
+#define DEFAULT_MAXSLEEP 100
+#define DEFAULT_PMHOLDDURATION 100
+/*----------------------------------------------------*/
+/* PRISM For W90N745 Definition */
+/*----------------------------------------------------*/
+#define WIRELESS_SPY // enable iwspy support
+
+#ifdef WIRELESS_SPY
+#define SPY_NUMBER(priv) (priv->spy_number)
+#else
+#define SPY_NUMBER(priv) 0
+#endif /* WIRELESS_SPY */
+
+struct w740prism_priv {
+ struct net_device_stats stats;
+ struct iw_statistics wstats;
+ int status; // wireless link status;
+ // -1: setup fail
+ // 0: setup ok
+ // 1: connected
+ // 2: disconnected
+ // 3: Access Point Change
+ // 4: Access Point Out of Range
+ // 5: Access Point In Range
+ // 6: Association failed
+ unsigned char mac_address[ETH_ALEN] __attribute__ ((aligned (2)));
+
+ int rx_packetlen;
+ u8 *rx_packetdata;
+ int tx_packetlen;
+ u8 *tx_packetdata;
+ struct sk_buff *skb;
+
+ unsigned short txfid; /* use for debug */
+ struct net_device * ndev;
+
+ u16 wep_on, wep_restrict, tx_key;
+ prism_keys_t keys;
+
+ /* Configuration paramaters */
+ u32 iw_mode;
+ int prefer_port3;
+ int bitratemode;
+ char nick[IW_ESSID_MAX_SIZE+1] __attribute__ ((aligned (2)));
+ char desired_essid[IW_ESSID_MAX_SIZE+1] __attribute__ ((aligned (2)));
+ u16 frag_thresh, mwo_robust;
+ u16 channel;
+ u16 ap_density, rts_thresh;
+ u16 pm_on, pm_mcast, pm_period, pm_timeout;
+ u16 preamble;
+#ifdef WIRELESS_SPY
+ int spy_number;
+ u8 spy_address[IW_MAX_SPY][ETH_ALEN];
+ struct iw_quality spy_stat[IW_MAX_SPY];
+#endif
+#ifdef SCAN_ENABLE
+ prism_ScanResult_t scan_res;
+ int scan_res_len;
+#endif
+ /* Configuration dependent variables */
+ int port_type, allow_ibss;
+ int promiscuous, mc_count;
+
+ struct semaphore sema; /* to sleep on */
+ spinlock_t lock;
+};
+
+
+#ifdef WDEBUG
+/*------------------Debug use--------------------*/
+#define LOGPRINT printk("%s: %d\n", __FILE__,__LINE__)
+#define DEBUG printk
+
+#else
+#define LOGPRINT
+#define DEBUG
+#endif
+//#define DEBUGPRINT
+//#define NEWDOCMD
+
+
+/*-----------------------------------------*/
+/* Inline functions */
+/*-----------------------------------------*/
+static inline void
+prism_lock(struct w740prism_priv *priv)
+{
+ spin_lock_bh(&priv->lock);
+}
+
+static inline void
+prism_unlock(struct w740prism_priv *priv)
+{
+ spin_unlock_bh(&priv->lock);
+}
+
+/*----------------------------------------------------*/
+/* PRISM For W90N745 Definition */
+/*----------------------------------------------------*/
+/*--------prism initialize set up value-------------*/
+#define PRISM_TxRate ((UINT16)0x000F)
+#define PRISM_Authentication ((UINT16)0x0003)
+#define PRISM_MacPortType ((UINT16)0x0001)
+#define PRISM_Default_Channel ((UINT16)0x0009)
+#define PRISM_Support_Rate ((UINT16)0x000F)
+#define PRISM_Beacon_Interval ((UINT16)1000)
+#define PRISM_DTIM_Period ((UINT16)0x0003)
+#define PRISM_MAX_DATA_LEN ((UINT16)2304)
+
+/*-------------transmit frame buffer declaration---------------*/
+#define FRAME_DATA_MAXLEN 2304
+#define PRISM2_TXBUF_MAX (sizeof(prism_tx_frame_t) + FRAME_DATA_MAXLEN)
+
+#if 0 //def _BIG_ENDIAN
+#define PRISM_FrameControl ((UINT16)0x0801) // ToDS = 1, FromDS = 0 STA mode
+#define PRISM_DurationID ((UINT16)0x0000)
+#else
+#define PRISM_FrameControl ((UINT16)0x0108) // ToDS = 1, FromDS = 0 STA mode
+#define PRISM_DurationID ((UINT16)0x0000)
+#endif //def _BIG_ENDIAN
+
+/* These are maximum timeouts. Most often, card wil react much faster */
+#define CMD_BUSY_TIMEOUT (100) /* In iterations of ~1us */
+#define CMD_INIT_TIMEOUT (50000) /* in iterations of ~10us */
+#define CMD_COMPL_TIMEOUT (1500) /* in iterations of ~10us */
+//#define CMD_COMPL_TIMEOUT (2000) /* in iterations of ~10us */
+#define ALLOC_COMPL_TIMEOUT (1000) /* in iterations of ~10us */
+#define BAP_BUSY_TIMEOUT (500) /* in iterations of ~1us */
+
+#define MAX_IRQLOOPS_PER_IRQ 10
+#define MAX_IRQLOOPS_PER_JIFFY (20000/HZ) /* Based on a guestimate of how many events the
+ device can legitimately generate */
+#define HERMES_DESCRIPTOR_OFFSET 0
+#define HERMES_802_11_OFFSET (14)
+#define HERMES_802_3_OFFSET (14+32)
+#define HERMES_802_2_OFFSET (14+32+14)
+
+#define DUMMY_FID 0xFFFF
+
+#define ENCAPS_OVERHEAD (6*sizeof(char) + 2)
+
+#define RUP_EVEN(a) ( (a) % 2 ? (a) + 1 : (a) )
+
+
+
+/*-----------------------------------function declares-------------------------*/
+/*------------ module routine------------- */
+int prism_init_module(void);
+void prism_cleanup(void);
+int prism_init(struct net_device *dev);
+
+/*------------------------------driver routine------------------------------*/
+/* open */
+int prism_open(struct net_device *dev);
+/* as close */
+int prism_release(struct net_device *dev);
+/* upper level software call to send package */
+int prism_start_tx(struct sk_buff *skb, struct net_device *dev);
+/* send buffer */
+static int send_frame(struct net_device *dev ,unsigned char *data,int length);
+/* prism get package from internal to upper level software */
+void prism_rx(struct net_device *dev);
+/* prism get communication information */
+int prism_info(struct net_device *dev);
+/* interrupt event handle function */
+void prism_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+/* mac driver's ioctl */
+int prism_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+/* multicast function */
+static void prism_set_multicast_list(struct net_device *dev);
+/* check after tx */
+int prism_tx(struct net_device *dev);
+/* timeout handle */
+void prism_tx_timeout (struct net_device *dev);
+/* set mac address */
+static int prism_set_mac_address(struct net_device *dev, void *addr);
+/* net device stat */
+struct net_device_stats *prism_stats(struct net_device *dev);
+/* net device reset */
+int prism_reset(struct w740prism_priv *priv);
+
+/* ------------------------------prism's operation ------------------------------*/
+/* prism init in W90N745 */
+int prism_initmac(struct net_device *dev);
+/* init command operation */
+int prism_cmd_initialize();
+/* copy content to prism though buffer access path */
+int prism_copy_to_bap(UINT16 bap, UINT16 id, UINT16 offset, void *buf, UINT32 len);
+/* copy buffer from prsim though buffer access path */
+int prism_copy_from_bap(UINT16 bap, UINT16 id, UINT16 offset, void *buf, UINT32 len);
+/* alloc buffer for tx */
+int prism_cmd_allocate(UINT16 len, unsigned short *txfid);
+/* reset this card */
+int prism_reset_device(struct net_device *dev);
+/* send command to prism and wait */
+#ifndef NEWDOCMD
+int prism_docmd_wait(UINT16 cmd, UINT16 parm0, UINT16 parm1, UINT16 parm2);
+int prism_docmd_nowait(UINT16 cmd, UINT16 parm0, UINT16 parm1, UINT16 parm2);
+#else
+//int prism_docmd_wait(UINT16 cmd, UINT16 parm0, UINT16 parm1, UINT16 parm2, hermes_response_t *resp);
+int prism_docmd_wait(UINT16 cmd, UINT16 parm0, UINT16 parm1, UINT16 parm2);
+int hermes_issue_cmd(UINT16 cmd, UINT16 param0, UINT16 param1, UINT16 param2);
+#endif
+int prism_cmd_access(UINT16 write, UINT16 rid);
+int prism_cmd_diagnose();
+int prism_config(struct net_device *dev, struct ifmap *map);
+int prism_cmd_enable(UINT16 macport);
+int prism_cmd_disable(UINT16 macport);
+/* command to start transmit which parameter is fid */
+int prism_cmd_transmit(UINT16 reclaim, UINT16 fid);
+int prism_cmd_inquiry(UINT16 infoType);
+int Write_RID_Config(UINT16 rid, void *buf, UINT16 len);
+int Read_RID_Config(UINT16 rid, void *buf);
+int Read_CT_InfoType(UINT16 Infofid, UINT16 *len);
+int Read_CT_InfoData(UINT16 Infofid, void *buf, int len);
+void prism_txexc();
+
+/* ioctl extends functions */
+int prism_ioctl_getessid(struct net_device *dev, struct iw_point *erq);
+int prism_ioctl_setessid(struct net_device *dev, struct iw_point *essid);
+long prism_hw_get_freq(struct w740prism_priv *priv);
+int prism_ioctl_setfreq(struct net_device *dev, struct iw_freq *freq);
+int prism_ioctl_setiwencode(struct net_device *dev, struct iw_point *erq);
+int prism_hw_setup_wep(struct w740prism_priv *priv);
+int prism_hw_get_bssid(struct net_device *dev, char buf[ETH_ALEN]);
+int prism_ioctl_getlinkstat(struct net_device *dev, struct iw_point *erq);
+int prism_ioctl_getiwrate(struct net_device *dev, struct iw_param *iwp);
+int prism_ioctl_setiwrate(struct net_device *dev, struct iw_param *iwp);
+int prism_hw_setiwrate(struct w740prism_priv *priv);
+int prism_ioctl_setrts(struct net_device *dev, struct iw_param *iwp);
+int prism_ioctl_getsens(struct net_device *dev, struct iw_param *iwp);
+int prism_ioctl_setsens(struct net_device *dev, struct iw_param *iwp);
+int prism_hw_setapdensity(struct w740prism_priv *priv);
+int prism_ioctl_getpower(struct net_device *dev, struct iw_param *iwp);
+int prism_ioctl_setpower(struct net_device *dev, struct iw_param *iwp);
+int prism_hw_setpower(struct w740prism_priv *priv);
+int get_scan_result(UINT16 infoid, int lens, struct w740prism_priv *priv);
+int prism_ioctl_getaplist(struct net_device *dev, struct iw_point * iwp);
+void set_port_type(struct w740prism_priv *priv);
+int prism_ioctl_setspy(struct net_device *dev, struct iw_point *iwp);
+int prism_ioctl_getspy(struct net_device *dev, struct iw_point *iwp);
+/*------------------Swap macro------------------*/
+static inline unsigned short Swap16(unsigned short val)
+{
+ return ((val & 0xFF) <<8) | ((val &0xFF00) >>8);
+}
+
+/*----------------Test card present--------------*/
+static inline int hermes_present()
+{
+ UINT32 value = READREG(PRISM_SWSUPPORT0);
+ printk("hermes_present: %x\n", value);
+ return (value == HERMES_MAGIC);
+}
+#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
new file mode 100755
index 0000000..4d0f17a
--- /dev/null
+++ b/uClinux-2.4.20-uc1/drivers/net/wireless/base.c
@@ -0,0 +1,1783 @@
+/*------------------------------------------------------------------------------*/
+/* Wireless driver base functions for winbond W90N745 */
+/* version 1.0.2(used only for Station) */
+/*------------------------------------------------------------------------------*/
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/pagemap.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#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, &reg, 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, &reg, 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, &reg, 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("<<<reset>>>\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, &reg, PRISM_RID_CNFPORTTYPE_LEN);
+ DEBUG("allow ibss %x\n", priv->allow_ibss);
+#if 0
+ reg = PRISM_TxRate;
+ Write_RID_Config(PRISM_RID_TXRATECNTL, &reg, 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, &reg, PRISM_RID_CNFMAXDATALEN_LEN);
+
+ /* set the channel */
+ reg = priv->channel;
+ Write_RID_Config(PRISM_RID_CNFOWNCHANNEL, &reg, 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*)(&reg))[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; j<cnt; j++)
+ {
+#if 1
+ if (scan->result[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; i<len-1; i+=2)
+// printk(" %02x %02x", scan->result[j].ssid.ssidName[i+1], scan->result[j].ssid.ssidName[i]);
+// printk(" %02x", scan->result[j].ssid.ssidName[len]);
+// }
+// else
+// {
+// for (i=0; i<len; i+=2)
+// printk(" %02x %02x", scan->result[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;
+}