diff options
author | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
---|---|---|
committer | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
commit | 871480933a1c28f8a9fed4c4d34d06c439a7a422 (patch) | |
tree | 8718f573808810c2a1e8cb8fb6ac469093ca2784 /drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux | |
parent | 9d40ac5867b9aefe0722bc1f110b965ff294d30d (diff) | |
download | FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.gz FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.bz2 FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.zip |
Moved, renamed, and deleted files
The original directory structure was scattered and unorganized.
Changes are basically to make it look like kernel structure.
Diffstat (limited to 'drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux')
22 files changed, 8508 insertions, 0 deletions
diff --git a/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/Makefile b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/Makefile new file mode 100755 index 00000000..35c17531 --- /dev/null +++ b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/Makefile @@ -0,0 +1,153 @@ +# Comment/uncomment the following line to disable/enable debugging +MAKE = make +RM = rm +MV = mv +ECHO = echo +CP = cp + + +#DEBUG = y +# Add your debugging flag (or not) to CFLAGS +ifeq ($(DEBUG),y) +DEBFLAGS = -O -g +else +DEBFLAGS = -O2 +endif + +#Use external 1.4V VCO +EXTRA_CFLAGS += -DVCO_14_SUPPLY +EXTRA_CFLAGS += -DREG_0XF6_NOT_CLEAR_BUG_FIX +#Default to NMI=EVAL if NMI isn't defined +ifeq ($(strip $(NMI)),) +NMI=EVAL +endif + +ifeq ($(NMI),EVAL) +EXTRA_CFLAGS += -DNMC_ASIC_A0 +else ifeq ($(NMI),FPGA) +endif + +ifeq ($(BUS),SDIO) +EXTRA_CFLAGS += -DNMI_SDIO +endif + +ifeq ($(SDIO_IRQ),GPIO) +EXTRA_CFLAGS += -DNMI_SDIO_IRQ_GPIO +endif + +ifeq ($(DMA_VER),VER_1) +EXTRA_CFLAGS += -DUSE_DMA_VER_1 +endif + +ifeq ($(TARGET),SIMULATION) +KERNELDIR ?= /lib/modules/$(shell uname -r)/build +TARGET=SIMULATION +EXTRA_CFLAGS += -DSIMULATION -g +OUT_ARCH = x86 +else ifeq ($(TARGET),PANDA) +KERNELDIR ?= $(DEV_TREE)/kernel/omap +EXTRA_CFLAGS += -DPANDA_BOARD -DUSE_WIRELESS +MAKE_FLAGS := CROSS_COMPILE=$(DEV_TREE)/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi- ARCH=arm +OUT_ARCH = ARM-3.0 +#EXTRA_CFLAGS += -DSIMULATION +else ifeq ($(TARGET),BEAGLE) +KERNELDIR ?= $(DEV_TREE) +OUT_ARCH = ARM-2.6.39 +MAKE_FLAGS := CROSS_COMPILE=arm-arago-linux-gnueabi- ARCH=arm +EXTRA_CFLAGS += -DBEAGLE_BOARD +KERNELDIR ?= $(DEV_TREE) +else ifeq ($(TARGET),NM73131) +KERNELDIR ?= $(DEV_TREE_LPC) +OUT_ARCH = ARM-2.6.28.2 +MAKE_FLAGS := CROSS_COMPILE=arm-linux- ARCH=arm +EXTRA_CFLAGS += -DNM73131_0_BOARD +else ifeq ($(TARGET),ALLWINNER) +KERNELDIR ?= $(DEV_TREE)/linux-3.0 +MAKE_FLAGS := CROSS_COMPILE=$(DEV_TREE)/buildroot/output/external-toolchain/bin/arm-none-linux-gnueabi- ARCH=arm +EXTRA_CFLAGS += -DALLWINNER_BOARD -DUSE_WIRELESS +OUT_ARCH = ARM-3.0 +else +KERNELDIR ?= /lib/modules/$(shell uname -r)/build +OUT_ARCH = x86 +TARGET=SIMULATION +EXTRA_CFLAGS += -DSIMULATION +endif + + + +EXTRA_CFLAGS += $(DEBFLAGS) -I $(PWD)/../../NMI_OsWrapper/include/ +EXTRA_CFLAGS += -I $(PWD)/../../ -I $(PWD)/../include -I $(PWD)/../ -I $(PWD)/include +EXTRA_CFLAGS += -DNMI_PLATFORM=NMI_LINUXKERNEL +EXTRA_CFLAGS += -Wno-unused-function + + + +obj-m := nmi_wifi.o +ifeq ($(TARGET),NM73131) +ifeq ($(BUS),SDIO) +nmi_wifi-objs := source/linux_wlan.o source/linux_wlan_sdio.o\ +source/nmi_debugfs.o source/nmi_queue.o\ +../binary/linux/$(OUT_ARCH)/NMI_WiFi_Driver.a\ +../../NMI_OsWrapper/binary/linux/$(OUT_ARCH)/NMI_OsWrapper.a +else +nmi_wifi-objs := source/linux_wlan.o source/linux_wlan_spi.o\ +source/nmi_debugfs.o source/nmi_queue.o\ +../binary/linux/$(OUT_ARCH)/NMI_WiFi_Driver.a\ +../../NMI_OsWrapper/binary/linux/$(OUT_ARCH)/NMI_OsWrapper.a +endif + +else + +ifeq ($(BUS),SDIO) +nmi_wifi-objs := source/NMI_WFI_NetDevice.o source/NMI_WFI_CfgOperations.o\ +source/linux_wlan.o source/linux_wlan_sdio.o source/linux_mon.o\ +source/nmi_debugfs.o source/nmi_queue.o\ +../binary/linux/$(OUT_ARCH)/NMI_WiFi_Driver.a\ +../../NMI_OsWrapper/binary/linux/$(OUT_ARCH)/NMI_OsWrapper.a +else +nmi_wifi-objs := source/NMI_WFI_NetDevice.o source/NMI_WFI_CfgOperations.o\ +source/linux_wlan.o source/linux_wlan_spi.o source/linux_mon.o\ +source/nmi_debugfs.o source/nmi_queue.o\ +../binary/linux/$(OUT_ARCH)/NMI_WiFi_Driver.a\ +../../NMI_OsWrapper/binary/linux/$(OUT_ARCH)/NMI_OsWrapper.a +endif + +endif + +ifneq ($(KERNELRELEASE),) +# call from kernel build system + + +else + +#KERNELDIR ?= /lib/modules/$(shell uname -r)/build +PWD := $(shell pwd) + +default: + echo KERNELDIR = $(KERNELDIR) + $(MAKE) TARGET=$(TARGET) NMI=$(NMI) BUS=$(BUS) FULLY_HOSTING_AP=$(FULLY_HOSTING_AP) -C ../ + @$(ECHO) "###########################################" + @$(ECHO) "##### Building NMI WiFi for Linux ######" + @$(ECHO) "##### TARGET =" $(TARGET) "######" + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules $(MAKE_FLAGS) + mkdir -p binary/linux/$(OUT_ARCH) + $(MV) -f $(PWD)/nmi_wifi.ko binary/linux/$(OUT_ARCH)/nmi_wifi.ko + +endif + +clean: + $(MAKE) TARGET=$(TARGET) NMI=$(NMI) BUS=$(BUS) -C ../ clean + @$(ECHO) "###########################################" + @$(ECHO) "##### Cleaning NMI WiFi for Linux ######" + @$(ECHO) "##### TARGET =" $(TARGET) "######" + $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) clean + rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions + rm -rf binary/linux/$(OUT_ARCH)/nmi_wifi.ko + +depend .depend dep: + $(CC) $(CFLAGS) -M *.c > .depend + + +ifeq (.depend,$(wildcard .depend)) +include .depend +endif diff --git a/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/allwinner_run_eval.sh b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/allwinner_run_eval.sh new file mode 100755 index 00000000..879a98fc --- /dev/null +++ b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/allwinner_run_eval.sh @@ -0,0 +1,4 @@ +adb push ../../core/wifi_v111/ASIC_A0/wifi_firmware.bin /system/vendor/firmware/wifi_firmware.bin +adb push binary/linux/ARM-3.0/nmi_wifi.ko /system/vendor/modules/nmi_wifi.ko +adb shell "echo 0 > /proc/driver/sunxi-mmc.3/insert" +adb shell "echo 1 > /proc/driver/sunxi-mmc.3/insert"
\ No newline at end of file diff --git a/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/ap_soft.conf b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/ap_soft.conf new file mode 100755 index 00000000..80b509d5 --- /dev/null +++ b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/ap_soft.conf @@ -0,0 +1,30 @@ +interface=wlan0 +dump_file=/data/misc/wifi/hostapd.dump +driver=nl80211 +ctrl_interface=/data/misc/wifi/hostapd +ssid=HOSTAPD +dtim_period=2 +beacon_int=100 +channel=6 +hw_mode=g +max_num_sta=8 +#auth_algs=1 +ap_max_inactivity=10 +#wpa=2 +#wpa_passphrase=12345678 +#wpa_key_mgmt=WPA-PSK +#wpa_pairwise= CCMP +#rsn_pairwise=CCMP +auth_algs=3 +#ignore_broadcast_ssid=0 +wep_default_key=0 +wep_key0=1234567890 +#wep_key0=000102030405060708090a0b0c +#wep_key0=0102030405060708090a0b0c0d +#wep_key0=1234567890abcdef1234567890 +#wep_key_len_broadcast=10 +#wep_key_len_unicast=10 + + + + diff --git a/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/include/NMI_WFI_CfgOperations.h b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/include/NMI_WFI_CfgOperations.h new file mode 100755 index 00000000..0c9a1ea0 --- /dev/null +++ b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/include/NMI_WFI_CfgOperations.h @@ -0,0 +1,75 @@ +/*! +* @file NMI_WFI_CfgOperations.h +* @brief Definitions for the network module +* @author syounan +* @sa NMI_OSWrapper.h top level OS wrapper file +* @date 31 Aug 2010 +* @version 1.0 +*/ +#ifndef NM_WFI_CFGOPERATIONS +#define NM_WFI_CFGOPERATIONS +#include "linux/include/NMI_WFI_NetDevice.h" + +#include "NMI_host_AP.h" + + +/* The following macros describe the bitfield map used by the firmware to determine its 11i mode */ +#define NO_ENCRYPT 0 +#define ENCRYPT_ENABLED (1 << 0) +#define WEP (1 << 1) +#define WEP_EXTENDED (1 << 2) +#define WPA (1 << 3) +#define WPA2 (1 << 4) +#define AES (1 << 5) +#define TKIP (1 << 6) + + +#define nl80211_SCAN_RESULT_EXPIRE (3 * HZ) + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30) +static const u32 cipher_suites[] = { + WLAN_CIPHER_SUITE_WEP40, + WLAN_CIPHER_SUITE_WEP104, + WLAN_CIPHER_SUITE_TKIP, + WLAN_CIPHER_SUITE_CCMP, + WLAN_CIPHER_SUITE_AES_CMAC, +}; +#endif + + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) +static const struct ieee80211_txrx_stypes +nmi_wfi_cfg80211_mgmt_types[NL80211_IFTYPE_MAX] = +{ + [NL80211_IFTYPE_STATION] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + }, + [NL80211_IFTYPE_AP] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) | + BIT(IEEE80211_STYPE_ACTION >> 4) + } +}; +#endif +/* Time to stay on the channel */ +#define NMI_WFI_DWELL_PASSIVE 100 +#define NMI_WFI_DWELL_ACTIVE 40 + +struct wireless_dev* NMI_WFI_CfgAlloc(void); +struct wireless_dev * NMI_WFI_WiphyRegister(struct net_device *net); +void NMI_WFI_WiphyFree(struct net_device *net); +int NMI_WFI_update_stats(struct wiphy *wiphy, u32 pktlen , u8 changed); +int NMI_WFI_DeInitHostInt(struct net_device *net); +int NMI_WFI_InitHostInt(struct net_device *net); +void NMI_WFI_monitor_rx(uint8_t *buff, uint32_t size); +int NMI_WFI_deinit_mon_interface(void); +int NMI_WFI_init_mon_interface(char *name, struct net_device *real_dev ); +#endif diff --git a/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/include/NMI_WFI_NetDevice.h b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/include/NMI_WFI_NetDevice.h new file mode 100755 index 00000000..c38cd711 --- /dev/null +++ b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/include/NMI_WFI_NetDevice.h @@ -0,0 +1,231 @@ +/*! +* @file NMI_WFI_NetDevice.h +* @brief Definitions for the network module +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +#ifndef NMI_WFI_NETDEVICE +#define NMI_WFI_NETDEVICE +/* +* Macros to help debugging +*/ + +#undef PDEBUG /* undef it, just in case */ +#ifdef SNULL_DEBUG +# ifdef __KERNEL__ +/* This one if debugging is on, and kernel space */ +# define PDEBUG(fmt, args...) printk( KERN_DEBUG "snull: " fmt, ## args) +# else +/* This one for user space */ +# define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args) +# endif +#else +# define PDEBUG(fmt, args...) /* not debugging: nothing */ +#endif + +#undef PDEBUGG +#define PDEBUGG(fmt, args...) /* nothing: it's a placeholder */ + + +/* These are the flags in the statusword */ +#define NMI_WFI_RX_INTR 0x0001 +#define NMI_WFI_TX_INTR 0x0002 + +/* Default timeout period */ +#define NMI_WFI_TIMEOUT 5 /* In jiffies */ +#define NMI_MAX_NUM_PMKIDS 16 +#define PMKID_LEN 16 +#define PMKID_FOUND 1 + #define NUM_STA_ASSOCIATED 8 + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/moduleparam.h> +#include <linux/sched.h> +#include <linux/kernel.h> /* printk() */ +#include <linux/slab.h> /* kmalloc() */ +#include <linux/errno.h> /* error codes */ +#include <linux/types.h> /* size_t */ +#include <linux/interrupt.h> /* mark_bh */ +#include <linux/time.h> +#include <linux/in.h> +#include <linux/netdevice.h> /* struct device, and other headers */ +#include <linux/etherdevice.h> /* eth_type_trans */ +#include <linux/ip.h> /* struct iphdr */ +#include <linux/tcp.h> /* struct tcphdr */ +#include <linux/skbuff.h> + +#include <linux/ieee80211.h> +#include <net/cfg80211.h> + +#include <linux/ieee80211.h> +#include <net/cfg80211.h> +#include <net/ieee80211_radiotap.h> +#include <linux/if_arp.h> + + +#include <linux/in6.h> +#include <asm/checksum.h> +#include "host_interface.h" + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,30) +#include <net/wireless.h> +#else +#include <linux/wireless.h> // tony, 2013-06-12 +#endif + +#define FLOW_CONTROL_LOWER_THRESHOLD 128 +#define FLOW_CONTROL_UPPER_THRESHOLD 256 + +/*iftype*/ + + +enum stats_flags +{ + NMI_WFI_RX_PKT = 1 << 0, + NMI_WFI_TX_PKT = 1 << 1, +}; + +struct NMI_WFI_stats +{ + + unsigned long rx_packets; + unsigned long tx_packets; + unsigned long rx_bytes; + unsigned long tx_bytes; + u64 rx_time; + u64 tx_time; + +}; + +/* +* This structure is private to each device. It is used to pass +* packets in and out, so there is place for a packet +*/ + +#define RX_BH_KTHREAD 0 +#define RX_BH_WORK_QUEUE 1 +#define RX_BH_THREADED_IRQ 2 +/* + * If you use RX_BH_WORK_QUEUE on LPC3131: You may lose the first interrupt on + * LPC3131 which is important to get the MAC start status when you are blocked inside + * linux_wlan_firmware_download() which blocks mac_open(). + */ +#if defined (NM73131_0_BOARD) +#define RX_BH_TYPE RX_BH_KTHREAD +#else +#define RX_BH_TYPE RX_BH_WORK_QUEUE +#endif + +struct nmi_wfi_key { + u8 * key; + u8 * seq; + int key_len; + int seq_len; + u32 cipher; +}; + +struct sta_info +{ + NMI_Uint8 au8Sta_AssociatedBss[MAX_NUM_STA][ETH_ALEN]; +}; + + +struct NMI_WFI_priv { + struct wireless_dev *wdev; + struct cfg80211_scan_request* pstrScanReq; + NMI_Bool bCfgScanning; + NMI_Uint32 u32RcvdChCount; + NMI_Uint32 u32LastScannedNtwrksCount; + tstrNetworkInfo astrLastScannedNtwrks[MAX_NUM_SCANNED_NETWORKS]; + NMI_Uint8 au8AssociatedBss[ETH_ALEN]; + struct sta_info assoc_stainfo; + struct net_device_stats stats; + NMI_Uint8 monitor_flag; + int status; + struct NMI_WFI_packet *ppool; + struct NMI_WFI_packet *rx_queue; /* List of incoming packets */ + int rx_int_enabled; + int tx_packetlen; + u8 *tx_packetdata; + struct sk_buff *skb; + spinlock_t lock; + struct net_device *dev; + struct napi_struct napi; + NMI_WFIDrvHandle hNMIWFIDrv; + tstrHostIFpmkidAttr pmkid_list; + struct NMI_WFI_stats netstats; + NMI_Uint8 NMI_WFI_wep_default; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) +#define WLAN_KEY_LEN_WEP104 13 +#endif + NMI_Uint8 NMI_WFI_wep_key[4][WLAN_KEY_LEN_WEP104]; + NMI_Uint8 NMI_WFI_wep_key_len[4]; + struct net_device* real_ndev; /* The real interface that the monitor is on */ + struct nmi_wfi_key* nmi_gtk[MAX_NUM_STA]; + struct nmi_wfi_key* nmi_ptk[MAX_NUM_STA]; + NMI_Uint8 nmi_groupkey; +}; + +typedef struct{ + int mac_status; + int nmc1000_initialized; + #if (!defined NMI_SDIO) || (defined NMI_SDIO_IRQ_GPIO) + unsigned short dev_irq_num; + #endif + nmi_wlan_oup_t oup; + int monitor_flag; + int close; + struct net_device_stats netstats; + struct mutex txq_cs; + struct mutex rxq_cs; + struct mutex hif_cs; + + //struct mutex txq_event; + struct semaphore rxq_event; + struct semaphore cfg_event; + struct semaphore sync_event; + + struct semaphore txq_event; + //struct completion txq_event; + +#if (RX_BH_TYPE == RX_BH_WORK_QUEUE) + struct work_struct rx_work_queue; +#elif (RX_BH_TYPE == RX_BH_KTHREAD) + struct task_struct* rx_bh_thread; + struct semaphore rx_sem; +#endif + + + + struct semaphore rxq_thread_started; + struct semaphore txq_thread_started; + + struct task_struct* rxq_thread; + struct task_struct* txq_thread; + + unsigned char eth_src_address[6]; + unsigned char eth_dst_address[6]; + + const struct firmware* nmc_firmware; /* Bug 4703 */ + + struct net_device* nmc_netdev; + struct net_device* real_ndev; +#ifdef NMI_SDIO + int already_claim; + struct sdio_func* nmc_sdio_func; +#else + struct spi_device* nmc_spidev; +#endif + + NMI_Uint8 iftype; +} linux_wlan_t; + +struct NMI_WFI_mon_priv +{ + struct net_device* real_ndev; +}; +extern struct net_device *NMI_WFI_devs[]; + +#endif diff --git a/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/init_deinit_test.sh b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/init_deinit_test.sh new file mode 100755 index 00000000..31bcc7a2 --- /dev/null +++ b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/init_deinit_test.sh @@ -0,0 +1,51 @@ +#!/bin/sh +num_init_iterations=0 +echo "* Starting Init/Deinit Test *" +while [ "$num_init_iterations" -lt "20" ] +do +echo "*****************************************" +echo "* initialization trial no. $((num_init_iterations+1)) *" +echo "*****************************************" +echo "Bringing wlan0 down" +ret_cfg_iface=$(adb shell ifconfig wlan0 down) +ret_cfg_iface_err=$(echo "$ret_cfg_iface" | grep 'error') +echo "$ret_cfg_iface_err" +if [ -n "${ret_cfg_iface_err}" ]; then + echo "failed in ifconfig wlan1 down" + echo "..Initialization failed.." + exit +fi +sleep 1 +echo "Bringing wlan0 up" +ret_cfg_iface=$(adb shell ifconfig wlan0 up) +ret_cfg_iface_err=$(echo "$ret_cfg_iface" | grep 'error') +echo "$ret_cfg_iface_err" +if [ -n "${ret_cfg_iface_err}" ]; then + echo "failed in ifconfig wlan1 up" + echo "..Initialization failed.." + exit +fi +sleep 1 +echo "Disabling Wifi" +adb shell svc wifi disable +sleep 5 +echo "Enabling Wifi" +adb shell svc wifi enable +sleep 10 +cli_status=$(adb shell wpa_cli status) +echo cli_status +cli_status_check=$(echo "$cli_status" | grep ^wpa_state) + +if [ -z "${cli_status_check}" ]; then + echo "failed in wpa_cli status" + echo "..Initialization failed.." + exit +fi +echo "succeeded" +num_init_iterations=$((num_init_iterations+1)) +adb shell ping -i.4 -c10 192.168.11.1 +#adb shell ping -i.4 -c10 192.168.1.1 + +done +echo "num of succeded init/deinit trials $num_init_iterations" +echo "* End of Init/Deinit Test *" diff --git a/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/nmi_wfi_load b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/nmi_wfi_load new file mode 100755 index 00000000..a4e42aa6 --- /dev/null +++ b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/nmi_wfi_load @@ -0,0 +1,10 @@ +#!/bin/sh + +export PATH=/sbin:/bin +# Use a pathname, as new modutils don't look in the current dir by default +#modprobe cfg80211 +insmod /lib/modules/$(uname -r)/kernel/net/wireless/cfg80211.ko +insmod ./binary/linux/x86/nmi_wifi.ko $* + +ifconfig wlan0 local0 +ifconfig wlan1 local1 diff --git a/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/nmi_wfi_unload b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/nmi_wfi_unload new file mode 100755 index 00000000..134c9352 --- /dev/null +++ b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/nmi_wfi_unload @@ -0,0 +1,6 @@ +#!/bin/sh + +/sbin/ifconfig wlan0 down +/sbin/ifconfig wlan1 down +/sbin/rmmod nmi_wifi +rmmod cfg80211 diff --git a/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/panda_run_eval.sh b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/panda_run_eval.sh new file mode 100755 index 00000000..043b7a9a --- /dev/null +++ b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/panda_run_eval.sh @@ -0,0 +1,6 @@ +adb shell rm /system/etc/firmware/wifi_firmware.bin +adb push ../../core/wifi_v111/ASIC_A0/wifi_firmware.bin /system/etc/firmware/wifi_firmware.bin +adb push ../../core/wifi_v111/ASIC_A0_AP/wifi_firmware_ap.bin /system/etc/firmware/wifi_firmware_ap.bin +adb shell rm /data/nmi_wifi.ko +adb push binary/linux/ARM-3.0/nmi_wifi.ko /data/nmi_wifi.ko +adb push ./ap_soft.conf /data/misc/wifi/hostapd.conf diff --git a/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/panda_run_fpga.sh b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/panda_run_fpga.sh new file mode 100755 index 00000000..d8a1a897 --- /dev/null +++ b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/panda_run_fpga.sh @@ -0,0 +1,4 @@ +adb push ../../core/wifi_v111/FPGA_485t/wifi_firmware.bin /system/etc/firmware/wifi_firmware.bin +adb push binary/linux/ARM-3.0/nmi_wifi.ko /sdcard/nmi_wifi.ko +#adb push ../../../../../AdelShare/android4.0/softap.conf /data/misc/wifi/softap.conf +adb shell insmod /sdcard/nmi_wifi.ko diff --git a/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/NMI_WFI_CfgOperations.c b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/NMI_WFI_CfgOperations.c new file mode 100755 index 00000000..2a2f0a59 --- /dev/null +++ b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/NMI_WFI_CfgOperations.c @@ -0,0 +1,2673 @@ +/*! +* @file NMI_WFI_CfgOpertaions.c +* @brief CFG80211 Function Implementation functionality +* @author aabouzaeid +* mabubakr +* mdaftedar +* zsalah +* @sa NMI_WFI_CfgOpertaions.h top level OS wrapper file +* @date 31 Aug 2010 +* @version 1.0 +*/ + +#include "linux/include/NMI_WFI_CfgOperations.h" + +NMI_SemaphoreHandle SemHandleUpdateStats; +static NMI_SemaphoreHandle hSemScanReq; + + +extern void linux_wlan_free(void* vp); +extern int linux_wlan_get_firmware(linux_wlan_t* p_nic); + + +#define CHAN2G(_channel, _freq, _flags) { \ + .band = IEEE80211_BAND_2GHZ, \ + .center_freq = (_freq), \ + .hw_value = (_channel), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} + +/*Frequency range for channels*/ +static struct ieee80211_channel NMI_WFI_2ghz_channels[] = { + CHAN2G(1, 2412, 0), + CHAN2G(2, 2417, 0), + CHAN2G(3, 2422, 0), + CHAN2G(4, 2427, 0), + CHAN2G(5, 2432, 0), + CHAN2G(6, 2437, 0), + CHAN2G(7, 2442, 0), + CHAN2G(8, 2447, 0), + CHAN2G(9, 2452, 0), + CHAN2G(10, 2457, 0), + CHAN2G(11, 2462, 0), + CHAN2G(12, 2467, 0), + CHAN2G(13, 2472, 0), + CHAN2G(14, 2484, 0), +}; + +#define RATETAB_ENT(_rate, _hw_value, _flags) { \ + .bitrate = (_rate), \ + .hw_value = (_hw_value), \ + .flags = (_flags), \ +} + + +/* Table 6 in section 3.2.1.1 */ +static struct ieee80211_rate NMI_WFI_rates[] = { + RATETAB_ENT(10, 0, 0), + RATETAB_ENT(20, 1, 0), + RATETAB_ENT(55, 2, 0), + RATETAB_ENT(110, 3, 0), + RATETAB_ENT(60, 9, 0), + RATETAB_ENT(90, 6, 0), + RATETAB_ENT(120, 7, 0), + RATETAB_ENT(180, 8, 0), + RATETAB_ENT(240, 9, 0), + RATETAB_ENT(360, 10, 0), + RATETAB_ENT(480, 11, 0), + RATETAB_ENT(540, 12, 0), +}; + +static struct ieee80211_supported_band NMI_WFI_band_2ghz = { + .channels = NMI_WFI_2ghz_channels, + .n_channels = ARRAY_SIZE(NMI_WFI_2ghz_channels), + .bitrates = NMI_WFI_rates, + .n_bitrates = ARRAY_SIZE(NMI_WFI_rates), +}; + +/** +* @brief CfgScanResult +* @details Callback function which returns the scan results found +* +* @param[in] tenuScanEvent enuScanEvent: enum, indicating the scan event triggered, whether that is +* SCAN_EVENT_NETWORK_FOUND or SCAN_EVENT_DONE +* tstrNetworkInfo* pstrNetworkInfo: structure holding the scan results information +* void* pUserVoid: Private structure associated with the wireless interface +* @return NONE +* @author mabubakr +* @date +* @version 1.0 +*/ +static void CfgScanResult(tenuScanEvent enuScanEvent, tstrNetworkInfo* pstrNetworkInfo, void* pUserVoid) + { + struct NMI_WFI_priv* priv; + struct wiphy* wiphy; + NMI_Sint32 s32Freq; + struct ieee80211_channel *channel; + NMI_Sint32 s32Error = NMI_SUCCESS; + + priv = (struct NMI_WFI_priv*)pUserVoid; + + + if(priv->bCfgScanning == NMI_TRUE) + { + PRINT_D(CFG80211_DBG,"Scanning in progress..\n"); + + if(enuScanEvent == SCAN_EVENT_NETWORK_FOUND) + { + wiphy = priv->dev->ieee80211_ptr->wiphy; + + NMI_NULLCHECK(s32Error, wiphy); + + if(wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC + && + ( (((NMI_Sint32)pstrNetworkInfo->s8rssi) * 100) < 0 + || + (((NMI_Sint32)pstrNetworkInfo->s8rssi) * 100) > 100) + ) + { + NMI_ERRORREPORT(s32Error, NMI_FAIL); + } + + if(priv->u32RcvdChCount <= MAX_NUM_SCANNED_NETWORKS) //TODO: mostafa: to be replaced by + // max_scan_ssids + { + PRINT_D(CFG80211_DBG,"Network %s found\n",pstrNetworkInfo->au8ssid); + #if defined (PLAT_WMS8304) //for debug + // rachel ++ + PRINT_D(CFG80211_DBG, "[MMM] Network rssi(%d), BSSID: %x:%x:%x:%x:%x:%x\n", pstrNetworkInfo->s8rssi + , pstrNetworkInfo->au8bssid[0], pstrNetworkInfo->au8bssid[1], pstrNetworkInfo->au8bssid[2] + , pstrNetworkInfo->au8bssid[3], pstrNetworkInfo->au8bssid[4], pstrNetworkInfo->au8bssid[5]); + // rachel -- + #endif + if(pstrNetworkInfo != NMI_NULL) + { + PRINT_D(CFG80211_DBG,"Network information received\n"); + + priv->u32RcvdChCount++; + #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) + s32Freq = ieee80211_channel_to_frequency((NMI_Sint32)pstrNetworkInfo->u8channel, IEEE80211_BAND_2GHZ); + #else + s32Freq = ieee80211_channel_to_frequency((NMI_Sint32)pstrNetworkInfo->u8channel); + #endif + channel = ieee80211_get_channel(wiphy, s32Freq); + + NMI_NULLCHECK(s32Error, channel); + + PRINT_INFO(CFG80211_DBG,"Network Info:: CHANNEL Frequency: %d, RSSI: %d, CapabilityInfo: %d," + "BeaconPeriod: %d \n",channel->center_freq, (((NMI_Sint32)pstrNetworkInfo->s8rssi) * 100), + pstrNetworkInfo->u16CapInfo, pstrNetworkInfo->u16BeaconPeriod); + + cfg80211_inform_bss(wiphy, channel, pstrNetworkInfo->au8bssid, 0, pstrNetworkInfo->u16CapInfo, + pstrNetworkInfo->u16BeaconPeriod, (const u8*)pstrNetworkInfo->pu8IEs, + (size_t)pstrNetworkInfo->u16IEsLen, (((NMI_Sint32)pstrNetworkInfo->s8rssi) * 100), GFP_KERNEL); + + /* BugID_4209: cache the last Scan results such that in Connect Response Callback function, a check is + done if the intended network has been in the scan results more than a specified time (currently 2.8sec), + the cached last scan results are raised again to the upper nl80211 kernel layer to refresh its scan results + to prevent it from generating kernel warning. */ + + priv->astrLastScannedNtwrks[priv->u32LastScannedNtwrksCount].s8rssi = pstrNetworkInfo->s8rssi; + priv->astrLastScannedNtwrks[priv->u32LastScannedNtwrksCount].u16CapInfo = pstrNetworkInfo->u16CapInfo; + + priv->astrLastScannedNtwrks[priv->u32LastScannedNtwrksCount].u8SsidLen = pstrNetworkInfo->u8SsidLen; + NMI_memcpy(priv->astrLastScannedNtwrks[priv->u32LastScannedNtwrksCount].au8ssid, + pstrNetworkInfo->au8ssid, pstrNetworkInfo->u8SsidLen); + + NMI_memcpy(priv->astrLastScannedNtwrks[priv->u32LastScannedNtwrksCount].au8bssid, + pstrNetworkInfo->au8bssid, ETH_ALEN); + + priv->astrLastScannedNtwrks[priv->u32LastScannedNtwrksCount].u16BeaconPeriod = pstrNetworkInfo->u16BeaconPeriod; + priv->astrLastScannedNtwrks[priv->u32LastScannedNtwrksCount].u8DtimPeriod = pstrNetworkInfo->u8DtimPeriod; + priv->astrLastScannedNtwrks[priv->u32LastScannedNtwrksCount].u8channel = pstrNetworkInfo->u8channel; + + priv->astrLastScannedNtwrks[priv->u32LastScannedNtwrksCount].u16IEsLen = pstrNetworkInfo->u16IEsLen; + priv->astrLastScannedNtwrks[priv->u32LastScannedNtwrksCount].pu8IEs = + (NMI_Uint8*)NMI_MALLOC(pstrNetworkInfo->u16IEsLen); /* will be deallocated + by the NMI_WFI_CfgScan() function */ + NMI_memcpy(priv->astrLastScannedNtwrks[priv->u32LastScannedNtwrksCount].pu8IEs, + pstrNetworkInfo->pu8IEs, pstrNetworkInfo->u16IEsLen); + + priv->astrLastScannedNtwrks[priv->u32LastScannedNtwrksCount].u32TimeRcvdInScan = jiffies; + + priv->u32LastScannedNtwrksCount++; + + + } + } + else + { + PRINT_ER("Discovered networks exceeded the max limit\n"); + } + } + else if(enuScanEvent == SCAN_EVENT_DONE) + { + PRINT_D(CFG80211_DBG,"Scan Done \n"); + + if(priv->u32RcvdChCount > 0) + { + PRINT_D(CFG80211_DBG,"%d Network(s) found \n", priv->u32RcvdChCount); + } + else + { + PRINT_D(CFG80211_DBG,"No networks found \n"); + } + + NMI_SemaphoreAcquire(&hSemScanReq, NULL); + + if(priv->pstrScanReq != NMI_NULL) + { + cfg80211_scan_done(priv->pstrScanReq, NMI_FALSE); + priv->u32RcvdChCount = 0; + priv->bCfgScanning = NMI_FALSE; + priv->pstrScanReq = NMI_NULL; + } + NMI_SemaphoreRelease(&hSemScanReq, NULL); + + } + /*Aborting any scan operation during mac close*/ + else if(enuScanEvent == SCAN_EVENT_ABORTED) + { + NMI_SemaphoreAcquire(&hSemScanReq, NULL); + + PRINT_D(CFG80211_DBG,"Aborting scan \n"); + if(priv->pstrScanReq != NMI_NULL) + { + cfg80211_scan_done(priv->pstrScanReq,NMI_TRUE); + priv->pstrScanReq = NMI_NULL; + } + NMI_SemaphoreRelease(&hSemScanReq, NULL); + } + } + + + NMI_CATCH(s32Error) + { + } + } + + +/** +* @brief NMI_WFI_Set_PMKSA +* @details Check if pmksa is cached and set it. +* @param[in] +* @return int : Return 0 on Success +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +int NMI_WFI_Set_PMKSA(NMI_Uint8 * bssid,struct NMI_WFI_priv* priv) +{ + NMI_Uint32 i; + NMI_Sint32 s32Error = NMI_SUCCESS; + + + for (i = 0; i < priv->pmkid_list.numpmkid; i++) + { + + if (!NMI_memcmp(bssid,priv->pmkid_list.pmkidlist[i].bssid, + ETH_ALEN)) + { + PRINT_D(CFG80211_DBG,"PMKID successful comparison"); + + /*If bssid is found, set the values*/ + s32Error = host_int_set_pmkid_info(priv->hNMIWFIDrv,&priv->pmkid_list); + + if(s32Error != NMI_SUCCESS) + PRINT_ER("Error in pmkid\n"); + + break; + } + } + + return s32Error; + + +} + +/** +* @brief CfgConnectResult +* @details +* @param[in] tenuConnDisconnEvent enuConnDisconnEvent: Type of connection response either +* connection response or disconnection notification. +* tstrConnectInfo* pstrConnectInfo: COnnection information. +* NMI_Uint8 u8MacStatus: Mac Status from firmware +* tstrDisconnectNotifInfo* pstrDisconnectNotifInfo: Disconnection Notification +* void* pUserVoid: Private data associated with wireless interface +* @return NONE +* @author mabubakr +* @date 01 MAR 2012 +* @version 1.0 +*/ +static void CfgConnectResult(tenuConnDisconnEvent enuConnDisconnEvent, + tstrConnectInfo* pstrConnectInfo, + NMI_Uint8 u8MacStatus, + tstrDisconnectNotifInfo* pstrDisconnectNotifInfo, + void* pUserVoid) +{ + struct NMI_WFI_priv* priv; + struct net_device* dev; + + if(enuConnDisconnEvent == CONN_DISCONN_EVENT_CONN_RESP) + { + /*Initialization*/ + NMI_Uint16 u16ConnectStatus = WLAN_STATUS_SUCCESS; + + priv = (struct NMI_WFI_priv*)pUserVoid; + + dev = priv->dev; + + u16ConnectStatus = pstrConnectInfo->u16ConnectStatus; + + PRINT_D(CFG80211_DBG," Connection response received = %d\n",u8MacStatus); + + if((u8MacStatus == MAC_DISCONNECTED) && + (pstrConnectInfo->u16ConnectStatus == SUCCESSFUL_STATUSCODE)) + { + /* The case here is that our station was waiting for association response frame and has just received it containing status code + = SUCCESSFUL_STATUSCODE, while mac status is MAC_DISCONNECTED (which means something wrong happened) */ + u16ConnectStatus = WLAN_STATUS_UNSPECIFIED_FAILURE; + PRINT_ER("Unspecified failure: Connection status %d : MAC status = %d \n",u16ConnectStatus,u8MacStatus); + } + + if(u16ConnectStatus == WLAN_STATUS_SUCCESS) + { + NMI_Bool bNeedScanRefresh = NMI_FALSE; + NMI_Uint32 i; + + PRINT_INFO(CFG80211_DBG,"Connection Successful:: BSSID: %x%x%x%x%x%x\n",pstrConnectInfo->au8bssid[0], + pstrConnectInfo->au8bssid[1],pstrConnectInfo->au8bssid[2],pstrConnectInfo->au8bssid[3],pstrConnectInfo->au8bssid[4],pstrConnectInfo->au8bssid[5]); + NMI_memcpy(priv->au8AssociatedBss, pstrConnectInfo->au8bssid, ETH_ALEN); + + + + /* BugID_4209: if this network has expired in the scan results in the above nl80211 layer, refresh them here by calling + cfg80211_inform_bss() with the last Scan results before calling cfg80211_connect_result() to avoid + Linux kernel warning generated at the nl80211 layer */ + + for(i = 0; i < priv->u32LastScannedNtwrksCount; i++) + { + if(NMI_memcmp(priv->astrLastScannedNtwrks[i].au8bssid, + pstrConnectInfo->au8bssid, ETH_ALEN) == 0) + { + unsigned long now = jiffies; + + if(time_after(now, + priv->astrLastScannedNtwrks[i].u32TimeRcvdInScan + (unsigned long)(nl80211_SCAN_RESULT_EXPIRE - (1 * HZ)))) + { + bNeedScanRefresh = NMI_TRUE; + } + + break; + } + } + + if(bNeedScanRefresh == NMI_TRUE) + { + struct wiphy* wiphy; + + PRINT_D(CFG80211_DBG," network %s expired. Refreshing scan results\n", + priv->astrLastScannedNtwrks[i].au8ssid); + + wiphy = priv->dev->ieee80211_ptr->wiphy; + + for(i = 0; i < priv->u32LastScannedNtwrksCount; i++) + { + tstrNetworkInfo* pstrNetworkInfo; + NMI_Sint32 s32Freq; + struct ieee80211_channel *channel; + + pstrNetworkInfo = &(priv->astrLastScannedNtwrks[i]); + + if(pstrNetworkInfo != NMI_NULL) + { + PRINT_D(CFG80211_DBG,"cached Network information retrieved\n"); + + #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) + s32Freq = ieee80211_channel_to_frequency((NMI_Sint32)pstrNetworkInfo->u8channel, IEEE80211_BAND_2GHZ); + #else + s32Freq = ieee80211_channel_to_frequency((NMI_Sint32)pstrNetworkInfo->u8channel); + #endif + channel = ieee80211_get_channel(wiphy, s32Freq); + + PRINT_INFO(CFG80211_DBG,"Network Info:: CHANNEL Frequency: %d, RSSI: %d, CapabilityInfo: %d," + "BeaconPeriod: %d \n",channel->center_freq, (((NMI_Sint32)pstrNetworkInfo->s8rssi) * 100), + pstrNetworkInfo->u16CapInfo, pstrNetworkInfo->u16BeaconPeriod); + + + cfg80211_inform_bss(wiphy, channel, pstrNetworkInfo->au8bssid, 0, pstrNetworkInfo->u16CapInfo, + pstrNetworkInfo->u16BeaconPeriod, (const u8*)pstrNetworkInfo->pu8IEs, + (size_t)pstrNetworkInfo->u16IEsLen, (((NMI_Sint32)pstrNetworkInfo->s8rssi) * 100), GFP_KERNEL); + + } + } + } + + } + + + PRINT_D(CFG80211_DBG,"Association request info elements length = %d\n", pstrConnectInfo->ReqIEsLen); + + PRINT_D(CFG80211_DBG,"Association response info elements length = %d\n", pstrConnectInfo->u16RespIEsLen); + + cfg80211_connect_result(dev, pstrConnectInfo->au8bssid, + pstrConnectInfo->pu8ReqIEs, pstrConnectInfo->ReqIEsLen, + pstrConnectInfo->pu8RespIEs, pstrConnectInfo->u16RespIEsLen, + u16ConnectStatus, GFP_KERNEL); //TODO: mostafa: u16ConnectStatus to + // be replaced by pstrConnectInfo->u16ConnectStatus + } + else if(enuConnDisconnEvent == CONN_DISCONN_EVENT_DISCONN_NOTIF) + { + priv = (struct NMI_WFI_priv*)pUserVoid; + dev = priv->dev; + + PRINT_ER("Received MAC_DISCONNECTED from firmware with reason %d\n", + pstrDisconnectNotifInfo->u16reason); + + NMI_memset(priv->au8AssociatedBss, 0, ETH_ALEN); + + cfg80211_disconnected(dev, pstrDisconnectNotifInfo->u16reason, pstrDisconnectNotifInfo->ie, + pstrDisconnectNotifInfo->ie_len, GFP_KERNEL); + + } + +} + + +/** +* @brief NMI_WFI_CfgSetChannel +* @details Set channel for a given wireless interface. Some devices +* may support multi-channel operation (by channel hopping) so cfg80211 +* doesn't verify much. Note, however, that the passed netdev may be +* %NULL as well if the user requested changing the channel for the +* device itself, or for a monitor interface. +* @param[in] +* @return int : Return 0 on Success +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_CfgSetChannel(struct wiphy *wiphy, + #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32) + struct net_device *netdev, + #endif + struct ieee80211_channel *channel, + enum nl80211_channel_type channel_type) +{ + + NMI_Uint32 channelnum = 0; + struct NMI_WFI_priv* priv; + NMI_Sint32 s32Error = NMI_SUCCESS; + priv = wiphy_priv(wiphy); + + channelnum = ieee80211_frequency_to_channel(channel->center_freq); + + PRINT_D(CFG80211_DBG,"Setting channel %d with frequency %d\n", channelnum, channel->center_freq ); + + s32Error = host_int_set_mac_chnl_num(priv->hNMIWFIDrv,channelnum); + + if(s32Error != NMI_SUCCESS) + PRINT_ER("Error in setting channel %d\n", channelnum); + + return s32Error; +} + +/** +* @brief NMI_WFI_CfgScan +* @details Request to do a scan. If returning zero, the scan request is given +* the driver, and will be valid until passed to cfg80211_scan_done(). +* For scan results, call cfg80211_inform_bss(); you can call this outside +* the scan/scan_done bracket too. +* @param[in] +* @return int : Return 0 on Success +* @author mabubakr +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_CfgScan(struct wiphy *wiphy,struct net_device *dev, + struct cfg80211_scan_request *request) +{ + struct NMI_WFI_priv* priv; + NMI_Uint32 i; + NMI_Sint32 s32Error = NMI_SUCCESS; + NMI_Uint8 au8ScanChanList[MAX_NUM_SCANNED_NETWORKS]; + tstrHiddenNetwork strHiddenNetwork; + + priv = wiphy_priv(wiphy); + + priv->pstrScanReq = request; + priv->u32RcvdChCount = 0; + + for(i = 0; i <priv->u32LastScannedNtwrksCount; i++) + { + if(priv->astrLastScannedNtwrks[i].pu8IEs != NULL) + { + NMI_FREE(priv->astrLastScannedNtwrks[i].pu8IEs); + priv->astrLastScannedNtwrks[i].pu8IEs = NULL; + } + priv->astrLastScannedNtwrks[i].u16IEsLen = 0; + } + + priv->u32LastScannedNtwrksCount = 0; + + NMI_memset((void*)priv->astrLastScannedNtwrks, 0, sizeof(priv->astrLastScannedNtwrks)); + + priv->bCfgScanning = NMI_TRUE; + + if(request->n_channels <= MAX_NUM_SCANNED_NETWORKS) //TODO: mostafa: to be replaced by + // max_scan_ssids + { + for(i = 0; i < request->n_channels; i++) + { + au8ScanChanList[i] = (NMI_Uint8)ieee80211_frequency_to_channel(request->channels[i]->center_freq); + PRINT_INFO(CFG80211_DBG, "ScanChannel List[%d] = %d,",i,au8ScanChanList[i]); + } + + PRINT_D(CFG80211_DBG,"Requested num of scan channel %d\n",request->n_channels); + PRINT_D(CFG80211_DBG,"Scan Request IE len = %d\n",request->ie_len); + + PRINT_D(CFG80211_DBG,"Number of SSIDs %d\n",request->n_ssids); + + if(request->n_ssids >= 1) + { + + + strHiddenNetwork.pstrHiddenNetworkInfo = NMI_MALLOC(request->n_ssids * sizeof(tstrHiddenNetwork)); + strHiddenNetwork.u8ssidnum = request->n_ssids; + + + /*BugID_4156*/ + for(i=0;i<request->n_ssids;i++) + { + + if(request->ssids[i].ssid != NULL && request->ssids[i].ssid_len!=0) + { + strHiddenNetwork.pstrHiddenNetworkInfo[i].pu8ssid= NMI_MALLOC( request->ssids[i].ssid_len); + NMI_memcpy(strHiddenNetwork.pstrHiddenNetworkInfo[i].pu8ssid,request->ssids[i].ssid,request->ssids[i].ssid_len); + strHiddenNetwork.pstrHiddenNetworkInfo[i].u8ssidlen = request->ssids[i].ssid_len; + } + else + { + PRINT_D(CFG80211_DBG,"Received one NULL SSID \n"); + strHiddenNetwork.u8ssidnum-=1; + } + } + PRINT_D(CFG80211_DBG,"Trigger Scan Request \n"); + s32Error = host_int_scan(priv->hNMIWFIDrv, USER_SCAN, ACTIVE_SCAN, + au8ScanChanList, request->n_channels, + (const NMI_Uint8*)request->ie, request->ie_len, + CfgScanResult, (void*)priv,&strHiddenNetwork); + } + else + { + PRINT_D(CFG80211_DBG,"Trigger Scan Request \n"); + s32Error = host_int_scan(priv->hNMIWFIDrv, USER_SCAN, ACTIVE_SCAN, + au8ScanChanList, request->n_channels, + (const NMI_Uint8*)request->ie, request->ie_len, + CfgScanResult, (void*)priv,NULL); + } + + } + else + { + PRINT_ER("Requested num of scanned channels is greater than the max, supported" + " channels \n"); + } + + if(s32Error != NMI_SUCCESS) + { + s32Error = -EBUSY; + PRINT_WRN(CFG80211_DBG,"Device is busy: Error(%d)\n",s32Error); + } + + return s32Error; +} + +/** +* @brief NMI_WFI_CfgConnect +* @details Connect to the ESS with the specified parameters. When connected, +* call cfg80211_connect_result() with status code %WLAN_STATUS_SUCCESS. +* If the connection fails for some reason, call cfg80211_connect_result() +* with the status from the AP. +* @param[in] +* @return int : Return 0 on Success +* @author mabubakr +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_CfgConnect(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_connect_params *sme) +{ + NMI_Sint32 s32Error = NMI_SUCCESS; + NMI_Uint32 i; + //SECURITY_T tenuSecurity_t = NO_SECURITY; + NMI_Uint8 u8security = NO_ENCRYPT; + AUTHTYPE_T tenuAuth_type = ANY; + NMI_Char * pcgroup_encrypt_val; + NMI_Char * pccipher_group; + NMI_Char * pcwpa_version; + + struct NMI_WFI_priv* priv; + tstrNetworkInfo* pstrNetworkInfo = NULL; + + priv = wiphy_priv(wiphy); + + PRINT_D(CFG80211_DBG,"Connecting to SSID [%s]\n",sme->ssid); + PRINT_INFO(CFG80211_DBG,"Required SSID = %s\n , AuthType = %d \n", sme->ssid,sme->auth_type); + + priv->NMI_WFI_wep_default = 0; + NMI_memset(priv->NMI_WFI_wep_key, 0, sizeof(priv->NMI_WFI_wep_key)); + NMI_memset(priv->NMI_WFI_wep_key_len, 0, sizeof(priv->NMI_WFI_wep_key_len)); + + PRINT_INFO(CFG80211_DBG,"sme->crypto.wpa_versions=%x\n", sme->crypto.wpa_versions); + PRINT_INFO(CFG80211_DBG,"sme->crypto.cipher_group=%x\n", sme->crypto.cipher_group); + + PRINT_INFO(CFG80211_DBG,"sme->crypto.n_ciphers_pairwise=%d\n", sme->crypto.n_ciphers_pairwise); + + if(INFO) + { + for(i=0 ; i < sme->crypto.n_ciphers_pairwise ; i++) + NMI_PRINTF("sme->crypto.ciphers_pairwise[%d]=%x\n", i, sme->crypto.ciphers_pairwise[i]); + } + + if(sme->crypto.cipher_group != NO_ENCRYPT) + { + /* To determine the u8security value, first we check the group cipher suite then {in case of WPA or WPA2} + we will add to it the pairwise cipher suite(s) */ + //switch(sme->crypto.wpa_versions) + //{ + //printk(">> sme->crypto.wpa_versions: %x\n",sme->crypto.wpa_versions); + //case NL80211_WPA_VERSION_1: + if( sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) + { + //printk("> wpa_version: NL80211_WPA_VERSION_2\n"); + //case NL80211_WPA_VERSION_2: + if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_TKIP) + { + //printk("> WPA2-TKIP\n"); + //tenuSecurity_t = WPA2_TKIP; + u8security = ENCRYPT_ENABLED | WPA2 | TKIP; + pcgroup_encrypt_val = "WPA2_TKIP"; + pccipher_group = "TKIP"; + } + else //TODO: mostafa: here we assume that any other encryption type is AES + { + //printk("> WPA2-AES\n"); + //tenuSecurity_t = WPA2_AES; + u8security = ENCRYPT_ENABLED | WPA2 | AES; + pcgroup_encrypt_val = "WPA2_AES"; + pccipher_group = "AES"; + } + pcwpa_version = "WPA_VERSION_2"; + } + else if( sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) + { + //printk("> wpa_version: NL80211_WPA_VERSION_1\n"); + if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_TKIP) + { + //printk("> WPA-TKIP\n"); + //tenuSecurity_t = WPA_TKIP; + u8security = ENCRYPT_ENABLED | WPA | TKIP; + pcgroup_encrypt_val = "WPA_TKIP"; + pccipher_group = "TKIP"; + } + else //TODO: mostafa: here we assume that any other encryption type is AES + { + //printk("> WPA-AES\n"); + //tenuSecurity_t = WPA_AES; + u8security = ENCRYPT_ENABLED | WPA | AES; + pcgroup_encrypt_val = "WPA_AES"; + pccipher_group = "AES"; + + } + pcwpa_version = "WPA_VERSION_1"; + + //break; + } + else{ + //break; + //default: + + pcwpa_version = "Default"; + PRINT_D(CFG80211_DBG,"Adding key with cipher group = %x\n",sme->crypto.cipher_group); + if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) + { + //printk("> WEP\n"); + //tenuSecurity_t = WEP_40; + u8security = ENCRYPT_ENABLED | WEP; + pcgroup_encrypt_val = "WEP40"; + pccipher_group = "WLAN_CIPHER_SUITE_WEP40"; + } + else if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104) + { + //printk("> WEP-WEP_EXTENDED\n"); + //tenuSecurity_t = WEP_104; + u8security = ENCRYPT_ENABLED | WEP | WEP_EXTENDED; + pcgroup_encrypt_val = "WEP104"; + pccipher_group = "WLAN_CIPHER_SUITE_WEP104"; + } + else + { + s32Error = -ENOTSUPP; + PRINT_ER("Not supported cipher: Error(%d)\n",s32Error); + //PRINT_ER("Cipher-Group: %x\n",sme->crypto.cipher_group); + + goto done; + } + + PRINT_INFO(CFG80211_DBG, "WEP Default Key Idx = %d\n",sme->key_idx); + + if(INFO) + { + for(i=0;i<sme->key_len;i++) + NMI_PRINTF("WEP Key Value[%d] = %d\n", i, sme->key[i]); + } + + priv->NMI_WFI_wep_default = sme->key_idx; + priv->NMI_WFI_wep_key_len[sme->key_idx] = sme->key_len; + NMI_memcpy(priv->NMI_WFI_wep_key[sme->key_idx], sme->key, sme->key_len); + host_int_set_WEPDefaultKeyID(priv->hNMIWFIDrv,sme->key_idx); + host_int_add_wep_key_bss_sta(priv->hNMIWFIDrv, sme->key,sme->key_len,sme->key_idx); + //break; + } + + /* After we set the u8security value from checking the group cipher suite, {in case of WPA or WPA2} we will + add to it the pairwise cipher suite(s) */ + if((sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) + || (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)) + { + for(i=0 ; i < sme->crypto.n_ciphers_pairwise ; i++) + { + if (sme->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP) + { + u8security = u8security | TKIP; + } + else //TODO: mostafa: here we assume that any other encryption type is AES + { + u8security = u8security | AES; + } + } + } + + } + PRINT_D(CFG80211_DBG, "Authentication Type = %d\n",sme->auth_type); + switch(sme->auth_type) + { + case NL80211_AUTHTYPE_OPEN_SYSTEM: + PRINT_D(CFG80211_DBG, "In OPEN SYSTEM\n"); + tenuAuth_type = OPEN_SYSTEM; + break; + case NL80211_AUTHTYPE_SHARED_KEY: + tenuAuth_type = SHARED_KEY; + PRINT_D(CFG80211_DBG, "In SHARED KEY\n"); + break; + default: + PRINT_D(CFG80211_DBG, "Automatic Authentation type = %d\n",sme->auth_type); + } + + + /* ai: key_mgmt: enterprise case */ + if (sme->crypto.n_akm_suites) + { + switch (sme->crypto.akm_suites[0]) + { + case WLAN_AKM_SUITE_8021X: + tenuAuth_type = IEEE8021; + break; + default: + //PRINT_D(CFG80211_DBG, "security unhandled [%x] \n",sme->crypto.akm_suites[0]); + break; + } + + + + } + + + for(i = 0; i < priv->u32LastScannedNtwrksCount; i++) + { + if(NMI_memcmp(priv->astrLastScannedNtwrks[i].au8ssid, + sme->ssid, + sme->ssid_len) == 0) + { + PRINT_INFO(CFG80211_DBG,"Network with required SSID is found %s\n", sme->ssid); + if(sme->bssid == NULL) + { + /* BSSID is not passed from the user, so decision of matching + * is done by SSID only */ + PRINT_INFO(CFG80211_DBG,"BSSID is not passed from the user\n"); + break; + } + else + { + /* BSSID is also passed from the user, so decision of matching + * should consider also this passed BSSID */ + + if(NMI_memcmp(priv->astrLastScannedNtwrks[i].au8bssid, + sme->bssid, + ETH_ALEN) == 0) + { + PRINT_INFO(CFG80211_DBG,"BSSID is passed from the user and matched\n"); + break; + } + } + } + } + + if(i < priv->u32LastScannedNtwrksCount) + { + PRINT_D(CFG80211_DBG, "Required bss is in scan results\n"); + + pstrNetworkInfo = &(priv->astrLastScannedNtwrks[i]); + + PRINT_INFO(CFG80211_DBG,"network BSSID to be associated: %x%x%x%x%x%x\n", + pstrNetworkInfo->au8bssid[0], pstrNetworkInfo->au8bssid[1], + pstrNetworkInfo->au8bssid[2], pstrNetworkInfo->au8bssid[3], + pstrNetworkInfo->au8bssid[4], pstrNetworkInfo->au8bssid[5]); + } + else + { + s32Error = -ENOENT; + PRINT_ER("Required bss not in scan results: Error(%d)\n",s32Error); + goto done; + } + + PRINT_INFO(CFG80211_DBG, "Required Channel = %d\n", pstrNetworkInfo->u8channel); + + PRINT_INFO(CFG80211_DBG, "Group encryption value = %s\n Cipher Group = %s\n WPA version = %s\n", + pcgroup_encrypt_val, pccipher_group,pcwpa_version); + + s32Error = host_int_set_join_req(priv->hNMIWFIDrv, pstrNetworkInfo->au8bssid, sme->ssid, + sme->ssid_len, sme->ie, sme->ie_len, + CfgConnectResult, (void*)priv, u8security, + tenuAuth_type, pstrNetworkInfo->u8channel); + if(s32Error != NMI_SUCCESS) + { + PRINT_ER("host_int_set_join_req(): Error(%d) \n", s32Error); + s32Error = -ENOENT; + goto done; + } + +done: + + return s32Error; +} + + +/** +* @brief NMI_WFI_disconnect +* @details Disconnect from the BSS/ESS. +* @param[in] +* @return int : Return 0 on Success +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_disconnect(struct wiphy *wiphy, struct net_device *dev,u16 reason_code) +{ + NMI_Sint32 s32Error = NMI_SUCCESS; + struct NMI_WFI_priv* priv; + + + + priv = wiphy_priv(wiphy); + + PRINT_D(CFG80211_DBG,"Disconnecting with reason code(%d)\n", reason_code); + + + s32Error = host_int_disconnect(priv->hNMIWFIDrv, reason_code); + if(s32Error != NMI_SUCCESS) + { + PRINT_ER("Error in disconnecting: Error(%d)\n", s32Error); + s32Error = -EINVAL; + } + + return s32Error; +} + +/** +* @brief NMI_WFI_add_key +* @details Add a key with the given parameters. @mac_addr will be %NULL +* when adding a group key. +* @param[in] key : key buffer; TKIP: 16-byte temporal key, 8-byte Tx Mic key, 8-byte Rx Mic Key +* @return int : Return 0 on Success +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_add_key(struct wiphy *wiphy, struct net_device *netdev,u8 key_index, + #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36) + bool pairwise, + #endif + const u8 *mac_addr,struct key_params *params) + +{ + NMI_Sint32 s32Error = NMI_SUCCESS,KeyLen = params->key_len; + NMI_Uint32 i; + struct NMI_WFI_priv* priv; + NMI_Uint8* pu8RxMic = NULL; + NMI_Uint8* pu8TxMic = NULL; + NMI_Uint8 u8mode = NO_ENCRYPT; + #ifdef NMI_AP_EXTERNAL_MLME + NMI_Uint8 u8gmode = NO_ENCRYPT; + NMI_Uint8 u8pmode = NO_ENCRYPT; + AUTHTYPE_T tenuAuth_type = ANY; + #endif + + priv = wiphy_priv(wiphy); + + PRINT_D(CFG80211_DBG,"Adding key with cipher suite = %x\n",params->cipher); + + switch(params->cipher) + { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + #ifdef NMI_AP_EXTERNAL_MLME + if(priv->wdev->iftype == NL80211_IFTYPE_AP) + { + + priv->NMI_WFI_wep_default = key_index; + priv->NMI_WFI_wep_key_len[key_index] = params->key_len; + NMI_memcpy(priv->NMI_WFI_wep_key[key_index], params->key, params->key_len); + + PRINT_D(CFG80211_DBG, "Adding AP WEP Default key Idx = %d\n",key_index); + PRINT_D(CFG80211_DBG, "Adding AP WEP Key len= %d\n",params->key_len); + + for(i=0;i<params->key_len;i++) + PRINT_D(CFG80211_DBG, "WEP AP key val[%d] = %x\n", i, params->key[i]); + + tenuAuth_type = OPEN_SYSTEM; + + if(params->cipher == WLAN_CIPHER_SUITE_WEP40) + u8mode = ENCRYPT_ENABLED | WEP; + else + u8mode = ENCRYPT_ENABLED | WEP | WEP_EXTENDED; + + host_int_add_wep_key_bss_ap(priv->hNMIWFIDrv,params->key,params->key_len,key_index,u8mode,tenuAuth_type); + break; + } + #endif + if(NMI_memcmp(params->key,priv->NMI_WFI_wep_key[key_index],params->key_len)) + { + priv->NMI_WFI_wep_default = key_index; + priv->NMI_WFI_wep_key_len[key_index] = params->key_len; + NMI_memcpy(priv->NMI_WFI_wep_key[key_index], params->key, params->key_len); + + PRINT_D(CFG80211_DBG, "Adding WEP Default key Idx = %d\n",key_index); + PRINT_D(CFG80211_DBG, "Adding WEP Key length = %d\n",params->key_len); + if(INFO) + { + for(i=0;i<params->key_len;i++) + PRINT_INFO(CFG80211_DBG, "WEP key value[%d] = %d\n", i, params->key[i]); + } + host_int_add_wep_key_bss_sta(priv->hNMIWFIDrv,params->key,params->key_len,key_index); + } + + break; + case WLAN_CIPHER_SUITE_TKIP: + case WLAN_CIPHER_SUITE_CCMP: + #ifdef NMI_AP_EXTERNAL_MLME + if(priv->wdev->iftype == NL80211_IFTYPE_AP) + { + + if(priv->nmi_gtk[key_index] == NULL) + priv->nmi_gtk[key_index] = (struct nmi_wfi_key *)NMI_MALLOC(sizeof(struct nmi_wfi_key)); + if(priv->nmi_ptk[key_index] == NULL) + priv->nmi_ptk[key_index] = (struct nmi_wfi_key *)NMI_MALLOC(sizeof(struct nmi_wfi_key)); + + #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36) + if (!pairwise) + #else + if (!mac_addr || is_broadcast_ether_addr(mac_addr)) + #endif + { + if(params->cipher == WLAN_CIPHER_SUITE_TKIP) + u8gmode = ENCRYPT_ENABLED |WPA | TKIP; + else + u8gmode = ENCRYPT_ENABLED |WPA2 | AES; + + priv->nmi_groupkey = u8gmode; + + if(params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) + { + + pu8TxMic = params->key+24; + pu8RxMic = params->key+16; + KeyLen = params->key_len - 16; + } + + priv->nmi_gtk[key_index]->key = (NMI_Uint8 *)NMI_MALLOC(params->key_len); + NMI_memcpy(priv->nmi_gtk[key_index]->key,params->key,params->key_len); + + if(priv->nmi_gtk[key_index]->seq == NULL) + priv->nmi_gtk[key_index]->seq = (NMI_Uint8 *)NMI_MALLOC(params->seq_len); + + NMI_memcpy(priv->nmi_gtk[key_index]->seq,params->seq,params->seq_len); + + priv->nmi_gtk[key_index]->cipher= params->cipher; + priv->nmi_gtk[key_index]->key_len=params->key_len; + priv->nmi_gtk[key_index]->seq_len=params->seq_len; + + if(INFO) + { + for(i=0;i<params->key_len;i++) + PRINT_INFO(CFG80211_DBG, "Adding group key value[%d] = %x\n", i, params->key[i]); + for(i=0;i<params->seq_len;i++) + PRINT_INFO(CFG80211_DBG, "Adding group seq value[%d] = %x\n", i, params->seq[i]); + } + + + host_int_add_rx_gtk(priv->hNMIWFIDrv,params->key,KeyLen, + key_index,params->seq_len,params->seq,pu8RxMic,pu8TxMic,AP_MODE,u8gmode); + + } + else + { + PRINT_INFO(CFG80211_DBG,"STA Address: %x%x%x%x%x\n",mac_addr[0],mac_addr[1],mac_addr[2],mac_addr[3],mac_addr[4]); + + if(params->cipher == WLAN_CIPHER_SUITE_TKIP) + u8pmode = ENCRYPT_ENABLED | WPA | TKIP; + else + u8pmode = priv->nmi_groupkey | AES; + + + if(params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) + { + + pu8TxMic = params->key+24; + pu8RxMic = params->key+16; + KeyLen = params->key_len - 16; + } + + + priv->nmi_ptk[key_index]->key = (NMI_Uint8 *)NMI_MALLOC(params->key_len); + priv->nmi_ptk[key_index]->seq = (NMI_Uint8 *)NMI_MALLOC(params->seq_len); + + if(INFO) + { + for(i=0;i<params->key_len;i++) + PRINT_INFO(CFG80211_DBG, "Adding pairwise key value[%d] = %x\n", i, params->key[i]); + + for(i=0;i<params->seq_len;i++) + PRINT_INFO(CFG80211_DBG, "Adding group seq value[%d] = %x\n", i, params->seq[i]); + } + + NMI_memcpy(priv->nmi_ptk[key_index]->key,params->key,params->key_len); + NMI_memcpy(priv->nmi_ptk[key_index]->seq,params->seq,params->seq_len); + priv->nmi_ptk[key_index]->cipher= params->cipher; + priv->nmi_ptk[key_index]->key_len=params->key_len; + priv->nmi_ptk[key_index]->seq_len=params->seq_len; + + host_int_add_ptk(priv->hNMIWFIDrv,params->key,KeyLen,mac_addr, + pu8RxMic,pu8TxMic,AP_MODE,u8pmode,key_index); + } + break; + } + #endif + + { + u8mode=0; + #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36) + if (!pairwise) + #else + if (!mac_addr || is_broadcast_ether_addr(mac_addr)) + #endif + { + if(params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) + { + //swap the tx mic by rx mic + pu8RxMic = params->key+24; + pu8TxMic = params->key+16; + KeyLen = params->key_len - 16; + } + host_int_add_rx_gtk(priv->hNMIWFIDrv,params->key,KeyLen, + key_index,params->seq_len,params->seq,pu8RxMic,pu8TxMic,STATION_MODE,u8mode); + //host_int_add_tx_gtk(priv->hNMIWFIDrv,params->key_len,params->key,key_index); + } + else + { + if(params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) + { + //swap the tx mic by rx mic + pu8RxMic = params->key+24; + pu8TxMic = params->key+16; + KeyLen = params->key_len - 16; + } + host_int_add_ptk(priv->hNMIWFIDrv,params->key,KeyLen,mac_addr, + pu8RxMic,pu8TxMic,STATION_MODE,u8mode,key_index); + PRINT_D(CFG80211_DBG,"Adding pairwise key\n"); + if(INFO) + { + for(i=0;i<params->key_len;i++) + PRINT_INFO(CFG80211_DBG, "Adding pairwise key value[%d] = %d\n", i, params->key[i]); + } + } + } + break; + default: + PRINT_ER("Not supported cipher: Error(%d)\n",s32Error); + s32Error = -ENOTSUPP; + + } + + return s32Error; +} + +/** +* @brief NMI_WFI_del_key +* @details Remove a key given the @mac_addr (%NULL for a group key) +* and @key_index, return -ENOENT if the key doesn't exist. +* @param[in] +* @return int : Return 0 on Success +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_del_key(struct wiphy *wiphy, struct net_device *netdev, + u8 key_index, + #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36) + bool pairwise, + #endif + const u8 *mac_addr) +{ + struct NMI_WFI_priv* priv; + NMI_Sint32 s32Error = NMI_SUCCESS; + + priv = wiphy_priv(wiphy); + + if(key_index >= 0 && key_index <=3) + { + NMI_memset(priv->NMI_WFI_wep_key[key_index], 0, priv->NMI_WFI_wep_key_len[key_index]); + priv->NMI_WFI_wep_key_len[key_index] = 0; + + PRINT_D(CFG80211_DBG, "Removing WEP key with index = %d\n",key_index); + host_int_remove_wep_key(priv->hNMIWFIDrv,key_index); + } + else + { + PRINT_D(CFG80211_DBG, "Removing all installed keys\n"); + host_int_remove_key(priv->hNMIWFIDrv,mac_addr); + } + + return s32Error; +} + +/** +* @brief NMI_WFI_get_key +* @details Get information about the key with the given parameters. +* @mac_addr will be %NULL when requesting information for a group +* key. All pointers given to the @callback function need not be valid +* after it returns. This function should return an error if it is +* not possible to retrieve the key, -ENOENT if it doesn't exist. +* @param[in] +* @return int : Return 0 on Success +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_get_key(struct wiphy *wiphy, struct net_device *netdev,u8 key_index, + #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36) + bool pairwise, + #endif + const u8 *mac_addr,void *cookie,void (*callback)(void* cookie, struct key_params*)) +{ + + NMI_Sint32 s32Error = NMI_SUCCESS; + + struct NMI_WFI_priv* priv; + struct key_params key_params; + NMI_Uint32 i; + priv= wiphy_priv(wiphy); + + + #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36) + if (!pairwise) + #else + if (!mac_addr || is_broadcast_ether_addr(mac_addr)) + #endif + { + PRINT_D(CFG80211_DBG,"Getting group key idx: %x\n",key_index); + + key_params.key=priv->nmi_gtk[key_index]->key; + key_params.cipher=priv->nmi_gtk[key_index]->cipher; + key_params.key_len=priv->nmi_gtk[key_index]->key_len; + key_params.seq=priv->nmi_gtk[key_index]->seq; + key_params.seq_len=priv->nmi_gtk[key_index]->seq_len; + if(INFO) + { + for(i=0;i<key_params.key_len;i++) + PRINT_INFO(CFG80211_DBG,"Retrieved key value %x\n",key_params.key[i]); + } + } + else + { + PRINT_D(CFG80211_DBG,"Getting pairwise key\n"); + + key_params.key=priv->nmi_ptk[key_index]->key; + key_params.cipher=priv->nmi_ptk[key_index]->cipher; + key_params.key_len=priv->nmi_ptk[key_index]->key_len; + key_params.seq=priv->nmi_ptk[key_index]->seq; + key_params.seq_len=priv->nmi_ptk[key_index]->seq_len; + } + + callback(cookie,&key_params); + + return s32Error;//priv->nmi_gtk->key_len ?0 : -ENOENT; +} + +/** +* @brief NMI_WFI_set_default_key +* @details Set the default management frame key on an interface +* @param[in] +* @return int : Return 0 on Success. +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_set_default_key(struct wiphy *wiphy,struct net_device *netdev,u8 key_index + #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,37) + ,bool unicast, bool multicast + #endif + ) +{ + NMI_Sint32 s32Error = NMI_SUCCESS; + struct NMI_WFI_priv* priv; + + + priv = wiphy_priv(wiphy); + + PRINT_D(CFG80211_DBG,"Setting default key with idx = %d \n", key_index); + + if(key_index!= priv->NMI_WFI_wep_default) + { + + host_int_set_WEPDefaultKeyID(priv->hNMIWFIDrv,key_index); + } + + return s32Error; +} + +/** +* @brief NMI_WFI_dump_survey +* @details Get site survey information +* @param[in] +* @return int : Return 0 on Success. +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_dump_survey(struct wiphy *wiphy, struct net_device *netdev, + int idx, struct survey_info *info) +{ + NMI_Sint32 s32Error = NMI_SUCCESS; + + + if (idx != 0) + { + s32Error = -ENOENT; + PRINT_ER("Error Idx value doesn't equal zero: Error(%d)\n",s32Error); + + } + + return s32Error; +} + + +/** +* @brief NMI_WFI_get_station +* @details Get station information for the station identified by @mac +* @param[in] NONE +* @return int : Return 0 on Success. +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_get_station(struct wiphy *wiphy, struct net_device *dev, + u8 *mac, struct station_info *sinfo) +{ + NMI_Sint32 s32Error = NMI_SUCCESS; + struct NMI_WFI_priv* priv; + linux_wlan_t* nic; + #ifdef NMI_AP_EXTERNAL_MLME + NMI_Uint32 i =0; + NMI_Uint32 associatedsta = 0; + NMI_Uint32 inactive_time=0; + #endif + priv = wiphy_priv(wiphy); + nic = netdev_priv(dev); + + #ifdef NMI_AP_EXTERNAL_MLME + if(nic->iftype == AP_MODE) + { + PRINT_D(HOSTAPD_DBG,"Getting station parameters\n"); + + PRINT_INFO(HOSTAPD_DBG, ": %x%x%x%x%x\n",mac[0],mac[1],mac[2],mac[3],mac[4]); + + for(i=0; i<NUM_STA_ASSOCIATED; i++) + { + + if (!(memcmp(mac, priv->assoc_stainfo.au8Sta_AssociatedBss[i], ETH_ALEN))) + { + associatedsta = i; + break; + } + + } + + if(associatedsta == -1) + { + s32Error = -ENOENT; + PRINT_ER("Station required is not associated : Error(%d)\n",s32Error); + + return s32Error; + } + + sinfo->filled |= STATION_INFO_INACTIVE_TIME; + + host_int_get_inactive_time(priv->hNMIWFIDrv, mac,&(inactive_time)); + sinfo->inactive_time = 1000 * inactive_time; + PRINT_D(CFG80211_DBG,"Inactive time %d\n",sinfo->inactive_time); + + } + #endif + + if(nic->iftype == STATION_MODE) + { + + sinfo->filled |= STATION_INFO_SIGNAL; + + s32Error = host_int_get_rssi(priv->hNMIWFIDrv, &(sinfo->signal)); + if(s32Error) + PRINT_ER("Failed to send get host channel param's message queue "); + + PRINT_D(CFG80211_DBG,"Rssi value = %d\n",sinfo->signal); + } + + + + return s32Error; +} + + +/** +* @brief NMI_WFI_change_bss +* @details Modify parameters for a given BSS. +* @param[in] +* -use_cts_prot: Whether to use CTS protection +* (0 = no, 1 = yes, -1 = do not change) + * -use_short_preamble: Whether the use of short preambles is allowed + * (0 = no, 1 = yes, -1 = do not change) + * -use_short_slot_time: Whether the use of short slot time is allowed + * (0 = no, 1 = yes, -1 = do not change) + * -basic_rates: basic rates in IEEE 802.11 format + * (or NULL for no change) + * -basic_rates_len: number of basic rates + * -ap_isolate: do not forward packets between connected stations + * -ht_opmode: HT Operation mode + * (u16 = opmode, -1 = do not change) +* @return int : Return 0 on Success. +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_change_bss(struct wiphy *wiphy, struct net_device *dev, + struct bss_parameters *params) +{ + PRINT_D(CFG80211_DBG,"Changing Bss parametrs\n"); + return 0; +} + +/** +* @brief NMI_WFI_auth +* @details Request to authenticate with the specified peer +* @param[in] +* @return int : Return 0 on Success. +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_auth(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_auth_request *req) +{ + PRINT_D(CFG80211_DBG,"In Authentication Function\n"); + return 0; +} + +/** +* @brief NMI_WFI_assoc +* @details Request to (re)associate with the specified peer +* @param[in] +* @return int : Return 0 on Success. +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_assoc(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_assoc_request *req) +{ + PRINT_D(CFG80211_DBG,"In Association Function\n"); + return 0; +} + +/** +* @brief NMI_WFI_deauth +* @details Request to deauthenticate from the specified peer +* @param[in] +* @return int : Return 0 on Success. +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_deauth(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_deauth_request *req,void *cookie) +{ + PRINT_D(CFG80211_DBG,"In De-authentication Function\n"); + return 0; +} + +/** +* @brief NMI_WFI_disassoc +* @details Request to disassociate from the specified peer +* @param[in] +* @return int : Return 0 on Success +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_disassoc(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_disassoc_request *req,void *cookie) +{ + PRINT_D(CFG80211_DBG, "In Disassociation Function\n"); + return 0; +} + +/** +* @brief NMI_WFI_set_wiphy_params +* @details Notify that wiphy parameters have changed; +* @param[in] Changed bitfield (see &enum wiphy_params_flags) describes which values +* have changed. +* @return int : Return 0 on Success +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_set_wiphy_params(struct wiphy *wiphy, u32 changed) +{ + NMI_Sint32 s32Error = NMI_SUCCESS; + tstrCfgParamVal pstrCfgParamVal; + struct NMI_WFI_priv* priv; + + priv = wiphy_priv(wiphy); +// priv = netdev_priv(priv->wdev->netdev); + + pstrCfgParamVal.u32SetCfgFlag = 0; + PRINT_D(CFG80211_DBG,"Setting Wiphy params \n"); + + if(changed & WIPHY_PARAM_RETRY_SHORT) + { + PRINT_D(CFG80211_DBG,"Setting WIPHY_PARAM_RETRY_SHORT %d\n", + priv->dev->ieee80211_ptr->wiphy->retry_short); + pstrCfgParamVal.u32SetCfgFlag |= RETRY_SHORT; + pstrCfgParamVal.short_retry_limit = priv->dev->ieee80211_ptr->wiphy->retry_short; + } + if(changed & WIPHY_PARAM_RETRY_LONG) + { + + PRINT_D(CFG80211_DBG,"Setting WIPHY_PARAM_RETRY_LONG %d\n",priv->dev->ieee80211_ptr->wiphy->retry_long); + pstrCfgParamVal.u32SetCfgFlag |= RETRY_LONG; + pstrCfgParamVal.long_retry_limit = priv->dev->ieee80211_ptr->wiphy->retry_long; + + } + if(changed & WIPHY_PARAM_FRAG_THRESHOLD) + { + PRINT_D(CFG80211_DBG,"Setting WIPHY_PARAM_FRAG_THRESHOLD %d\n",priv->dev->ieee80211_ptr->wiphy->frag_threshold); + pstrCfgParamVal.u32SetCfgFlag |= FRAG_THRESHOLD; + pstrCfgParamVal.frag_threshold = priv->dev->ieee80211_ptr->wiphy->frag_threshold; + + } + + if(changed & WIPHY_PARAM_RTS_THRESHOLD) + { + PRINT_D(CFG80211_DBG, "Setting WIPHY_PARAM_RTS_THRESHOLD %d\n",priv->dev->ieee80211_ptr->wiphy->rts_threshold); + + pstrCfgParamVal.u32SetCfgFlag |= RTS_THRESHOLD; + pstrCfgParamVal.rts_threshold = priv->dev->ieee80211_ptr->wiphy->rts_threshold; + + } + + PRINT_D(CFG80211_DBG,"Setting CFG params in the host interface\n"); + s32Error = hif_set_cfg(priv->hNMIWFIDrv,&pstrCfgParamVal); + if(s32Error) + PRINT_ER("Error in setting WIPHY PARAMS\n"); + + + return s32Error; +} +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32) +/** +* @brief NMI_WFI_set_bitrate_mask +* @details set the bitrate mask configuration +* @param[in] +* @return int : Return 0 on Success +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_set_bitrate_mask(struct wiphy *wiphy, + struct net_device *dev,const u8 *peer, + const struct cfg80211_bitrate_mask *mask) +{ + NMI_Sint32 s32Error = NMI_SUCCESS; + tstrCfgParamVal pstrCfgParamVal; + struct NMI_WFI_priv* priv; + + PRINT_D(CFG80211_DBG, "Setting Bitrate mask function\n"); + + priv = wiphy_priv(wiphy); + //priv = netdev_priv(priv->wdev->netdev); + + pstrCfgParamVal.curr_tx_rate = mask->control[IEEE80211_BAND_2GHZ].legacy; + + PRINT_D(CFG80211_DBG, "Tx rate = %d\n",pstrCfgParamVal.curr_tx_rate); + s32Error = hif_set_cfg(priv->hNMIWFIDrv,&pstrCfgParamVal); + + if(s32Error) + PRINT_ER("Error in setting bitrate\n"); + + return s32Error; + +} + +/** +* @brief NMI_WFI_set_pmksa +* @details Cache a PMKID for a BSSID. This is mostly useful for fullmac +* devices running firmwares capable of generating the (re) association +* RSN IE. It allows for faster roaming between WPA2 BSSIDs. +* @param[in] +* @return int : Return 0 on Success +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_set_pmksa(struct wiphy *wiphy, struct net_device *netdev, + struct cfg80211_pmksa *pmksa) +{ + NMI_Uint32 i; + NMI_Sint32 s32Error = NMI_SUCCESS; + NMI_Uint8 flag = 0; + + struct NMI_WFI_priv* priv = wiphy_priv(wiphy); + + PRINT_D(CFG80211_DBG, "Setting PMKSA\n"); + + + for (i = 0; i < priv->pmkid_list.numpmkid; i++) + { + if (!NMI_memcmp(pmksa->bssid,priv->pmkid_list.pmkidlist[i].bssid, + ETH_ALEN)) + { + /*If bssid already exists and pmkid value needs to reset*/ + flag = PMKID_FOUND; + PRINT_D(CFG80211_DBG, "PMKID already exists\n"); + break; + } + } + if (i < NMI_MAX_NUM_PMKIDS) { + PRINT_D(CFG80211_DBG, "Setting PMKID in private structure\n"); + NMI_memcpy(priv->pmkid_list.pmkidlist[i].bssid, pmksa->bssid, + ETH_ALEN); + NMI_memcpy(priv->pmkid_list.pmkidlist[i].pmkid, pmksa->pmkid, + PMKID_LEN); + if(!(flag == PMKID_FOUND)) + priv->pmkid_list.numpmkid++; + } + else + { + PRINT_ER("Invalid PMKID index\n"); + s32Error = -EINVAL; + } + + if(!s32Error) + { + PRINT_D(CFG80211_DBG, "Setting pmkid in the host interface\n"); + s32Error = host_int_set_pmkid_info(priv->hNMIWFIDrv, &priv->pmkid_list); + } + return s32Error; +} + +/** +* @brief NMI_WFI_del_pmksa +* @details Delete a cached PMKID. +* @param[in] +* @return int : Return 0 on Success +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_del_pmksa(struct wiphy *wiphy, struct net_device *netdev, + struct cfg80211_pmksa *pmksa) +{ + + NMI_Uint32 i; + NMI_Uint8 flag = 0; + NMI_Sint32 s32Error = NMI_SUCCESS; + + struct NMI_WFI_priv* priv = wiphy_priv(wiphy); + //priv = netdev_priv(priv->wdev->netdev); + + PRINT_D(CFG80211_DBG, "Deleting PMKSA keys\n"); + + for (i = 0; i < priv->pmkid_list.numpmkid; i++) + { + if (!NMI_memcmp(pmksa->bssid,priv->pmkid_list.pmkidlist[i].bssid, + ETH_ALEN)) + { + /*If bssid is found, reset the values*/ + PRINT_D(CFG80211_DBG, "Reseting PMKID values\n"); + NMI_memset(&priv->pmkid_list.pmkidlist[i], 0, sizeof(tstrHostIFpmkid)); + flag = PMKID_FOUND; + break; + } + } + + if(i < priv->pmkid_list.numpmkid && priv->pmkid_list.numpmkid > 0) + { + for (; i < (priv->pmkid_list.numpmkid- 1); i++) { + NMI_memcpy(priv->pmkid_list.pmkidlist[i].bssid, + priv->pmkid_list.pmkidlist[i+1].bssid, + ETH_ALEN); + NMI_memcpy(priv->pmkid_list.pmkidlist[i].pmkid, + priv->pmkid_list.pmkidlist[i].pmkid, + PMKID_LEN); + } + priv->pmkid_list.numpmkid--; + } + else { + s32Error = -EINVAL; + } + + return s32Error; +} + +/** +* @brief NMI_WFI_flush_pmksa +* @details Flush all cached PMKIDs. +* @param[in] +* @return int : Return 0 on Success +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev) +{ + struct NMI_WFI_priv* priv = wiphy_priv(wiphy); + //priv = netdev_priv(priv->wdev->netdev); + + PRINT_D(CFG80211_DBG, "Flushing PMKID key values\n"); + + /*Get cashed Pmkids and set all with zeros*/ + NMI_memset(&priv->pmkid_list, 0, sizeof(tstrHostIFpmkidAttr) ); + + return 0; +} +#endif +/** +* @brief NMI_WFI_remain_on_channel +* @details Request the driver to remain awake on the specified +* channel for the specified duration to complete an off-channel +* operation (e.g., public action frame exchange). When the driver is +* ready on the requested channel, it must indicate this with an event +* notification by calling cfg80211_ready_on_channel(). +* @param[in] +* @return int : Return 0 on Success +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_remain_on_channel(struct wiphy *wiphy, + struct net_device *dev,struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + unsigned int duration,u64 *cookie) +{ + PRINT_D(HOSTAPD_DBG, "Remaining on channel\n"); + return 0; +} + +/** +* @brief NMI_WFI_cancel_remain_on_channel +* @details Cancel an on-going remain-on-channel operation. +* This allows the operation to be terminated prior to timeout based on +* the duration value. +* @param[in] struct wiphy *wiphy, +* @param[in] struct net_device *dev +* @param[in] u64 cookie, +* @return int : Return 0 on Success +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_cancel_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, + u64 cookie) +{ + PRINT_D(CFG80211_DBG, "Cancel remain on channel\n"); + return 0; + +} + +/** +* @brief NMI_WFI_set_cqm_rssi_config +* @details Configure connection quality monitor RSSI threshold. +* @param[in] struct wiphy *wiphy: +* @param[in] struct net_device *dev: +* @param[in] s32 rssi_thold: +* @param[in] u32 rssi_hyst: +* @return int : Return 0 on Success +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_set_cqm_rssi_config(struct wiphy *wiphy, + struct net_device *dev, s32 rssi_thold, u32 rssi_hyst) +{ + PRINT_D(CFG80211_DBG, "Setting CQM RSSi Function\n"); + return 0; + +} +/** +* @brief NMI_WFI_dump_station +* @details Configure connection quality monitor RSSI threshold. +* @param[in] struct wiphy *wiphy: +* @param[in] struct net_device *dev +* @param[in] int idx +* @param[in] u8 *mac +* @param[in] struct station_info *sinfo +* @return int : Return 0 on Success +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_dump_station(struct wiphy *wiphy, struct net_device *dev, + int idx, u8 *mac, struct station_info *sinfo) +{ + struct NMI_WFI_priv* priv; + PRINT_D(CFG80211_DBG, "Dumping station information\n"); + + if (idx != 0) + return -ENOENT; + + priv = wiphy_priv(wiphy); + //priv = netdev_priv(priv->wdev->netdev); + + sinfo->filled |= STATION_INFO_SIGNAL ; + + host_int_get_rssi(priv->hNMIWFIDrv, &(sinfo->signal)); + +#if 0 + sinfo->filled |= STATION_INFO_TX_BYTES | + STATION_INFO_TX_PACKETS | + STATION_INFO_RX_BYTES | + STATION_INFO_RX_PACKETS | STATION_INFO_SIGNAL | STATION_INFO_INACTIVE_TIME; + + NMI_SemaphoreAcquire(&SemHandleUpdateStats,NULL); + sinfo->inactive_time = priv->netstats.rx_time > priv->netstats.tx_time ? jiffies_to_msecs(jiffies - priv->netstats.tx_time) : jiffies_to_msecs(jiffies - priv->netstats.rx_time); + sinfo->rx_bytes = priv->netstats.rx_bytes; + sinfo->tx_bytes = priv->netstats.tx_bytes; + sinfo->rx_packets = priv->netstats.rx_packets; + sinfo->tx_packets = priv->netstats.tx_packets; + NMI_SemaphoreRelease(&SemHandleUpdateStats,NULL); +#endif + return 0; + +} + + +/** +* @brief NMI_WFI_set_power_mgmt +* @details +* @param[in] +* @return int : Return 0 on Success. +* @author mdaftedar +* @date 01 JUL 2012 +* @version 1.0NMI_WFI_set_cqmNMI_WFI_set_cqm_rssi_configNMI_WFI_set_cqm_rssi_configNMI_WFI_set_cqm_rssi_configNMI_WFI_set_cqm_rssi_config_rssi_config +*/ +int NMI_WFI_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, + bool enabled, int timeout) +{ + struct NMI_WFI_priv* priv; + PRINT_D(CFG80211_DBG," Power save Enabled= %d , TimeOut = %d\n",enabled,timeout); + + if (wiphy == NMI_NULL) + return -ENOENT; + + priv = wiphy_priv(wiphy); + +#ifndef UNUSE_POWER_MGMT //johnny add 0419 power saving + printk("johnny host_int_set_power_mgmt\n"); + host_int_set_power_mgmt(priv->hNMIWFIDrv, enabled, timeout); +#endif + + return NMI_SUCCESS; + +} +#ifdef NMI_AP_EXTERNAL_MLME +/** +* @brief NMI_WFI_change_virt_intf +* @details Change type/configuration of virtual interface, +* keep the struct wireless_dev's iftype updated. +* @param[in] NONE +* @return int : Return 0 on Success. +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_change_virt_intf(struct wiphy *wiphy,struct net_device *dev, + enum nl80211_iftype type, u32 *flags,struct vif_params *params) +{ + NMI_Sint32 s32Error = NMI_SUCCESS; + struct NMI_WFI_priv* priv; + //struct NMI_WFI_mon_priv* mon_priv; + linux_wlan_t* nic; + + nic = netdev_priv(dev); + + PRINT_D(HOSTAPD_DBG,"In Change virtual interface function\n"); + + priv = wiphy_priv(wiphy); + + PRINT_D(HOSTAPD_DBG,"Wireless interface name =%s\n", dev->name); + + switch(type) + { + case NL80211_IFTYPE_STATION: + + PRINT_D(HOSTAPD_DBG,"Interface type = NL80211_IFTYPE_STATION\n"); + + dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; + nic->iftype = STATION_MODE; + + #ifndef SIMULATION + PRINT_D(HOSTAPD_DBG,"Downloading STATION firmware\n"); + linux_wlan_get_firmware(nic); + #endif + break; + + case NL80211_IFTYPE_AP: + + PRINT_D(HOSTAPD_DBG,"Interface type = NL80211_IFTYPE_AP\n"); + + //mon_priv = netdev_priv(dev); + //mon_priv->real_ndev = dev; + dev->ieee80211_ptr->iftype = NL80211_IFTYPE_AP; + priv->wdev->iftype = type; + nic->iftype = AP_MODE; + + #ifndef SIMULATION + PRINT_D(HOSTAPD_DBG,"Downloading AP firmware\n"); + linux_wlan_get_firmware(nic); + #endif + + break; + default: + PRINT_ER("Unknown interface type= %d\n", type); + s32Error = -EINVAL; + return s32Error; + break; + } + + return s32Error; +} + +/** +* @brief NMI_WFI_add_beacon +* @details Add a beacon with given parameters, @head, @interval +* and @dtim_period will be valid, @tail is optional. +* @param[in] wiphy +* @param[in] dev The net device structure +* @param[in] info Parameters for the beacon to be added +* @return int : Return 0 on Success. +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_add_beacon(struct wiphy *wiphy, struct net_device *dev, + struct beacon_parameters *info) +{ + NMI_Sint32 s32Error = NMI_SUCCESS; + struct NMI_WFI_priv* priv; + + + + priv = wiphy_priv(wiphy); + PRINT_D(HOSTAPD_DBG,"Adding Beacon\n"); + + PRINT_D(HOSTAPD_DBG,"Interval = %d \n DTIM period = %d\n Head length = %d Tail length = %d\n",info->interval , info->dtim_period,info->head_len,info->tail_len ); + + #ifndef NMI_FULLY_HOSTING_AP + s32Error = host_int_add_beacon(priv->hNMIWFIDrv, info->interval, + info->dtim_period, + info->head_len, info->head, + info->tail_len, info->tail); + + #else + s32Error = host_add_beacon(priv->hNMIWFIDrv, info->interval, + info->dtim_period, + info->head_len, info->head, + info->tail_len, info->tail); + #endif + + return s32Error; +} + +/** +* @brief NMI_WFI_set_beacon +* @details Change the beacon parameters for an access point mode +* interface. This should reject the call when no beacon has been +* configured. +* @param[in] +* @return int : Return 0 on Success. +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_set_beacon(struct wiphy *wiphy, struct net_device *dev, + struct beacon_parameters *info) +{ + NMI_Sint32 s32Error = NMI_SUCCESS; + + + PRINT_D(HOSTAPD_DBG,"Setting beacon\n"); + + s32Error = NMI_WFI_add_beacon(wiphy, dev, info); + + return s32Error; +} + +/** +* @brief NMI_WFI_del_beacon +* @details Remove beacon configuration and stop sending the beacon. +* @param[in] +* @return int : Return 0 on Success. +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_del_beacon(struct wiphy *wiphy, struct net_device *dev) +{ + NMI_Sint32 s32Error = NMI_SUCCESS; + struct NMI_WFI_priv* priv; + + + NMI_NULLCHECK(s32Error, wiphy); + + priv = wiphy_priv(wiphy); + + PRINT_D(HOSTAPD_DBG,"Deleting beacon\n"); + + #ifndef NMI_FULLY_HOSTING_AP + s32Error = host_int_del_beacon(priv->hNMIWFIDrv); + #else + s32Error = host_del_beacon(priv->hNMIWFIDrv); + #endif + + NMI_ERRORCHECK(s32Error); + + NMI_CATCH(s32Error) + { + } + return s32Error; +} + + +/** +* @brief NMI_WFI_add_station +* @details Add a new station. +* @param[in] +* @return int : Return 0 on Success. +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_add_station(struct wiphy *wiphy, struct net_device *dev, + u8 *mac, struct station_parameters *params) +{ + NMI_Sint32 s32Error = NMI_SUCCESS; + struct NMI_WFI_priv* priv; + tstrNMI_AddStaParam strStaParams; + linux_wlan_t* nic; + + + NMI_NULLCHECK(s32Error, wiphy); + + priv = wiphy_priv(wiphy); + nic = netdev_priv(dev); + + if(nic->iftype == AP_MODE) + { + + NMI_memcpy(strStaParams.au8BSSID, mac, ETH_ALEN); + NMI_memcpy(priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid],mac,ETH_ALEN); + strStaParams.u16AssocID = params->aid; + strStaParams.u8NumRates = params->supported_rates_len; + strStaParams.pu8Rates = params->supported_rates; + + PRINT_D(CFG80211_DBG,"Adding station parameters %d\n",params->aid); + + PRINT_D(CFG80211_DBG,"BSSID = %x%x%x%x%x%x\n",priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][0],priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][1],priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][2],priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][3],priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][4], + priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][5]); + PRINT_D(HOSTAPD_DBG,"ASSOC ID = %d\n",strStaParams.u16AssocID); + PRINT_D(HOSTAPD_DBG,"Number of supported rates = %d\n",strStaParams.u8NumRates); + + if(params->ht_capa == NMI_NULL) + { + strStaParams.bIsHTSupported = NMI_FALSE; + } + else + { + strStaParams.bIsHTSupported = NMI_TRUE; + strStaParams.u16HTCapInfo = params->ht_capa->cap_info; + strStaParams.u8AmpduParams = params->ht_capa->ampdu_params_info; + NMI_memcpy(strStaParams.au8SuppMCsSet, ¶ms->ht_capa->mcs, NMI_SUPP_MCS_SET_SIZE); + strStaParams.u16HTExtParams = params->ht_capa->extended_ht_cap_info; + strStaParams.u32TxBeamformingCap = params->ht_capa->tx_BF_cap_info; + strStaParams.u8ASELCap = params->ht_capa->antenna_selection_info; + strStaParams.u16FlagsMask = params->sta_flags_mask; + strStaParams.u16FlagsSet = params->sta_flags_set; + + } + + PRINT_D(HOSTAPD_DBG,"IS HT supported = %d\n", strStaParams.bIsHTSupported); + PRINT_D(HOSTAPD_DBG,"Capability Info = %d\n", strStaParams.u16HTCapInfo); + PRINT_D(HOSTAPD_DBG,"AMPDU Params = %d\n",strStaParams.u8AmpduParams); + PRINT_D(HOSTAPD_DBG,"HT Extended params = %d\n",strStaParams.u16HTExtParams); + PRINT_D(HOSTAPD_DBG,"Tx Beamforming Cap = %d\n",strStaParams.u32TxBeamformingCap); + PRINT_D(HOSTAPD_DBG,"Antenna selection info = %d\n",strStaParams.u8ASELCap); + PRINT_D(HOSTAPD_DBG,"Flag Mask = %d\n",strStaParams.u16FlagsMask); + PRINT_D(HOSTAPD_DBG,"Flag Set = %d\n",strStaParams.u16FlagsSet); + + s32Error = host_int_add_station(priv->hNMIWFIDrv, &strStaParams); + NMI_ERRORCHECK(s32Error); + } + + NMI_CATCH(s32Error) + { + } + return s32Error; +} + +/** +* @brief NMI_WFI_del_station +* @details Remove a station; @mac may be NULL to remove all stations. +* @param[in] +* @return int : Return 0 on Success. +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_del_station(struct wiphy *wiphy, struct net_device *dev, + u8 *mac) +{ + NMI_Sint32 s32Error = NMI_SUCCESS; + struct NMI_WFI_priv* priv; + linux_wlan_t* nic; + + + NMI_NULLCHECK(s32Error, wiphy); + NMI_NULLCHECK(s32Error, mac); + + priv = wiphy_priv(wiphy); + nic = netdev_priv(dev); + + if(nic->iftype == AP_MODE) + { + PRINT_D(HOSTAPD_DBG,"Deleting station\n"); + + PRINT_INFO(HOSTAPD_DBG,"With mac address: %x%x%x%x%x%x\n",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]); + + s32Error = host_int_del_station(priv->hNMIWFIDrv , mac); + NMI_ERRORCHECK(s32Error); + } + NMI_CATCH(s32Error) + { + } + return s32Error; +} + +/** +* @brief NMI_WFI_change_station +* @details Modify a given station. +* @param[in] +* @return int : Return 0 on Success. +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_change_station(struct wiphy *wiphy, struct net_device *dev, + u8 *mac, struct station_parameters *params) +{ + NMI_Sint32 s32Error = NMI_SUCCESS; + struct NMI_WFI_priv* priv; + tstrNMI_AddStaParam strStaParams; + linux_wlan_t* nic; + + + PRINT_D(HOSTAPD_DBG,"Change station paramters\n"); + + NMI_NULLCHECK(s32Error, wiphy); + + priv = wiphy_priv(wiphy); + nic = netdev_priv(dev); + + if(nic->iftype == AP_MODE) + { + + NMI_memcpy(strStaParams.au8BSSID, mac, ETH_ALEN); + strStaParams.u16AssocID = params->aid; + strStaParams.u8NumRates = params->supported_rates_len; + strStaParams.pu8Rates = params->supported_rates; + + PRINT_D(HOSTAPD_DBG,"BSSID = %x%x%x%x%x%x\n",strStaParams.au8BSSID[0],strStaParams.au8BSSID[1],strStaParams.au8BSSID[2],strStaParams.au8BSSID[3],strStaParams.au8BSSID[4], + strStaParams.au8BSSID[5]); + PRINT_D(HOSTAPD_DBG,"ASSOC ID = %d\n",strStaParams.u16AssocID); + PRINT_D(HOSTAPD_DBG,"Number of supported rates = %d\n",strStaParams.u8NumRates); + + if(params->ht_capa == NMI_NULL) + { + strStaParams.bIsHTSupported = NMI_FALSE; + } + else + { + strStaParams.bIsHTSupported = NMI_TRUE; + strStaParams.u16HTCapInfo = params->ht_capa->cap_info; + strStaParams.u8AmpduParams = params->ht_capa->ampdu_params_info; + NMI_memcpy(strStaParams.au8SuppMCsSet, ¶ms->ht_capa->mcs, NMI_SUPP_MCS_SET_SIZE); + strStaParams.u16HTExtParams = params->ht_capa->extended_ht_cap_info; + strStaParams.u32TxBeamformingCap = params->ht_capa->tx_BF_cap_info; + strStaParams.u8ASELCap = params->ht_capa->antenna_selection_info; + strStaParams.u16FlagsMask = params->sta_flags_mask; + strStaParams.u16FlagsSet = params->sta_flags_set; + + } + + PRINT_D(HOSTAPD_DBG,"IS HT supported = %d\n", strStaParams.bIsHTSupported); + PRINT_D(HOSTAPD_DBG,"Capability Info = %d\n", strStaParams.u16HTCapInfo); + PRINT_D(HOSTAPD_DBG,"AMPDU Params = %d\n",strStaParams.u8AmpduParams); + PRINT_D(HOSTAPD_DBG,"HT Extended params = %d\n",strStaParams.u16HTExtParams); + PRINT_D(HOSTAPD_DBG,"Tx Beamforming Cap = %d\n",strStaParams.u32TxBeamformingCap); + PRINT_D(HOSTAPD_DBG,"Antenna selection info = %d\n",strStaParams.u8ASELCap); + PRINT_D(HOSTAPD_DBG,"Flag Mask = %d\n",strStaParams.u16FlagsMask); + PRINT_D(HOSTAPD_DBG,"Flag Set = %d\n",strStaParams.u16FlagsSet); + + s32Error = host_int_edit_station(priv->hNMIWFIDrv, &strStaParams); + NMI_ERRORCHECK(s32Error); + } + NMI_CATCH(s32Error) + { + } + return s32Error; +} + + +/** +* @brief NMI_WFI_add_virt_intf +* @details +* @param[in] +* @return int : Return 0 on Success. +* @author mdaftedar +* @date 01 JUL 2012 +* @version 1.0 +*/ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) +int +#else +struct net_device * +#endif +NMI_WFI_add_virt_intf(struct wiphy *wiphy, char *name, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params) +{ + linux_wlan_t *nic; + struct NMI_WFI_priv* priv; + //struct NMI_WFI_mon_priv* mon_priv; + NMI_Sint32 s32Error = NMI_SUCCESS; + priv = wiphy_priv(wiphy); + + + + PRINT_D(HOSTAPD_DBG,"Adding monitor interface\n"); + + nic = netdev_priv(priv->wdev->netdev); + + + if(type == NL80211_IFTYPE_MONITOR) + { + PRINT_D(HOSTAPD_DBG,"Monitor interface mode: Initializing mon interface virtual device driver\n"); + + s32Error = NMI_WFI_init_mon_interface(name,nic->nmc_netdev); + if(!s32Error) + { + PRINT_D(HOSTAPD_DBG,"Setting monitor flag in private structure\n"); + #ifdef SIMULATION + priv = netdev_priv(priv->wdev->netdev); + priv->monitor_flag = 1; + #else + nic = netdev_priv(priv->wdev->netdev); + nic->monitor_flag = 1; + #endif + } + else + PRINT_ER("Error in initializing monitor interface\n "); + } + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) + return s32Error; + #else + return priv->wdev->netdev; + #endif + +} + +/** +* @brief NMI_WFI_del_virt_intf +* @details +* @param[in] +* @return int : Return 0 on Success. +* @author mdaftedar +* @date 01 JUL 2012 +* @version 1.0 +*/ + +int NMI_WFI_del_virt_intf(struct wiphy *wiphy,struct net_device *dev) +{ + PRINT_D(HOSTAPD_DBG,"Deleting virtual interface\n"); + return NMI_SUCCESS; +} + +/** +* @brief NMI_WFI_action +* @details Transmit an action frame +* @param[in] +* @return int : Return 0 on Success. +* @author mdaftedar +* @date 01 JUL 2012 +* @version 1.0 +* */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34) +int NMI_WFI_action(struct wiphy *wiphy, struct net_device *dev, + struct ieee80211_channel *chan,enum nl80211_channel_type channel_type, + const u8 *buf, size_t len, u64 *cookie) +{ + PRINT_D(HOSTAPD_DBG,"In action function\n"); + return NMI_SUCCESS; +} +#endif +#else +/** +* @brief NMI_WFI_frame_register +* @details Notify driver that a management frame type was +* registered. Note that this callback may not sleep, and cannot run +* concurrently with itself. +* @param[in] +* @return NONE. +* @author mdaftedar +* @date 01 JUL 2012 +* @version +*/ +void NMI_WFI_frame_register(struct wiphy *wiphy,struct net_device *dev, + u16 frame_type, bool reg) +{ + PRINT_D(HOSTAPD_DBG,"Frame registeringn"); + +} + +/** +* @brief NMI_WFI_mgmt_tx_frame +* @details +* +* @param[in] +* @return NONE. +* @author mdaftedar +* @date 01 JUL 2012 +* @version +*/ + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,37) +int NMI_WFI_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, + struct ieee80211_channel *chan, bool offchan, + enum nl80211_channel_type channel_type, + bool channel_type_valid, unsigned int wait, + const u8 *buf, size_t len, u64 *cookie) +#else +int NMI_WFI_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + bool channel_type_valid, + const u8 *buf, size_t len, u64 *cookie) +#endif +{ + + PRINT_D(HOSTAPD_DBG,"In NMI_WFI_mgmt_tx function\n"); + return 0; +} +#endif +#endif /*NMI_AP_EXTERNAL_MLME*/ +static struct cfg80211_ops NMI_WFI_cfg80211_ops = { + + .set_channel = NMI_WFI_CfgSetChannel, + .scan = NMI_WFI_CfgScan, + .connect = NMI_WFI_CfgConnect, + .disconnect = NMI_WFI_disconnect, + .add_key = NMI_WFI_add_key, + .del_key = NMI_WFI_del_key, + .get_key = NMI_WFI_get_key, + .set_default_key = NMI_WFI_set_default_key, +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32) + //.dump_survey = NMI_WFI_dump_survey, +#endif + #ifdef NMI_AP_EXTERNAL_MLME + .add_virtual_intf = NMI_WFI_add_virt_intf, + .del_virtual_intf = NMI_WFI_del_virt_intf, + .change_virtual_intf = NMI_WFI_change_virt_intf, + .add_beacon = NMI_WFI_add_beacon, + .set_beacon = NMI_WFI_set_beacon, + .del_beacon = NMI_WFI_del_beacon, + .add_station = NMI_WFI_add_station, + .del_station = NMI_WFI_del_station, + .change_station = NMI_WFI_change_station, + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34) + .action = NMI_WFI_action, + #endif + #else + .mgmt_tx = NMI_WFI_mgmt_tx, + .mgmt_frame_register = NMI_WFI_frame_register, + #endif + #endif /* NMI_AP_EXTERNAL_MLME*/ + .get_station = NMI_WFI_get_station, + .dump_station = NMI_WFI_dump_station, + .change_bss = NMI_WFI_change_bss, + //.auth = NMI_WFI_auth, + //.assoc = NMI_WFI_assoc, + //.deauth = NMI_WFI_deauth, + //.disassoc = NMI_WFI_disassoc, + .set_wiphy_params = NMI_WFI_set_wiphy_params, + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32) + .set_bitrate_mask = NMI_WFI_set_bitrate_mask, + .set_pmksa = NMI_WFI_set_pmksa, + .del_pmksa = NMI_WFI_del_pmksa, + .flush_pmksa = NMI_WFI_flush_pmksa, + .remain_on_channel = NMI_WFI_remain_on_channel, + .cancel_remain_on_channel = NMI_WFI_cancel_remain_on_channel, + //.mgmt_tx_cancel_wait = NMI_WFI_mgmt_tx_cancel_wait, + .set_power_mgmt = NMI_WFI_set_power_mgmt, + .set_cqm_rssi_config = NMI_WFI_set_cqm_rssi_config, +#endif + +}; + + + + + +/** +* @brief NMI_WFI_update_stats +* @details Modify parameters for a given BSS. +* @param[in] +* @return int : Return 0 on Success. +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0NMI_WFI_set_cqmNMI_WFI_set_cqm_rssi_configNMI_WFI_set_cqm_rssi_configNMI_WFI_set_cqm_rssi_configNMI_WFI_set_cqm_rssi_config_rssi_config +*/ +int NMI_WFI_update_stats(struct wiphy *wiphy, u32 pktlen , u8 changed) +{ + + struct NMI_WFI_priv *priv; + + priv = wiphy_priv(wiphy); + //NMI_SemaphoreAcquire(&SemHandleUpdateStats,NULL); +#if 1 + switch(changed) + { + + case NMI_WFI_RX_PKT: + { + //MI_PRINTF("In Rx Receive Packet\n"); + priv->netstats.rx_packets++; + priv->netstats.rx_bytes += pktlen; + priv->netstats.rx_time = get_jiffies_64(); + } + break; + case NMI_WFI_TX_PKT: + { + //NMI_PRINTF("In Tx Receive Packet\n"); + priv->netstats.tx_packets++; + priv->netstats.tx_bytes += pktlen; + priv->netstats.tx_time = get_jiffies_64(); + + } + break; + + default: + break; + } + //NMI_SemaphoreRelease(&SemHandleUpdateStats,NULL); +#endif + return 0; +} +/** +* @brief NMI_WFI_InitPriv +* @details Initialization of the net device, private data +* @param[in] NONE +* @return NONE +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +void NMI_WFI_InitPriv(struct net_device *dev) +{ + + struct NMI_WFI_priv *priv; + priv = netdev_priv(dev); + + priv->netstats.rx_packets = 0; + priv->netstats.tx_packets = 0; + priv->netstats.rx_bytes = 0; + priv->netstats.rx_bytes = 0; + priv->netstats.rx_time = 0; + priv->netstats.tx_time = 0; + + +} +/** +* @brief NMI_WFI_CfgAlloc +* @details Allocation of the wireless device structure and assigning it +* to the cfg80211 operations structure. +* @param[in] NONE +* @return wireless_dev : Returns pointer to wireless_dev structure. +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +struct wireless_dev* NMI_WFI_CfgAlloc(void) +{ + + struct wireless_dev *wdev; + + + PRINT_D(CFG80211_DBG,"Allocating wireless device\n"); + /*Allocating the wireless device structure*/ + wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (!wdev) + { + PRINT_ER("Cannot allocate wireless device\n"); + goto _fail_; + } + + /*Creating a new wiphy, linking wireless structure with the wiphy structure*/ + wdev->wiphy = wiphy_new(&NMI_WFI_cfg80211_ops, sizeof(struct NMI_WFI_priv)); + if (!wdev->wiphy) + { + PRINT_ER("Cannot allocate wiphy\n"); + goto _fail_mem_; + + } + /*wiphy bands*/ + wdev->wiphy->bands[IEEE80211_BAND_2GHZ]= &NMI_WFI_band_2ghz; + + return wdev; + +_fail_mem_: + kfree(wdev); +_fail_: + return NULL; + +} +/** +* @brief NMI_WFI_WiphyRegister +* @details Registering of the wiphy structure and interface modes +* @param[in] NONE +* @return NONE +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +struct wireless_dev* NMI_WFI_WiphyRegister(struct net_device *net) +{ + struct NMI_WFI_priv *priv; + struct wireless_dev *wdev; + NMI_Sint32 s32Error = NMI_SUCCESS; + + PRINT_D(CFG80211_DBG,"Registering wifi device\n"); + + wdev = NMI_WFI_CfgAlloc(); + if(wdev == NULL){ + PRINT_ER("CfgAlloc Failed\n"); + return NULL; + } + + NMI_SemaphoreCreate(&SemHandleUpdateStats,NULL); + /*Return hardware description structure (wiphy)'s priv*/ + priv = wdev_priv(wdev); + + /*Link the wiphy with wireless structure*/ + priv->wdev = wdev; + + /*Maximum number of probed ssid to be added by user for the scan request*/ + wdev->wiphy->max_scan_ssids = MAX_NUM_PROBED_SSID; + + #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32) + /*Maximum number of pmkids to be cashed*/ + wdev->wiphy->max_num_pmkids = NMI_MAX_NUM_PMKIDS; + PRINT_INFO(CFG80211_DBG,"Max number of PMKIDs = %d\n",wdev->wiphy->max_num_pmkids); + #endif + + wdev->wiphy->max_scan_ie_len = 1000; + + /*signal strength in mBm (100*dBm) */ + wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + + /*Set the availaible cipher suites*/ + wdev->wiphy->cipher_suites = cipher_suites; + wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) + /*Setting default managment types: for register action frame: */ + wdev->wiphy->mgmt_stypes = nmi_wfi_cfg80211_mgmt_types; +#endif + /*Setting the wiphy interfcae mode and type before registering the wiphy*/ + wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR); + wdev->iftype = NL80211_IFTYPE_STATION; + + + + PRINT_INFO(CFG80211_DBG,"Max scan ids = %d,Max scan IE len = %d,Signal Type = %d,Interface Modes = %d,Interface Type = %d\n", + wdev->wiphy->max_scan_ssids,wdev->wiphy->max_scan_ie_len,wdev->wiphy->signal_type, + wdev->wiphy->interface_modes, wdev->iftype); + + /*Register wiphy structure*/ + s32Error = wiphy_register(wdev->wiphy); + if (s32Error){ + PRINT_ER("Cannot register wiphy device\n"); + /*should define what action to be taken in such failure*/ + } + else + { + PRINT_D(CFG80211_DBG,"Successful Registering\n"); + } + +#if 0 + /*wdev[i]->wiphy->interface_modes = + BIT(NL80211_IFTYPE_AP); + wdev[i]->iftype = NL80211_IFTYPE_AP; + */ + + /*Pointing the priv structure the netdev*/ + priv= netdev_priv(net); + + /*linking the wireless_dev structure with the netdevice*/ + priv->dev->ieee80211_ptr = wdev; + priv->dev->ml_priv = priv; + wdev->netdev = priv->dev; +#endif + priv->dev = net; +#if 0 + ret = host_int_init(&priv->hNMIWFIDrv); + if(ret) + { + NMI_PRINTF("Error Init Driver\n"); + } +#endif + return wdev; + + +} +/** +* @brief NMI_WFI_WiphyFree +* @details Freeing allocation of the wireless device structure +* @param[in] NONE +* @return NONE +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +int NMI_WFI_InitHostInt(struct net_device *net) +{ + + NMI_Sint32 s32Error = NMI_SUCCESS; + + struct NMI_WFI_priv *priv; + + tstrNMI_SemaphoreAttrs strSemaphoreAttrs; + + NMI_SemaphoreFillDefault(&strSemaphoreAttrs); + + ///////////////////////////////////////// + //strSemaphoreAttrs.u32InitCount = 0; + NMI_SemaphoreCreate(&hSemScanReq, &strSemaphoreAttrs); + + priv = wdev_priv(net->ieee80211_ptr); + s32Error = host_int_init(&priv->hNMIWFIDrv); + if(s32Error) + { + PRINT_ER("Error while initializing hostinterface\n"); + } + return s32Error; +} + +/** +* @brief NMI_WFI_WiphyFree +* @details Freeing allocation of the wireless device structure +* @param[in] NONE +* @return NONE +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +int NMI_WFI_DeInitHostInt(struct net_device *net) +{ + + NMI_Sint32 s32Error = NMI_SUCCESS; + + + struct NMI_WFI_priv *priv; + priv = wdev_priv(net->ieee80211_ptr); + + NMI_SemaphoreDestroy(&hSemScanReq,NULL); + + s32Error = host_int_deinit(priv->hNMIWFIDrv); + if(s32Error) + { + PRINT_ER("Error while deintializing hostinterface\n"); + } + return s32Error; +} + + +/** +* @brief NMI_WFI_WiphyFree +* @details Freeing allocation of the wireless device structure +* @param[in] NONE +* @return NONE +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +void NMI_WFI_WiphyFree(struct net_device *net) +{ + + PRINT_D(CFG80211_DBG,"Unregistering wiphy\n"); + + if(net == NULL){ + PRINT_D(INIT_DBG,"net_device is NULL\n"); + return; + } + + if(net->ieee80211_ptr == NULL){ + PRINT_D(INIT_DBG,"ieee80211_ptr is NULL\n"); + return; + } + + if(net->ieee80211_ptr->wiphy == NULL){ + PRINT_D(INIT_DBG,"wiphy is NULL\n"); + return; + } + + wiphy_unregister(net->ieee80211_ptr->wiphy); + + PRINT_D(INIT_DBG,"Freeing wiphy\n"); + wiphy_free(net->ieee80211_ptr->wiphy); + kfree(net->ieee80211_ptr); + +} diff --git a/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/NMI_WFI_NetDevice.c b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/NMI_WFI_NetDevice.c new file mode 100755 index 00000000..41847cba --- /dev/null +++ b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/NMI_WFI_NetDevice.c @@ -0,0 +1,969 @@ +/*! +* @file NMI_WFI_NetDevice.c +* @brief File Operations OS wrapper functionality +* @author mdaftedar +* @sa NMI_WFI_NetDevice.h +* @date 01 MAR 2012 +* @version 1.0 +*/ + +#ifdef SIMULATION + +#include "linux/include/NMI_WFI_CfgOperations.h" +#include "host_interface.h" + + +MODULE_AUTHOR("Mai Daftedar"); +MODULE_LICENSE("Dual BSD/GPL"); + + +struct net_device *NMI_WFI_devs[2]; + +/* +* Transmitter lockup simulation, normally disabled. +*/ +static int lockup = 0; +module_param(lockup, int, 0); + +static int timeout = NMI_WFI_TIMEOUT; +module_param(timeout, int, 0); + +/* +* Do we run in NAPI mode? +*/ +static int use_napi = 0; +module_param(use_napi, int, 0); + + +/* +* A structure representing an in-flight packet. +*/ +struct NMI_WFI_packet { + struct NMI_WFI_packet *next; + struct net_device *dev; + int datalen; + u8 data[ETH_DATA_LEN]; +}; + + + +int pool_size = 8; +module_param(pool_size, int, 0); + + +static void NMI_WFI_TxTimeout(struct net_device *dev); +static void (*NMI_WFI_Interrupt)(int, void *, struct pt_regs *); + +/** +* @brief NMI_WFI_SetupPool +* @details Set up a device's packet pool. +* @param[in] struct net_device *dev : Network Device Pointer +* @return NONE +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ + void NMI_WFI_SetupPool(struct net_device *dev) + { + struct NMI_WFI_priv *priv = netdev_priv(dev); + int i; + struct NMI_WFI_packet *pkt; + + priv->ppool = NULL; + for (i = 0; i < pool_size; i++) { + pkt = kmalloc (sizeof (struct NMI_WFI_packet), GFP_KERNEL); + if (pkt == NULL) { + printk (KERN_NOTICE "Ran out of memory allocating packet pool\n"); + return; + } + pkt->dev = dev; + pkt->next = priv->ppool; + priv->ppool = pkt; + } + } + +/** +* @brief NMI_WFI_TearDownPool +* @details Internal cleanup function that's called after the network device + driver is unregistered +* @param[in] struct net_device *dev : Network Device Driver +* @return NONE +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +void NMI_WFI_TearDownPool(struct net_device *dev) + { + struct NMI_WFI_priv *priv = netdev_priv(dev); + struct NMI_WFI_packet *pkt; + + while ((pkt = priv->ppool)) { + priv->ppool = pkt->next; + kfree (pkt); + /* FIXME - in-flight packets ? */ + } + } + +/** +* @brief NMI_WFI_GetTxBuffer +* @details Buffer/pool management +* @param[in] net_device *dev : Network Device Driver Structure +* @return struct NMI_WFI_packet +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ + struct NMI_WFI_packet *NMI_WFI_GetTxBuffer(struct net_device *dev) + { + struct NMI_WFI_priv *priv = netdev_priv(dev); + unsigned long flags; + struct NMI_WFI_packet *pkt; + + spin_lock_irqsave(&priv->lock, flags); + pkt = priv->ppool; + priv->ppool = pkt->next; + if (priv->ppool == NULL) { + printk (KERN_INFO "Pool empty\n"); + netif_stop_queue(dev); + } + spin_unlock_irqrestore(&priv->lock, flags); + return pkt; + } +/** +* @brief NMI_WFI_ReleaseBuffer +* @details Buffer/pool management +* @param[in] NMI_WFI_packet *pkt : Structure holding in-flight packet +* @return NONE +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +void NMI_WFI_ReleaseBuffer(struct NMI_WFI_packet *pkt) +{ + unsigned long flags; + struct NMI_WFI_priv *priv = netdev_priv(pkt->dev); + + spin_lock_irqsave(&priv->lock, flags); + pkt->next = priv->ppool; + priv->ppool = pkt; + spin_unlock_irqrestore(&priv->lock, flags); + if (netif_queue_stopped(pkt->dev) && pkt->next == NULL) + netif_wake_queue(pkt->dev); +} + +/** +* @brief NMI_WFI_EnqueueBuf +* @details Enqueuing packets in an RX buffer queue +* @param[in] NMI_WFI_packet *pkt : Structure holding in-flight packet +* @param[in] net_device *dev : Network Device Driver Structure +* @return NONE +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +void NMI_WFI_EnqueueBuf(struct net_device *dev, struct NMI_WFI_packet *pkt) +{ + unsigned long flags; + struct NMI_WFI_priv *priv = netdev_priv(dev); + + spin_lock_irqsave(&priv->lock, flags); + pkt->next = priv->rx_queue; /* FIXME - misorders packets */ + priv->rx_queue = pkt; + spin_unlock_irqrestore(&priv->lock, flags); + } + +/** +* @brief NMI_WFI_DequeueBuf +* @details Dequeuing packets from the RX buffer queue +* @param[in] net_device *dev : Network Device Driver Structure +* @return NMI_WFI_packet *pkt : Structure holding in-flight pac +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +struct NMI_WFI_packet *NMI_WFI_DequeueBuf(struct net_device *dev) +{ + struct NMI_WFI_priv *priv = netdev_priv(dev); + struct NMI_WFI_packet *pkt; + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + pkt = priv->rx_queue; + if (pkt != NULL) + priv->rx_queue = pkt->next; + spin_unlock_irqrestore(&priv->lock, flags); + return pkt; + } +/** +* @brief NMI_WFI_RxInts +* @details Enable and disable receive interrupts. +* @param[in] net_device *dev : Network Device Driver Structure +* @param[in] enable : Enable/Disable flag +* @return NONE +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static void NMI_WFI_RxInts(struct net_device *dev, int enable) +{ + struct NMI_WFI_priv *priv = netdev_priv(dev); + priv->rx_int_enabled = enable; +} + +/** +* @brief NMI_WFI_Open +* @details Open Network Device Driver, called when the network + interface is opened. It starts the interface's transmit queue. +* @param[in] net_device *dev : Network Device Driver Structure +* @param[in] enable : Enable/Disable flag +* @return int : Returns 0 upon success. +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +int NMI_WFI_Open(struct net_device *dev) +{ + /* request_region(), request_irq(), .... (like fops->open) */ + /* + * Assign the hardware address of the board: use "\0SNULx", where + * x is 0 or 1. The first byte is '\0' to avoid being a multicast + * address (the first byte of multicast addrs is odd). + */ + memcpy(dev->dev_addr, "\0WLAN0", ETH_ALEN); + if (dev == NMI_WFI_devs[1]) + dev->dev_addr[ETH_ALEN-1]++; /* \0SNUL1 */ + + NMI_WFI_InitHostInt(dev); + netif_start_queue(dev); + return 0; +} +/** +* @brief NMI_WFI_Release +* @details Release Network Device Driver, called when the network + interface is stopped or brought down. This function marks + the network driver as not being able to transmit +* @param[in] net_device *dev : Network Device Driver Structure +* @return int : Return 0 on Success. +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +int NMI_WFI_Release(struct net_device *dev) +{ + /* release ports, irq and such -- like fops->close */ + + netif_stop_queue(dev); /* can't transmit any more */ + + return 0; + } +/** +* @brief NMI_WFI_Config +* @details Configuration changes (passed on by ifconfig) +* @param[in] net_device *dev : Network Device Driver Structure +* @param[in] struct ifmap *map : Contains the ioctl implementation for the + network driver. +* @return int : Return 0 on Success. +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +int NMI_WFI_Config(struct net_device *dev, struct ifmap *map) +{ + if (dev->flags & IFF_UP) /* can't act on a running interface */ + return -EBUSY; + + /* Don't allow changing the I/O address */ + if (map->base_addr != dev->base_addr) { + printk(KERN_WARNING "NMI_WFI: Can't change I/O address\n"); + return -EOPNOTSUPP; + } + + /* Allow changing the IRQ */ + if (map->irq != dev->irq) { + dev->irq = map->irq; + /* request_irq() is delayed to open-time */ + } + + /* ignore other fields */ + return 0; +} +/** +* @brief NMI_WFI_Rx +* @details Receive a packet: retrieve, encapsulate and pass over to upper + levels +* @param[in] net_device *dev : Network Device Driver Structure +* @param[in] NMI_WFI_packet : +* @return NONE +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +void NMI_WFI_Rx(struct net_device *dev, struct NMI_WFI_packet *pkt) +{ + int i; + struct sk_buff *skb; + struct NMI_WFI_priv *priv = netdev_priv(dev); + s8 rssi; + /* + * The packet has been retrieved from the transmission + * medium. Build an skb around it, so upper layers can handle it + */ + + + skb = dev_alloc_skb(pkt->datalen + 2); + if (!skb) { + if (printk_ratelimit()) + printk(KERN_NOTICE "NMI_WFI rx: low on mem - packet dropped\n"); + priv->stats.rx_dropped++; + goto out; + } + skb_reserve(skb, 2); /* align IP on 16B boundary */ + memcpy(skb_put(skb, pkt->datalen), pkt->data, pkt->datalen); + + if(priv->monitor_flag) + { + PRINT_INFO(RX_DBG,"In monitor device name %s\n", dev->name); + priv = wiphy_priv(priv->dev->ieee80211_ptr->wiphy); + printk("VALUE PASSED IN OF HRWD %p\n", priv->hNMIWFIDrv); + // host_int_get_rssi(priv->hNMIWFIDrv, &(rssi)); + // NMI_PRINTF("RSSI value is %d\n", rssi); + if(INFO) + { + for (i=14 ; i<skb->len; i++) + PRINT_INFO(RX_DBG,"RXdata[%d] %02x\n",i,skb->data[i]); + } + NMI_WFI_monitor_rx(dev, skb); + return; + } +#if 0 + NMI_PRINTF("In RX NORMAl Device name %s\n", dev->name); + /* 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 */ + NMI_WFI_update_stats(priv->dev->ieee80211_ptr->wiphy ,pkt->datalen,NMI_WFI_RX_PKT); + netif_rx(skb); +#endif +out: + return; +} + +/** +* @brief NMI_WFI_Poll +* @details The poll implementation +* @param[in] struct napi_struct *napi : +* @param[in] int budget : +* @return int : Return 0 on Success. +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static int NMI_WFI_Poll(struct napi_struct *napi, int budget) +{ + int npackets = 0; + struct sk_buff *skb; + struct NMI_WFI_priv *priv = container_of(napi, struct NMI_WFI_priv, napi); + struct net_device *dev = priv->dev; + struct NMI_WFI_packet *pkt; + + while (npackets < budget && priv->rx_queue) { + pkt = NMI_WFI_DequeueBuf(dev); + skb = dev_alloc_skb(pkt->datalen + 2); + if (! skb) { + if (printk_ratelimit()) + printk(KERN_NOTICE "NMI_WFI: packet dropped\n"); + priv->stats.rx_dropped++; + NMI_WFI_ReleaseBuffer(pkt); + continue; + } + skb_reserve(skb, 2); /* align IP on 16B boundary */ + memcpy(skb_put(skb, pkt->datalen), pkt->data, pkt->datalen); + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */ + netif_receive_skb(skb); + /* Maintain stats */ + npackets++; + NMI_WFI_update_stats(priv->dev->ieee80211_ptr->wiphy,pkt->datalen,NMI_WFI_RX_PKT); + NMI_WFI_ReleaseBuffer(pkt); + } + /* If we processed all packets, we're done; tell the kernel and re-enable ints */ + if (npackets < budget) { + napi_complete(napi); + NMI_WFI_RxInts(dev, 1); + } + return npackets; + } + +/** +* @brief NMI_WFI_Poll +* @details The typical interrupt entry point +* @param[in] struct napi_struct *napi : +* @param[in] int budget : +* @return int : Return 0 on Success. +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static void NMI_WFI_RegularInterrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + int statusword; + struct NMI_WFI_priv *priv; + struct NMI_WFI_packet *pkt = NULL; + /* + * As usual, check the "device" pointer to be sure it is + * really interrupting. + * Then assign "struct device *dev" + */ + struct net_device *dev = (struct net_device *)dev_id; + /* ... and check with hw if it's really ours */ + + /* paranoid */ + if (!dev) + return; + + /* Lock the device */ + priv = netdev_priv(dev); + spin_lock(&priv->lock); + + /* retrieve statusword: real netdevices use I/O instructions */ + statusword = priv->status; + priv->status = 0; + if (statusword & NMI_WFI_RX_INTR) { + /* send it to NMI_WFI_rx for handling */ + pkt = priv->rx_queue; + if (pkt) { + priv->rx_queue = pkt->next; + NMI_WFI_Rx(dev, pkt); + } + } + if (statusword & NMI_WFI_TX_INTR) { + /* a transmission is over: free the skb */ + NMI_WFI_update_stats(priv->dev->ieee80211_ptr->wiphy,priv->tx_packetlen,NMI_WFI_TX_PKT); + dev_kfree_skb(priv->skb); + } + + /* Unlock the device and we are done */ + spin_unlock(&priv->lock); + if (pkt) NMI_WFI_ReleaseBuffer(pkt); /* Do this outside the lock! */ + return; +} +/** +* @brief NMI_WFI_NapiInterrupt +* @details A NAPI interrupt handler +* @param[in] irq: +* @param[in] dev_id: +* @param[in] pt_regs: +* @return NONE +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +static void NMI_WFI_NapiInterrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + int statusword; + struct NMI_WFI_priv *priv; + + /* + * As usual, check the "device" pointer for shared handlers. + * Then assign "struct device *dev" + */ + struct net_device *dev = (struct net_device *)dev_id; + /* ... and check with hw if it's really ours */ + + /* paranoid */ + if (!dev) + return; + + /* Lock the device */ + priv = netdev_priv(dev); + spin_lock(&priv->lock); + + /* retrieve statusword: real netdevices use I/O instructions */ + statusword = priv->status; + priv->status = 0; + if (statusword & NMI_WFI_RX_INTR) { + NMI_WFI_RxInts(dev, 0); /* Disable further interrupts */ + napi_schedule(&priv->napi); + } + if (statusword & NMI_WFI_TX_INTR) { + /* a transmission is over: free the skb */ + + NMI_WFI_update_stats(priv->dev->ieee80211_ptr->wiphy,priv->tx_packetlen,NMI_WFI_TX_PKT); + dev_kfree_skb(priv->skb); + } + + /* Unlock the device and we are done */ + spin_unlock(&priv->lock); + return; +} + +/** +* @brief MI_WFI_HwTx +* @details Transmit a packet (low level interface) +* @param[in] buf: +* @param[in] len: +* @param[in] net_device *dev: +* @return NONE +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ + void NMI_WFI_HwTx(char *buf, int len, struct net_device *dev) +{ + /* + * This function deals with hw details. This interface loops + * back the packet to the other NMI_WFI interface (if any). + * In other words, this function implements the NMI_WFI behaviour, + * while all other procedures are rather device-independent + */ + struct iphdr *ih; + struct net_device *dest; + struct NMI_WFI_priv *priv; + u32 *saddr, *daddr; + struct NMI_WFI_packet *tx_buffer; + + + /* I am paranoid. Ain't I? */ + if (len < sizeof(struct ethhdr) + sizeof(struct iphdr)) { + printk("NMI_WFI: Hmm... packet too short (%i octets)\n", + len); + return; + } + + if (0) { /* enable this conditional to look at the data */ + int i; + printk("len is %i",len); + for (i=14 ; i<len; i++) + printk("TXdata[%d] %02x\n",i,buf[i]&0xff); + // printk("\n"); + } + /* + * Ethhdr is 14 bytes, but the kernel arranges for iphdr + * to be aligned (i.e., ethhdr is unaligned) + */ + ih = (struct iphdr *)(buf+sizeof(struct ethhdr)); + saddr = &ih->saddr; + daddr = &ih->daddr; + + ((u8 *)saddr)[2] ^= 1; /* change the third octet (class C) */ + ((u8 *)daddr)[2] ^= 1; + + ih->check = 0; /* and rebuild the checksum (ip needs it) */ + ih->check = ip_fast_csum((unsigned char *)ih,ih->ihl); + + + if (dev == NMI_WFI_devs[0]) + PDEBUGG("%08x:%05i --> %08x:%05i\n", + ntohl(ih->saddr),ntohs(((struct tcphdr *)(ih+1))->source), + ntohl(ih->daddr),ntohs(((struct tcphdr *)(ih+1))->dest)); + else + PDEBUGG("%08x:%05i <-- %08x:%05i\n", + ntohl(ih->daddr),ntohs(((struct tcphdr *)(ih+1))->dest), + ntohl(ih->saddr),ntohs(((struct tcphdr *)(ih+1))->source)); + + /* + * Ok, now the packet is ready for transmission: first simulate a + * receive interrupt on the twin device, then a + * transmission-done on the transmitting device + */ + dest = NMI_WFI_devs[dev == NMI_WFI_devs[0] ? 1 : 0]; + priv = netdev_priv(dest); + + tx_buffer = NMI_WFI_GetTxBuffer(dev); + tx_buffer->datalen = len; + memcpy(tx_buffer->data, buf, len); + NMI_WFI_EnqueueBuf(dest, tx_buffer); + if (priv->rx_int_enabled) { + priv->status |= NMI_WFI_RX_INTR; + NMI_WFI_Interrupt(0, dest, NULL); + } + + priv = netdev_priv(dev); + priv->tx_packetlen = len; + priv->tx_packetdata = buf; + priv->status |= NMI_WFI_TX_INTR; + if (lockup && ((priv->stats.tx_packets + 1) % lockup) == 0) { + /* Simulate a dropped transmit interrupt */ + netif_stop_queue(dev); + PDEBUG("Simulate lockup at %ld, txp %ld\n", jiffies, + (unsigned long) priv->stats.tx_packets); + } + else + NMI_WFI_Interrupt(0, dev, NULL); + +} + +/** +* @brief NMI_WFI_Tx +* @details Transmit a packet (called by the kernel) +* @param[in] sk_buff *skb: +* @param[in] net_device *dev: +* @return NONE +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +int NMI_WFI_Tx(struct sk_buff *skb, struct net_device *dev) +{ + int len; + char *data, shortpkt[ETH_ZLEN]; + struct NMI_WFI_priv *priv = netdev_priv(dev); + + // priv = wiphy_priv(priv->dev->ieee80211_ptr->wiphy); + + // if(priv->monitor_flag) + // mac80211_hwsim_monitor_rx(skb); + + + data = skb->data; + len = skb->len; + + if (len < ETH_ZLEN) { + memset(shortpkt, 0, ETH_ZLEN); + memcpy(shortpkt, skb->data, skb->len); + len = ETH_ZLEN; + data = shortpkt; + } + dev->trans_start = jiffies; /* save the timestamp */ + + /* Remember the skb, so we can free it at interrupt time */ + priv->skb = skb; + + /* actual deliver of data is device-specific, and not shown here */ + NMI_WFI_HwTx(data, len, dev); + + return 0; /* Our simple device can not fail */ + } + +/** +* @brief NMI_WFI_TxTimeout +* @details Deal with a transmit timeout. +* @param[in] net_device *dev: +* @return NONE +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +void NMI_WFI_TxTimeout(struct net_device *dev) +{ + struct NMI_WFI_priv *priv = netdev_priv(dev); + + PDEBUG("Transmit timeout at %ld, latency %ld\n", jiffies, + jiffies - dev->trans_start); + /* Simulate a transmission interrupt to get things moving */ + priv->status = NMI_WFI_TX_INTR; + NMI_WFI_Interrupt(0, dev, NULL); + priv->stats.tx_errors++; + netif_wake_queue(dev); + return; +} + +/** +* @brief NMI_WFI_Ioctl +* @details Ioctl commands +* @param[in] net_device *dev: +* @param[in] ifreq *rq +* @param[in] cmd: +* @return int : Return 0 on Success +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +int NMI_WFI_Ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + PDEBUG("ioctl\n"); + return 0; +} + +/** +* @brief NMI_WFI_Stat +* @details Return statistics to the caller +* @param[in] net_device *dev: +* @return NMI_WFI_Stats : Return net_device_stats stucture with the + network device driver private data contents. +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +struct net_device_stats *NMI_WFI_Stats(struct net_device *dev) +{ + struct NMI_WFI_priv *priv = netdev_priv(dev); + return &priv->stats; +} + +/** +* @brief NMI_WFI_RebuildHeader +* @details This function is called to fill up an eth header, since arp is not +* available on the interface +* @param[in] sk_buff *skb: +* @return int : Return 0 on Success +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +int NMI_WFI_RebuildHeader(struct sk_buff *skb) +{ + struct ethhdr *eth = (struct ethhdr *) skb->data; + struct net_device *dev = skb->dev; + + memcpy(eth->h_source, dev->dev_addr, dev->addr_len); + memcpy(eth->h_dest, dev->dev_addr, dev->addr_len); + eth->h_dest[ETH_ALEN-1] ^= 0x01; /* dest is us xor 1 */ + return 0; +} +/** +* @brief NMI_WFI_RebuildHeader +* @details This function is called to fill up an eth header, since arp is not +* available on the interface +* @param[in] sk_buff *skb: +* @param[in] struct net_device *dev: +* @param[in] unsigned short type: +* @param[in] const void *saddr, +* @param[in] const void *daddr: +* @param[in] unsigned int len +* @return int : Return 0 on Success +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +int NMI_WFI_Header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, const void *daddr, const void *saddr, + unsigned int len) +{ + struct ethhdr *eth = (struct ethhdr *)skb_push(skb,ETH_HLEN); + + eth->h_proto = htons(type); + memcpy(eth->h_source, saddr ? saddr : dev->dev_addr, dev->addr_len); + memcpy(eth->h_dest, daddr ? daddr : dev->dev_addr, dev->addr_len); + eth->h_dest[ETH_ALEN-1] ^= 0x01; /* dest is us xor 1 */ + return (dev->hard_header_len); +} + +/** +* @brief NMI_WFI_ChangeMtu +* @details The "change_mtu" method is usually not needed. +* If you need it, it must be like this. +* @param[in] net_device *dev : Network Device Driver Structure +* @param[in] new_mtu : +* @return int : Returns 0 on Success. +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +int NMI_WFI_ChangeMtu(struct net_device *dev, int new_mtu) +{ + unsigned long flags; + struct NMI_WFI_priv *priv = netdev_priv(dev); + spinlock_t *lock = &priv->lock; + + /* check ranges */ + if ((new_mtu < 68) || (new_mtu > 1500)) + return -EINVAL; + /* + * Do anything you need, and the accept the value + */ + spin_lock_irqsave(lock, flags); + dev->mtu = new_mtu; + spin_unlock_irqrestore(lock, flags); + return 0; /* success */ +} + +static const struct header_ops NMI_WFI_header_ops = { + .create = NMI_WFI_Header, + .rebuild = NMI_WFI_RebuildHeader, + .cache = NULL, /* disable caching */ +}; + + +static const struct net_device_ops NMI_WFI_netdev_ops = { + .ndo_open = NMI_WFI_Open, + .ndo_stop = NMI_WFI_Release, + .ndo_set_config = NMI_WFI_Config, + .ndo_start_xmit = NMI_WFI_Tx, + .ndo_do_ioctl = NMI_WFI_Ioctl, + .ndo_get_stats = NMI_WFI_Stats, + .ndo_change_mtu = NMI_WFI_ChangeMtu, + .ndo_tx_timeout = NMI_WFI_TxTimeout, + }; + +/** +* @brief NMI_WFI_Init +* @details The init function (sometimes called probe). +* It is invoked by register_netdev() +* @param[in] net_device *dev: +* @return NONE +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +void NMI_WFI_Init(struct net_device *dev) +{ + struct NMI_WFI_priv *priv; + + + /* + * Then, assign other fields in dev, using ether_setup() and some + * hand assignments + */ + ether_setup(dev); /* assign some of the fields */ + //1- Allocate space + + dev->netdev_ops = &NMI_WFI_netdev_ops; + dev->header_ops = &NMI_WFI_header_ops; + dev->watchdog_timeo = timeout; + /* keep the default flags, just add NOARP */ + dev->flags |= IFF_NOARP; + dev->features |= NETIF_F_NO_CSUM; + /* + * Then, initialize the priv field. This encloses the statistics + * and a few private fields. + */ + priv = netdev_priv(dev); + memset(priv, 0, sizeof(struct NMI_WFI_priv)); + priv->dev = dev; + netif_napi_add(dev, &priv->napi, NMI_WFI_Poll, 2); + /* The last parameter above is the NAPI "weight". */ + spin_lock_init(&priv->lock); + NMI_WFI_RxInts(dev, 1); /* enable receive interrupts */ + NMI_WFI_SetupPool(dev); + } + +/** +* @brief NMI_WFI_Stat +* @details Return statistics to the caller +* @param[in] net_device *dev: +* @return NMI_WFI_Stats : Return net_device_stats stucture with the + network device driver private data contents. +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ + +void NMI_WFI_Cleanup(void) +{ + int i; + struct NMI_WFI_priv *priv[2]; + + /*if(hwsim_mon!=NULL) + { + printk("Freeing monitor interface\n"); + unregister_netdev(hwsim_mon); + free_netdev(hwsim_mon); + }*/ + for (i = 0; i < 2;i++) + { + priv[i] = netdev_priv(NMI_WFI_devs[i]); + + if (NMI_WFI_devs[i]) + { + NMI_PRINTF("Unregistering\n"); + unregister_netdev(NMI_WFI_devs[i]); + NMI_WFI_TearDownPool(NMI_WFI_devs[i]); + free_netdev(NMI_WFI_devs[i]); + NMI_PRINTF("[NETDEV]Stopping interface\n"); + NMI_WFI_DeInitHostInt(NMI_WFI_devs[i]); + NMI_WFI_WiphyFree(NMI_WFI_devs[i]); + } + + } + //unregister_netdev(hwsim_mon); + NMI_WFI_deinit_mon_interface(); + return; +} + + +void StartConfigSim(void); + + + + + + + +/** +* @brief NMI_WFI_Stat +* @details Return statistics to the caller +* @param[in] net_device *dev: +* @return NMI_WFI_Stats : Return net_device_stats stucture with the + network device driver private data contents. +* @author mdaftedar +* @date 01 MAR 2012 +* @version 1.0 +*/ +int NMI_WFI_InitModule(void) +{ + + int result, i, ret = -ENOMEM; + struct NMI_WFI_priv *priv[2],*netpriv; + struct wireless_dev *wdev; + NMI_WFI_Interrupt = use_napi ? NMI_WFI_NapiInterrupt : NMI_WFI_RegularInterrupt; + char buf[IFNAMSIZ]; + + for (i = 0; i < 2; i++) + { + + /* Allocate the net devices */ + NMI_WFI_devs[i] = alloc_netdev(sizeof(struct NMI_WFI_priv), "wlan%d", + NMI_WFI_Init); + if(NMI_WFI_devs[i] == NULL) + goto out; + //priv[i] = netdev_priv(NMI_WFI_devs[i]); + + wdev = NMI_WFI_WiphyRegister(NMI_WFI_devs[i]); + NMI_WFI_devs[i]->ieee80211_ptr = wdev; + netpriv = netdev_priv(NMI_WFI_devs[i]); + netpriv->dev->ieee80211_ptr = wdev; + netpriv->dev->ml_priv = netpriv; + wdev->netdev = netpriv->dev; + + /*Registering the net device*/ + if ((result = register_netdev(NMI_WFI_devs[i]))) + printk("NMI_WFI: error %i registering device \"%s\"\n", + result, NMI_WFI_devs[i]->name); + else + ret = 0; + } + + + /*init NMi driver */ + priv[0] = netdev_priv(NMI_WFI_devs[0]); + priv[1] = netdev_priv(NMI_WFI_devs[1]); + //printk("Net dev handler in int %lu\n",&priv[0]->hNMIWFIDrv); + + if(priv[1]->dev->ieee80211_ptr->wiphy->interface_modes && BIT(NL80211_IFTYPE_MONITOR) ) + { + //snprintf(buf, IFNAMSIZ, "mon.%s", priv[1]->dev->name); + // printk("Initializing mon interface %s\n", buf); + // NMI_WFI_init_mon_interface(); + // priv[1]->monitor_flag = 1; + + } + priv[0]->bCfgScanning = NMI_FALSE; + priv[0]->u32RcvdChCount = 0; + + NMI_memset(priv[0]->au8AssociatedBss, 0xFF, ETH_ALEN); + + + //ret = host_int_init(&priv[0]->hNMIWFIDrv); + /*copy handle to the other driver*/ + //priv[1]->hNMIWFIDrv = priv[0]->hNMIWFIDrv; + if(ret) + { + NMI_PRINTF("Error Init Driver\n"); + } + + + out: + if (ret) + NMI_WFI_Cleanup(); + return ret; + + +} + + +module_init(NMI_WFI_InitModule); +module_exit(NMI_WFI_Cleanup); + +#endif diff --git a/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/linux_mon.c b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/linux_mon.c new file mode 100755 index 00000000..0f3b8471 --- /dev/null +++ b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/linux_mon.c @@ -0,0 +1,521 @@ +/*! +* @file linux_mon.c +* @brief File Operations OS wrapper functionality +* @author mdaftedar +* @sa NMI_WFI_NetDevice.h +* @date 01 MAR 2012 +* @version 1.0 +*/ + +#ifndef SIMULATION +#include "NMI_WFI_CfgOperations.h" +#include "linux_wlan_common.h" +#include "nmi_wlan_if.h" +#include "nmi_wlan.h" +#endif +#ifdef NMI_AP_EXTERNAL_MLME +#ifdef SIMULATION +#include "NMI_WFI_CfgOperations.h" +#endif +struct nmi_wfi_radiotap_hdr { + struct ieee80211_radiotap_header hdr; + u8 rate; + // u32 channel; +}__attribute__((packed)); +struct nmi_wfi_radiotap_cb_hdr { + struct ieee80211_radiotap_header hdr; + u8 rate; + u8 dump; + u16 tx_flags; + // u32 channel; +}__attribute__((packed)); + +static struct net_device *nmi_wfi_mon = NULL; /* global monitor netdev */ + +#ifdef SIMULATION +extern int NMI_WFI_Tx(struct sk_buff *skb, struct net_device *dev); +#elif USE_WIRELESS +extern int mac_xmit(struct sk_buff *skb, struct net_device *dev); +#endif + + +NMI_Uint8 srcAdd[6]; +NMI_Uint8 bssid[6]; +/** +* @brief NMI_WFI_monitor_rx +* @details +* @param[in] +* @return int : Return 0 on Success +* @author mdaftedar +* @date 12 JUL 2012 +* @version 1.0 +*/ + +#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */ +#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive*/ +#define IS_MANAGMEMENT 0x100 +#define IS_MANAGMEMENT_CALLBACK 0x080 +#define IS_MGMT_STATUS_SUCCES 0x040 +#define GET_PKT_OFFSET(a) (((a) >> 22) & 0x1ff) + +void NMI_WFI_monitor_rx(uint8_t *buff, uint32_t size) +{ + + //NMI_Uint32 i; + + + uint32_t header,pkt_offset; + struct sk_buff *skb = NULL; + struct nmi_wfi_radiotap_hdr *hdr; + struct nmi_wfi_radiotap_cb_hdr *cb_hdr; + + PRINT_INFO(HOSTAPD_DBG,"In monitor interface receive function\n"); + + // struct NMI_WFI_priv *priv = netdev_priv(dev); + + // priv = wiphy_priv(priv->dev->ieee80211_ptr->wiphy); + + /* Bug 4601 */ + if(nmi_wfi_mon == NULL) + return; + + if (!netif_running(nmi_wfi_mon)) + { + PRINT_INFO(HOSTAPD_DBG,"Monitor interface already RUNNING\n"); + return; + } + + //Get NMI header + memcpy(&header, (buff-HOST_HDR_OFFSET), HOST_HDR_OFFSET); + + //The packet offset field conain info about what type of managment frame + // we are dealing with and ack status + pkt_offset = GET_PKT_OFFSET(header); + + if(pkt_offset & IS_MANAGMEMENT_CALLBACK) + { + + // hostapd callback mgmt frame + + //if(INFO || buff[0] == 0x10 || buff[0] == 0xb0) + //PRINT_D(HOSTAPD_DBG,"In monitor interface callback receive function\n"); + + + skb = dev_alloc_skb(size+sizeof(struct nmi_wfi_radiotap_cb_hdr)); + if(skb == NULL) + { + PRINT_INFO(HOSTAPD_DBG,"Monitor if : No memory to allocate skb"); + return; + } + + memcpy(skb_put(skb,size),buff, size); + + cb_hdr = (struct nmi_wfi_radiotap_cb_hdr *) skb_push(skb, sizeof(*cb_hdr)); + memset(cb_hdr, 0, sizeof(struct nmi_wfi_radiotap_cb_hdr)); + + cb_hdr->hdr.it_version = 0;//PKTHDR_RADIOTAP_VERSION; + + cb_hdr->hdr.it_len = cpu_to_le16(sizeof(struct nmi_wfi_radiotap_cb_hdr)); + + cb_hdr->hdr.it_present = cpu_to_le32( + (1 << IEEE80211_RADIOTAP_RATE) | + (1 << IEEE80211_RADIOTAP_TX_FLAGS)); + + cb_hdr->rate = 5;//txrate->bitrate / 5; + + if(pkt_offset & IS_MGMT_STATUS_SUCCES) + { + //success + cb_hdr->tx_flags = IEEE80211_RADIOTAP_F_TX_RTS; + } + else + { + cb_hdr->tx_flags = IEEE80211_RADIOTAP_F_TX_FAIL; + } + + } + else + { + + // normal mgmt frame + + //if(INFO || buff[0] == 0x00 || buff[0] == 0xb0) + // { + //PRINT_D(HOSTAPD_DBG,"In monitor interface receive function , length = %d\n",size); + //for(i=0;i<size;i++) + //PRINT_D(HOSTAPD_DBG,"Mon RxData[%d] = %02x\n",i,buff[i]); + // } + + + skb = dev_alloc_skb(size+sizeof(struct nmi_wfi_radiotap_hdr)); + + if(skb == NULL) + { + PRINT_INFO(HOSTAPD_DBG,"Monitor if : No memory to allocate skb"); + return; + } + + //skb = skb_copy_expand(tx_skb, sizeof(*hdr), 0, GFP_ATOMIC); + //if (skb == NULL) + // return; + + memcpy(skb_put(skb,size),buff, size); + //printk("--radiotap header--\n",sizeof(*hdr)); + hdr = (struct nmi_wfi_radiotap_hdr *) skb_push(skb, sizeof(*hdr)); + memset(hdr, 0, sizeof(struct nmi_wfi_radiotap_hdr)); + hdr->hdr.it_version = 0;//PKTHDR_RADIOTAP_VERSION; + //hdr->hdr.it_pad = 0; + hdr->hdr.it_len = cpu_to_le16(sizeof(struct nmi_wfi_radiotap_hdr)); + PRINT_INFO(HOSTAPD_DBG,"Radiotap len %d\n", hdr->hdr.it_len); + hdr->hdr.it_present = cpu_to_le32 + (1 << IEEE80211_RADIOTAP_RATE); //| + //(1 << IEEE80211_RADIOTAP_CHANNEL)); + PRINT_INFO(HOSTAPD_DBG,"Presentflags %d\n", hdr->hdr.it_present); + hdr->rate = 5;//txrate->bitrate / 5; + + } + +/* if(INFO || if(skb->data[9] == 0x00 || skb->data[9] == 0xb0)) + { + for(i=0;i<skb->len;i++) + PRINT_INFO(HOSTAPD_DBG,"Mon RxData[%d] = %02x\n",i,skb->data[i]); + }*/ + + + skb->dev = nmi_wfi_mon; + skb_set_mac_header(skb, 0); + skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = htons(ETH_P_802_2); + memset(skb->cb, 0, sizeof(skb->cb)); + + netif_rx(skb); + + +} + +struct tx_complete_mon_data{ + int size; + void* buff; +}; + +static void mgmt_tx_complete(void* priv, int status){ + + //struct sk_buff *skb2; + //struct nmi_wfi_radiotap_cb_hdr *cb_hdr; + + struct tx_complete_mon_data* pv_data = (struct tx_complete_mon_data*)priv; + NMI_Uint8 * buf= pv_data->buff; + + + + if(status == 1){ + if(INFO || buf[0] == 0x10 || buf[0] == 0xb0) + PRINT_D(HOSTAPD_DBG,"Packet sent successfully - Size = %d - Address = %p.\n",pv_data->size,pv_data->buff); + }else{ + PRINT_D(HOSTAPD_DBG,"Couldn't send packet - Size = %d - Address = %p.\n",pv_data->size,pv_data->buff); + } + + +/* //(skb->data[9] == 0x00 || skb->data[9] == 0xb0 || skb->data[9] == 0x40 || skb->data[9] == 0xd0 ) + { + skb2 = dev_alloc_skb(pv_data->size+sizeof(struct nmi_wfi_radiotap_cb_hdr)); + + memcpy(skb_put(skb2,pv_data->size),pv_data->buff, pv_data->size); + + cb_hdr = (struct nmi_wfi_radiotap_cb_hdr *) skb_push(skb2, sizeof(*cb_hdr)); + memset(cb_hdr, 0, sizeof(struct nmi_wfi_radiotap_cb_hdr)); + + cb_hdr->hdr.it_version = 0;//PKTHDR_RADIOTAP_VERSION; + + cb_hdr->hdr.it_len = cpu_to_le16(sizeof(struct nmi_wfi_radiotap_cb_hdr)); + + cb_hdr->hdr.it_present = cpu_to_le32( + (1 << IEEE80211_RADIOTAP_RATE) | + (1 << IEEE80211_RADIOTAP_TX_FLAGS)); + + cb_hdr->rate = 5;//txrate->bitrate / 5; + cb_hdr->tx_flags = 0x0004; + + skb2->dev = nmi_wfi_mon; + skb_set_mac_header(skb2, 0); + skb2->ip_summed = CHECKSUM_UNNECESSARY; + skb2->pkt_type = PACKET_OTHERHOST; + skb2->protocol = htons(ETH_P_802_2); + memset(skb2->cb, 0, sizeof(skb2->cb)); + + netif_rx(skb2); + }*/ + + kfree(pv_data->buff); + + kfree(pv_data); +} +static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len) +{ + linux_wlan_t* nic; + struct tx_complete_mon_data *mgmt_tx =NULL; + + if(dev == NULL) + { + PRINT_D(HOSTAPD_DBG,"ERROR: dev == NULL\n"); + return NMI_FAIL; + } + nic =netdev_priv(dev); + + //NMI_PRINTF("--IN mon_mgmt_tx--\n"); + netif_stop_queue(dev); + mgmt_tx = (struct tx_complete_mon_data*)kmalloc(sizeof(struct tx_complete_mon_data),GFP_ATOMIC); + if(mgmt_tx == NULL){ + PRINT_ER("Failed to allocate memory for mgmt_tx structure\n"); + return NMI_FAIL; + } + + mgmt_tx->buff= (char*)kmalloc(len,GFP_ATOMIC); + if(mgmt_tx->buff == NULL) + { + PRINT_ER("Failed to allocate memory for mgmt_tx buff\n"); + return NMI_FAIL; + + } + memcpy(mgmt_tx->buff,buf,len); + mgmt_tx->size=len; + //NMI_PRINTF("--IN mon_mgmt_tx: Sending MGMT Pkt to tx queue--\n"); + nic->oup.wlan_add_mgmt_to_tx_que(mgmt_tx,mgmt_tx->buff,mgmt_tx->size,mgmt_tx_complete); + + netif_wake_queue(dev); + return 0; +} + +/** +* @brief NMI_WFI_mon_xmit +* @details +* @param[in] +* @return int : Return 0 on Success +* @author mdaftedar +* @date 12 JUL 2012 +* @version 1.0 +*/ +static netdev_tx_t NMI_WFI_mon_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + struct ieee80211_radiotap_header *rtap_hdr; + NMI_Uint32 rtap_len,i,ret=0; + struct NMI_WFI_mon_priv *mon_priv ; + + /* Bug 4601 */ + if(nmi_wfi_mon == NULL) + return NMI_FAIL; + + //if(skb->data[3] == 0x10 || skb->data[3] == 0xb0) + PRINT_INFO(HOSTAPD_DBG,"Monitor xmit function\n"); + + + + mon_priv = netdev_priv(nmi_wfi_mon); + if(mon_priv== NULL) + { + PRINT_ER("Monitor interface private structure is NULL\n"); + return NMI_FAIL; + } + + if(INFO) + { + for(i=0; i<skb->len ; i++) + PRINT_INFO(HOSTAPD_DBG,"Data[%d] %02x\n",i,skb->data[i]); + } + rtap_hdr = (struct ieee80211_radiotap_header *)skb->data; + + rtap_len = ieee80211_get_radiotap_len(skb->data); + if (skb->len < rtap_len) + { + PRINT_ER("Error in radiotap header\n"); + return -1; + } + /* skip the radiotap header */ + PRINT_INFO(HOSTAPD_DBG,"Radiotap len: %d\n", rtap_len); + + if(INFO) + { + for(i=0; i<20 ; i++) + PRINT_INFO(HOSTAPD_DBG,"Radiotap_hdr[%d] %02x\n",i,skb->data[i]); + } + /* Skip the ratio tap header */ + skb_pull(skb, rtap_len); + skb->dev = mon_priv->real_ndev; + + PRINT_INFO(HOSTAPD_DBG,"Skipping the radiotap header\n"); + + + + /* actual deliver of data is device-specific, and not shown here */ + PRINT_INFO(HOSTAPD_DBG,"SKB netdevice name = %s\n", skb->dev->name); + PRINT_INFO(HOSTAPD_DBG,"MONITOR real dev name = %s\n", mon_priv->real_ndev->name); + + #ifdef SIMULATION + ret = NMI_WFI_Tx(skb,mon_priv->real_ndev); + #elif USE_WIRELESS + //Identify if Ethernet or MAC header (data or mgmt) + memcpy(srcAdd,& skb->data[11],6); + //NMI_PRINTF("SRC/BSSID\n"); + memcpy(bssid, &skb->data[17],6); + //if source address and bssid fields are equal>>Mac header + /*send it to mgmt frames handler */ + if(!(memcmp(srcAdd,bssid,6))) + { + //NMI_PRINTF("--MGMT PKT in mon_xmit--\n"); + mon_mgmt_tx(mon_priv->real_ndev, skb->data, skb->len); + dev_kfree_skb(skb); + } + else + ret = mac_xmit(skb,mon_priv->real_ndev); + #endif + + //return NETDEV_TX_OK; + return ret; +} + +static const struct net_device_ops nmi_wfi_netdev_ops = { + .ndo_start_xmit = NMI_WFI_mon_xmit, + +}; + +/** +* @brief NMI_WFI_mon_setup +* @details +* @param[in] +* @return int : Return 0 on Success +* @author mdaftedar +* @date 12 JUL 2012 +* @version 1.0 +*/ +static void NMI_WFI_mon_setup(struct net_device *dev) +{ + + dev->netdev_ops = &nmi_wfi_netdev_ops; + // dev->destructor = free_netdev; + PRINT_INFO(CORECONFIG_DBG,"In Ethernet setup function\n"); + ether_setup(dev); + dev->tx_queue_len = 0; + dev->type = ARPHRD_IEEE80211_RADIOTAP; + memset(dev->dev_addr, 0, ETH_ALEN); + + #ifdef USE_WIRELESS + { + // u8 * mac_add; + unsigned char mac_add[] = {0x00,0x50,0xc2,0x5e,0x10,0x8f}; + // priv = wiphy_priv(priv->dev->ieee80211_ptr->wiphy); + // mac_add = (NMI_Uint8*)NMI_MALLOC(ETH_ALEN); + //status = host_int_get_MacAddress(priv->hNMIWFIDrv,mac_add); + //mac_add[ETH_ALEN-1]+=1; + memcpy(dev->dev_addr, mac_add, ETH_ALEN); + } + #else + dev->dev_addr[0] = 0x12; + #endif + +} + +/** +* @brief NMI_WFI_init_mon_interface +* @details +* @param[in] +* @return int : Return 0 on Success +* @author mdaftedar +* @date 12 JUL 2012 +* @version 1.0 +*/ +int NMI_WFI_init_mon_interface(char *name , struct net_device *real_dev ) +{ + NMI_Uint32 ret = NMI_SUCCESS; + struct NMI_WFI_mon_priv *priv ; + + nmi_wfi_mon = alloc_netdev(sizeof(struct NMI_WFI_mon_priv), name, NMI_WFI_mon_setup); + if (nmi_wfi_mon == NULL) + { + PRINT_ER("Failed to allocate netdevice\n"); + goto failed; + } + + //rtnl_lock(); + PRINT_INFO(HOSTAPD_DBG,"Monitor interface name %s\n", nmi_wfi_mon->name); + + + ret = dev_alloc_name(nmi_wfi_mon, nmi_wfi_mon->name); + if (ret < 0) + goto failed_mon; + + + priv = netdev_priv(nmi_wfi_mon); + if(priv== NULL) + { + PRINT_ER("private structure is NULL\n"); + return NMI_FAIL; + } + + priv->real_ndev = real_dev; + + + ret = register_netdevice(nmi_wfi_mon); + + + if (ret < 0) + { + PRINT_ER("Failed to register netdevice\n"); + goto failed_mon; + } + + + return NMI_SUCCESS; + // rtnl_unlock(); + +failed: + return ret; + +failed_mon: + //rtnl_unlock(); + free_netdev(nmi_wfi_mon); + return ret; + + + +} + +/** +* @brief NMI_WFI_deinit_mon_interface +* @details +* @param[in] +* @return int : Return 0 on Success +* @author mdaftedar +* @date 12 JUL 2012 +* @version 1.0 +*/ +int NMI_WFI_deinit_mon_interface() +{ + bool rollback_lock = false; + + if(nmi_wfi_mon != NULL) + { + PRINT_D(HOSTAPD_DBG,"In Deinit monitor interface\n"); + PRINT_D(HOSTAPD_DBG,"RTNL is being locked\n"); + if (rtnl_is_locked()) + { + rtnl_unlock(); + rollback_lock = true; + } + PRINT_D(HOSTAPD_DBG,"Unregister netdev\n"); + unregister_netdev(nmi_wfi_mon); + //NMI_PRINTF("Free Netdev\n"); + //free_netdev(nmi_wfi_mon); + + if (rollback_lock) + { + rtnl_lock(); + rollback_lock = false; + } + nmi_wfi_mon = NULL; + } + return NMI_SUCCESS; + +} +#endif // NMI_AP_EXTERNAL_MLME diff --git a/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/linux_wlan.c b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/linux_wlan.c new file mode 100755 index 00000000..297223d8 --- /dev/null +++ b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/linux_wlan.c @@ -0,0 +1,2357 @@ +#ifndef SIMULATION
+#include "NMI_WFI_CfgOperations.h"
+#include "linux_wlan_common.h"
+#include "nmi_wlan_if.h"
+#include "nmi_wlan.h"
+#ifdef USE_WIRELESS
+#include "NMI_WFI_CfgOperations.h"
+#endif
+
+#include "linux_wlan_common.h"
+
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#ifndef PLAT_ALLWINNER_A10 // tony
+#include <asm/gpio.h>
+#endif
+#include <linux/kthread.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+
+#include <linux/version.h>
+#include <linux/semaphore.h>
+
+#include "svnrevision.h"
+
+#ifdef NMI_SDIO
+#include "linux_wlan_sdio.h"
+#else
+#include "linux_wlan_spi.h"
+#endif
+
+
+#if defined(PLAT_WMS8304)
+#include "nmi_custom_gpio.c"
+#elif defined(PLAT_WM8880)
+#include "nmi_wm8880_gpio.c"
+
+#include <linux/wireless.h> // simon, rachel
+#include <mach/irqs.h>
+#include <linux/mmc/sdio.h>
+#include <mach/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+int wmt_nmc1000_intr_num=15; //gpio 15
+#endif
+
+#define nmi_wlan_deinit(nic) if(&nic->oup != NULL) \
+ if(nic->oup.wlan_cleanup != NULL) \
+ nic->oup.wlan_cleanup()
+
+//[[ johnny : enable to selecte bin file on Makefile
+#ifndef STA_FIRMWARE
+#define STA_FIRMWARE "wifi_firmware.bin"
+#endif
+
+#ifndef AP_FIRMWARE
+#define AP_FIRMWARE "wifi_firmware_ap.bin"
+#endif
+//]]
+
+// [[ added by tony
+typedef struct android_wifi_priv_cmd {
+ char *buf;
+ int used_len;
+ int total_len;
+} android_wifi_priv_cmd;
+// ]] for wpa supplicant iw
+
+#if defined(PLAT_AML8726_M3) //[[ johnny : because of dummy irq
+static int _available_irq_ready = 0;
+#endif
+
+#define IRQ_WAIT 1
+#define IRQ_NO_WAIT 0
+ /*
+ to sync between mac_close and module exit.
+ don't initialize or de-initialize from init/deinitlocks
+ to be initialized from module nmc_netdev_init and
+ deinitialized from mdoule_exit
+ */
+static struct semaphore close_exit_sync;
+unsigned int int_rcvdU;
+unsigned int int_rcvdB;
+unsigned int int_clrd;
+
+static int wlan_deinit_locks(linux_wlan_t* nic);
+static void wlan_deinitialize_threads(linux_wlan_t* nic);
+static void linux_wlan_lock(void* vp);
+static void linux_wlan_unlock(void* vp);
+
+
+static void* internal_alloc(uint32_t size, uint32_t flag);
+static void linux_wlan_tx_complete(void* priv, int status);
+void frmw_to_linux(uint8_t *buff, uint32_t size);
+static int mac_init_fn(struct net_device *ndev);
+int mac_xmit(struct sk_buff *skb, struct net_device *dev);
+static int mac_open(struct net_device *ndev);
+static int mac_close(struct net_device *ndev);
+static struct net_device_stats *mac_stats(struct net_device *dev);
+static int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd);
+
+
+struct tx_complete_data{
+ int size;
+ void* buff;
+ struct sk_buff *skb;
+};
+
+
+ /*
+ for now - in frmw_to_linux there should be private data to be passed to it
+ and this data should be pointer to net device
+ */
+linux_wlan_t* g_linux_wlan = NULL;
+nmi_wlan_oup_t* gpstrWlanOps;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
+
+static const struct net_device_ops nmc_netdev_ops = {
+ .ndo_init = mac_init_fn,
+ .ndo_open = mac_open,
+ .ndo_stop = mac_close,
+ .ndo_start_xmit = mac_xmit,
+ .ndo_do_ioctl = mac_ioctl,
+ .ndo_get_stats = mac_stats,
+
+};
+
+#define nmc_set_netdev_ops(ndev) do { (ndev)->netdev_ops = &nmc_netdev_ops; } while(0)
+
+#else
+
+static void nmc_set_netdev_ops(struct net_device *ndev)
+{
+
+ ndev->init = mac_init_fn;
+ ndev->open = mac_open;
+ ndev->stop = mac_close;
+ ndev->hard_start_xmit = mac_xmit;
+ ndev->do_ioctl = mac_ioctl;
+ ndev->get_stats = mac_stats;
+}
+
+#endif
+#ifdef DEBUG_MODE
+
+extern volatile int timeNo;
+
+#define DEGUG_BUFFER_LENGTH 1000
+volatile int WatchDogdebuggerCounter=0;
+char DebugBuffer[DEGUG_BUFFER_LENGTH+20]={0};
+static char * ps8current=DebugBuffer;
+
+
+
+void printk_later(const char * format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ ps8current += vsprintf (ps8current,format, args);
+ va_end (args);
+ if((ps8current-DebugBuffer)>DEGUG_BUFFER_LENGTH)
+ {
+ ps8current=DebugBuffer;
+ }
+
+}
+
+
+void dump_logs()
+{
+ if(DebugBuffer[0])
+ {
+ DebugBuffer[DEGUG_BUFFER_LENGTH]=0;
+ printk("early printed\n");
+ printk(ps8current+1);
+ ps8current[1]=0;
+ printk("latest printed\n");
+ printk(DebugBuffer);
+ DebugBuffer[0]=0;
+ ps8current=DebugBuffer;
+ }
+}
+
+void Reset_WatchDogdebugger()
+{
+ WatchDogdebuggerCounter=0;
+}
+
+static int DebuggingThreadTask(void* vp)
+{
+ while(1){
+ while(!WatchDogdebuggerCounter)
+ {
+ printk("Debug Thread Running %d\n",timeNo);
+ WatchDogdebuggerCounter=1;
+ msleep(10000);
+ }
+ dump_logs();
+ WatchDogdebuggerCounter=0;
+ }
+}
+
+
+#endif
+/*
+ * Interrupt initialization and handling functions
+ */
+
+void linux_wlan_enable_irq(void){
+
+#if (RX_BH_TYPE != RX_BH_THREADED_IRQ)
+#if (!defined NMI_SDIO) || (defined NMI_SDIO_IRQ_GPIO)
+ PRINT_D(INT_DBG,"Enabling IRQ ...\n");
+
+#if defined(PLAT_WMS8304) // added by rachel
+ //enable_irq(nic->dev_irq_num);
+ /*clean corresponding int status bit, or it will generate int continuously for ever*/
+ gpio_clean_irq_status_any(&gpio_irq_ctrl);
+
+ enable_irq(g_linux_wlan->dev_irq_num);
+
+ /*we should reopen this gpio pin int in order to capture the future/comming interruption*/
+ enable_gpio_int_any(&gpio_irq_ctrl, INT_EN);
+ #elif defined(PLAT_WM8880)
+
+ wmt_gpio_ack_irq(wmt_nmc1000_intr_num);
+ wmt_gpio_unmask_irq(wmt_nmc1000_intr_num);
+
+ #else
+ enable_irq(g_linux_wlan->dev_irq_num);
+ #endif
+
+#endif
+#endif
+}
+
+void linux_wlan_disable_irq(int wait){
+#if (!defined NMI_SDIO) || (defined NMI_SDIO_IRQ_GPIO)
+ if(wait){
+ PRINT_D(INT_DBG,"Disabling IRQ ...\n");
+#if defined(PLAT_WM8880)
+ wmt_gpio_mask_irq(wmt_nmc1000_intr_num);
+#else
+ disable_irq(g_linux_wlan->dev_irq_num);
+#endif
+ } else {
+ PRINT_D(INT_DBG,"Disabling IRQ ...\n");
+#if defined(PLAT_WM8880)
+ wmt_gpio_mask_irq(wmt_nmc1000_intr_num);
+#else
+ disable_irq_nosync(g_linux_wlan->dev_irq_num);
+#endif
+ }
+#endif
+}
+#if (!defined NMI_SDIO) || (defined NMI_SDIO_IRQ_GPIO)
+static irqreturn_t isr_uh_routine(int irq, void* user_data){
+ linux_wlan_t *nic = (linux_wlan_t*)user_data;
+
+#if defined(PLAT_WMS8304)
+ int pin_state;
+ //printk("isr_uh_routine\n");
+ /*if this gpio pin int is not enable or int status bit is not toggled, it is not our interruption*/
+ if(!gpio_irq_isEnable_any(&gpio_irq_ctrl) || !gpio_irq_state_any(&gpio_irq_ctrl))
+ return IRQ_NONE;
+
+ /*be here, be sure that this int is myself, but we should disable int before handler this interruption*/
+ enable_gpio_int_any(&gpio_irq_ctrl, INT_DIS);
+
+ /*get value on gpin int pin*/
+ pin_state = gpio_get_value_any(&gpio_irq_ctrl);
+
+ if(pin_state == 0) {
+ //printk("wlan int\n");
+ //dont_deinit_irq = 0;
+ }
+ else
+ {
+ //printk("this is fake interruption!!\n");
+ enable_gpio_int_any(&gpio_irq_ctrl, INT_EN);
+ return IRQ_HANDLED;
+ }
+#elif defined(PLAT_WM8880)
+
+ if(!is_gpio_irqenable(wmt_nmc1000_intr_num) || !gpio_irqstatus(wmt_nmc1000_intr_num))
+ return IRQ_NONE;
+
+ wmt_gpio_mask_irq(wmt_nmc1000_intr_num);
+
+#endif
+
+ int_rcvdU++;
+ PRINT_D(INT_DBG,"Interrupt received UH\n");
+#if (RX_BH_TYPE != RX_BH_THREADED_IRQ)
+ linux_wlan_disable_irq(IRQ_NO_WAIT);
+#endif
+
+#if defined(PLAT_AML8726_M3)//[[ johnny : because of dummy irq
+ if ( _available_irq_ready == 0 )
+ {
+ linux_wlan_enable_irq();
+ PRINT_D(GENERIC_DBG,"johnny test : recevied dummy irq\n");
+ return IRQ_HANDLED;
+ }
+#endif//]]
+
+ /*While mac is closing cacncel the handling of any interrupts received*/
+ if(nic->close)
+ {
+ PRINT_ER("Driver is CLOSING: Can't handle UH interrupt\n");
+ #if (RX_BH_TYPE == RX_BH_THREADED_IRQ)
+ return IRQ_HANDLED;
+ #else
+ return IRQ_NONE;
+ #endif
+
+ }
+#if (RX_BH_TYPE == RX_BH_WORK_QUEUE)
+ schedule_work(&nic->rx_work_queue);
+ return IRQ_HANDLED;
+#elif (RX_BH_TYPE == RX_BH_KTHREAD)
+ linux_wlan_unlock(&nic->rx_sem);
+ return IRQ_HANDLED;
+#elif (RX_BH_TYPE == RX_BH_THREADED_IRQ)
+ return IRQ_WAKE_THREAD;
+#endif
+
+}
+#endif
+
+#if (RX_BH_TYPE == RX_BH_WORK_QUEUE || RX_BH_TYPE == RX_BH_THREADED_IRQ)
+
+#if (RX_BH_TYPE == RX_BH_THREADED_IRQ)
+irqreturn_t isr_bh_routine(int irq, void *userdata){
+ linux_wlan_t* nic;
+ nic = (linux_wlan_t*)userdata;
+#else
+static void isr_bh_routine(struct work_struct *work){
+ linux_wlan_t* nic;
+ nic = container_of(work,linux_wlan_t,rx_work_queue);
+#endif
+
+ /*While mac is closing cacncel the handling of any interrupts received*/
+ if(nic->close)
+ {
+ PRINT_ER("Driver is CLOSING: Can't handle BH interrupt\n");
+ #if (RX_BH_TYPE == RX_BH_THREADED_IRQ)
+ return IRQ_HANDLED;
+ #else
+ return;
+ #endif
+
+
+
+ }
+
+ int_rcvdB++;
+ PRINT_D(INT_DBG,"Interrupt received BH\n");
+ if(nic->oup.wlan_handle_rx_isr != 0){
+ nic->oup.wlan_handle_rx_isr();
+ }else{
+ PRINT_ER("wlan_handle_rx_isr() hasn't been initialized\n");
+ }
+
+
+#if (RX_BH_TYPE == RX_BH_THREADED_IRQ)
+ return IRQ_HANDLED;
+#endif
+}
+#elif (RX_BH_TYPE == RX_BH_KTHREAD)
+static int isr_bh_routine(void *vp)
+{
+ linux_wlan_t* nic;
+
+ nic = (linux_wlan_t*)vp;
+
+ while(1) {
+ linux_wlan_lock(&nic->rx_sem);
+ if (nic->close){
+
+ while(!kthread_should_stop())
+ schedule();
+
+ break;
+ }
+ int_rcvdB++;
+ PRINT_D(INT_DBG,"Interrupt received BH\n");
+ if(nic->oup.wlan_handle_rx_isr != 0){
+ nic->oup.wlan_handle_rx_isr();
+ } else{
+ PRINT_ER("wlan_handle_rx_isr() hasn't been initialized\n");
+ }
+ }
+
+ return 0;
+}
+#endif
+
+
+#if (!defined NMI_SDIO) || (defined NMI_SDIO_IRQ_GPIO)
+static int init_irq(linux_wlan_t* p_nic){
+ int ret = 0;
+ linux_wlan_t *nic = p_nic;
+
+#if defined(PLAT_AML8726_M3) //johnny add
+ nic->dev_irq_num = INT_GPIO_4; // <== skyworth //'100' value for onda vi30 platform
+
+ ret = request_irq(nic->dev_irq_num, isr_uh_routine, IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+ "NMC_IRQ", nic);
+
+ if (ret < 0) {
+ PRINT_ER("Failed to request IRQ for GPIO: %d\n",nic->dev_irq_num);
+ }
+
+#elif defined (PLAT_WMS8304) //simon
+ //system("rmmod /system/modules/3.0.8-default/kpad.ko");
+ irq_gpio_init();
+ nic->dev_irq_num = IRQ_GPIO; //(5) gpio_irq_ctrl;
+ printk("%s\n",__FUNCTION__);
+ ret = request_irq(nic->dev_irq_num, isr_uh_routine, IRQF_SHARED,
+ "NMC_IRQ", nic);
+
+ if (ret < 0) {
+ PRINT_ER("Failed to request IRQ for GPIO: %d\n",nic->dev_irq_num);
+ }
+
+ enable_gpio_int_any(&gpio_irq_ctrl,INT_EN);
+
+#elif defined(PLAT_WM8880)
+
+ printk("%s\n",__FUNCTION__);
+ wmt_gpio_setpull(wmt_nmc1000_intr_num,WMT_GPIO_PULL_UP);
+ wmt_gpio_mask_irq(wmt_nmc1000_intr_num);
+ wmt_gpio_ack_irq(wmt_nmc1000_intr_num);
+
+
+ nic->dev_irq_num = IRQ_GPIO;
+ ret = request_irq(nic->dev_irq_num, isr_uh_routine, IRQF_SHARED,
+ "NMC_IRQ", nic);
+
+ if (ret < 0) {
+ PRINT_ER("Failed to request IRQ for GPIO: %d\n",nic->dev_irq_num);
+ }
+
+ /*clear int status register before enable this int pin*/
+ wmt_gpio_ack_irq(wmt_nmc1000_intr_num);
+ /*enable this int pin*/
+ wmt_gpio_unmask_irq(wmt_nmc1000_intr_num);
+
+#else
+ /*initialize GPIO and register IRQ num*/
+ /*GPIO request*/
+ if ((gpio_request(GPIO_NUM, "NMC_INTR") == 0) &&
+ (gpio_direction_input(GPIO_NUM) == 0)) {
+#if defined (NM73131_0_BOARD)
+ nic->dev_irq_num = IRQ_NMC1000;
+#else
+ gpio_export(GPIO_NUM, 1);
+ nic->dev_irq_num = OMAP_GPIO_IRQ(GPIO_NUM);
+ irq_set_irq_type(nic->dev_irq_num, IRQ_TYPE_LEVEL_LOW);
+#endif
+ } else {
+ ret = -1;
+ PRINT_ER("could not obtain gpio for NMC_INTR\n");
+ }
+
+
+#if (RX_BH_TYPE == RX_BH_THREADED_IRQ)
+ if( (ret != -1) && ( request_threaded_irq(nic->dev_irq_num, isr_uh_routine, isr_bh_routine,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT, /*Without IRQF_ONESHOT the uh will remain kicked in and dont gave a chance to bh*/
+ "NMC_IRQ", nic))<0){
+
+#else
+ /*Request IRQ*/
+ if( (ret != -1) && (request_irq(nic->dev_irq_num, isr_uh_routine,
+ IRQF_TRIGGER_LOW, "NMC_IRQ", nic) < 0)){
+
+#endif
+ PRINT_ER("Failed to request IRQ for GPIO: %d\n",GPIO_NUM);
+ ret = -1;
+ }else{
+
+ PRINT_D(INIT_DBG,"IRQ request succeeded IRQ-NUM= %d on GPIO: %d\n",
+ nic->dev_irq_num,GPIO_NUM);
+ }
+#endif
+
+ return ret;
+}
+#endif
+
+static void deinit_irq(linux_wlan_t* nic){
+ #if (!defined NMI_SDIO) || (defined NMI_SDIO_IRQ_GPIO)
+ /* Deintialize IRQ */
+ if(&nic->dev_irq_num != 0){
+ free_irq(nic->dev_irq_num, nic);
+#if defined(PLAT_AML8726_M3) //johnny
+
+#elif defined (PLAT_WMS8304)
+ irq_gpio_deinit();
+
+#elif defined(PLAT_WM8880)
+
+#else
+ gpio_free(GPIO_NUM);
+#endif
+ }
+ #endif
+}
+
+
+/*
+ OS functions
+*/
+static void linux_wlan_msleep(uint32_t msc){
+ if(msc <= 4000000)
+ {
+ NMI_Uint32 u32Temp = msc * 1000;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
+ usleep_range(u32Temp, u32Temp);
+#else
+ /* This is delay not sleep !!!, has to be changed*/
+ msleep(msc);
+#endif
+ }
+ else
+ {
+ msleep(msc);
+ }
+}
+
+static void linux_wlan_atomic_msleep(uint32_t msc){
+ mdelay(msc);
+}
+static void linux_wlan_dbg(uint8_t *buff){
+ printk(buff);
+#if defined (NMC_DEBUGFS)
+ kmsgdump_write(buff);
+#endif
+}
+
+static void* linux_wlan_malloc_atomic(uint32_t sz){
+ char* pntr = NULL;
+ pntr = (char*)kmalloc(sz,GFP_ATOMIC );
+ PRINT_D(MEM_DBG,"Allocating %d bytes at address %p\n",sz,pntr);
+ return ((void*)pntr);
+
+}
+static void* linux_wlan_malloc(uint32_t sz){
+ char* pntr = NULL;
+ pntr = (char*)kmalloc(sz,GFP_KERNEL );
+ PRINT_D(MEM_DBG,"Allocating %d bytes at address %p\n",sz,pntr);
+ return ((void*)pntr);
+}
+
+void linux_wlan_free(void* vp){
+ if(vp != NULL){
+ PRINT_D(MEM_DBG,"Freeing %p\n",vp);
+ kfree(vp);
+ }
+}
+
+
+static void* internal_alloc(uint32_t size, uint32_t flag){
+ char* pntr = NULL;
+ pntr = (char*)kmalloc(size,flag);
+ PRINT_D(MEM_DBG,"Allocating %d bytes at address %p\n",size,pntr);
+ return ((void*)pntr);
+}
+
+
+static void linux_wlan_init_lock(char* lockName, void* plock,int count)
+{
+ sema_init((struct semaphore*)plock,count);
+ PRINT_D(LOCK_DBG,"Initializing [%s][%p]\n",lockName,plock);
+
+}
+
+static void linux_wlan_deinit_lock(void* plock)
+{
+ //mutex_destroy((struct mutex*)plock);
+}
+
+static void linux_wlan_lock(void* vp)
+{
+ PRINT_D(LOCK_DBG,"Locking %p\n",vp);
+ if(vp != NULL)
+ {
+ down((struct semaphore*)vp);
+ }
+ else
+ {
+ PRINT_ER("Failed, mutex is NULL\n");
+ }
+}
+
+static int linux_wlan_lock_timeout(void* vp,NMI_Uint32 timeout)
+{
+ int error = -1;
+ PRINT_D(LOCK_DBG,"Locking %p\n",vp);
+ if(vp != NULL)
+ {
+ error = down_timeout((struct semaphore*)vp, msecs_to_jiffies(timeout));
+ }
+ else
+ {
+ PRINT_ER("Failed, mutex is NULL\n");
+ }
+ return error;
+}
+
+static void linux_wlan_unlock(void* vp)
+{
+ PRINT_D(LOCK_DBG,"Unlocking %p\n",vp);
+ if(vp != NULL)
+ {
+ up((struct semaphore*)vp);
+ }
+ else
+ {
+ PRINT_ER("Failed, mutex is NULL\n");
+ }
+}
+
+
+static void linux_wlan_init_mutex(char* lockName, void* plock,int count)
+{
+ mutex_init((struct mutex*)plock);
+ PRINT_D(LOCK_DBG,"Initializing mutex [%s][%p]\n",lockName,plock);
+
+}
+
+static void linux_wlan_deinit_mutex(void* plock)
+{
+ mutex_destroy((struct mutex*)plock);
+}
+
+static void linux_wlan_lock_mutex(void* vp)
+{
+ PRINT_D(LOCK_DBG,"Locking mutex %p\n",vp);
+ if(vp != NULL)
+ {
+ /*
+ if(mutex_is_locked((struct mutex*)vp))
+ {
+ //PRINT_ER("Mutex already locked - %p \n",vp);
+ }
+*/
+ mutex_lock((struct mutex*)vp);
+
+ }else
+ {
+ PRINT_ER("Failed, mutex is NULL\n");
+ }
+}
+
+static void linux_wlan_unlock_mutex(void* vp){
+ PRINT_D(LOCK_DBG,"Unlocking mutex %p\n",vp);
+ if(vp != NULL){
+
+ if(mutex_is_locked((struct mutex*)vp)){
+ mutex_unlock((struct mutex*)vp);
+ }else{
+ //PRINT_ER("Mutex already unlocked - %p\n",vp);
+ }
+
+ }else{
+ PRINT_ER("Failed, mutex is NULL\n");
+ }
+}
+
+
+
+static void linux_wlan_mac_indicate(int flag){
+ /*I have to do it that way becuase there is no mean to encapsulate device pointer
+ as a parameter
+ */
+ linux_wlan_t *pd = g_linux_wlan;
+ int status;
+
+ if (flag == NMI_MAC_INDICATE_STATUS) {
+ pd->oup.wlan_cfg_get_value(WID_STATUS, (unsigned char*)&status, 4);
+ if (pd->mac_status == NMI_MAC_STATUS_INIT) {
+ pd->mac_status = status;
+ linux_wlan_unlock(&pd->sync_event);
+ } else {
+ pd->mac_status = status;
+ }
+
+ if (pd->mac_status == NMI_MAC_STATUS_CONNECT) { /* Connect */
+#if 0
+ /**
+ get the mac and bssid address
+ **/
+ PRINT_D(RX_DBG,"Calling cfg_get to get MAC_ADDR\n");
+ pd->oup.wlan_cfg_get(1, WID_MAC_ADDR, 0);
+ PRINT_D(RX_DBG,"Calling cfg_get to get BSSID\n");
+ pd->oup.wlan_cfg_get(0, WID_BSSID, 1);
+
+ /**
+ get the value
+ **/
+ pd->oup.wlan_cfg_get_value(WID_MAC_ADDR, pd->eth_src_address, 6);
+ pd->oup.wlan_cfg_get_value(WID_BSSID, pd->eth_dst_address, 6);
+
+ PRINT_D(GENERIC_DBG,"Source Address = %s",pd->eth_src_address);
+ PRINT_D(GENERIC_DBG,"Destiation Address = %s",pd->eth_dst_address);
+
+ /**
+ launch ndis
+ **/
+#endif
+ }
+
+ } else if (flag == NMI_MAC_INDICATE_SCAN) {
+ PRINT_D(GENERIC_DBG,"Scanning ...\n");
+
+ }
+
+}
+
+
+static int linux_wlan_rxq_task(void* vp){
+
+ linux_wlan_t *pd = (linux_wlan_t*)vp;
+ /* inform nmc1000_wlan_init that RXQ task is started. */
+ linux_wlan_unlock(&pd->rxq_thread_started);
+ while(1) {
+ linux_wlan_lock(&pd->rxq_event);
+ //wait_for_completion(&pd->rxq_event);
+ if (pd->close){
+ /*Unlock the mutex in the mac_close function to indicate the exiting of the RX thread */
+ linux_wlan_unlock(&pd->rxq_thread_started);
+
+ while(!kthread_should_stop())
+ schedule();
+
+ PRINT_D(RX_DBG," RX thread stopped\n");
+ break;
+ }
+ PRINT_D(RX_DBG,"Calling wlan_handle_rx_que()\n");
+ pd->oup.wlan_handle_rx_que();
+ }
+ return 0;
+}
+
+#define USE_TX_BACKOFF_DELAY_IF_NO_BUFFERS
+
+static int linux_wlan_txq_task(void* vp)
+{
+ int ret,txq_count;
+ linux_wlan_t *pd = (linux_wlan_t*)vp;
+
+#if defined USE_TX_BACKOFF_DELAY_IF_NO_BUFFERS
+#define TX_BACKOFF_WEIGHT_INCR_STEP (1)
+#define TX_BACKOFF_WEIGHT_DECR_STEP (1)
+#define TX_BACKOFF_WEIGHT_MAX (7)
+#define TX_BACKOFF_WEIGHT_MIN (0)
+#define TX_BACKOFF_WEIGHT_UNIT_MS (10)
+ int backoff_weight = TX_BACKOFF_WEIGHT_MIN;
+ signed long timeout;
+#endif
+
+ /* inform nmc1000_wlan_init that TXQ task is started. */
+ linux_wlan_unlock(&pd->txq_thread_started);
+ while(1) {
+
+ PRINT_D(TX_DBG,"txq_task Taking a nap :)\n");
+ linux_wlan_lock(&pd->txq_event);
+ //wait_for_completion(&pd->txq_event);
+ PRINT_D(TX_DBG,"txq_task Who waked me up :$\n");
+
+ if (pd->close){
+ /*Unlock the mutex in the mac_close function to indicate the exiting of the TX thread */
+ linux_wlan_unlock(&pd->txq_thread_started);
+
+ while(!kthread_should_stop())
+ schedule();
+
+ PRINT_D(TX_DBG,"TX thread stopped\n");
+ break;
+ }
+ PRINT_D(TX_DBG,"txq_task handle the sending packet and let me go to sleep.\n");
+#if !defined USE_TX_BACKOFF_DELAY_IF_NO_BUFFERS
+ pd->oup.wlan_handle_tx_que();
+#else
+ do {
+ ret = pd->oup.wlan_handle_tx_que(&txq_count);
+ if(txq_count < FLOW_CONTROL_LOWER_THRESHOLD && netif_queue_stopped(pd->nmc_netdev))
+ {
+ PRINT_D(TX_DBG,"Waking up queue\n");
+ netif_wake_queue(pd->nmc_netdev);
+ }
+
+ if(ret == NMI_TX_ERR_NO_BUF) { /* failed to allocate buffers in chip. */
+ timeout = msecs_to_jiffies(TX_BACKOFF_WEIGHT_UNIT_MS << backoff_weight);
+ do {
+ /* Back off from sending packets for some time. */
+ /* schedule_timeout will allow RX task to run and free buffers.*/
+ //set_current_state(TASK_UNINTERRUPTIBLE);
+ //timeout = schedule_timeout(timeout);
+ msleep(TX_BACKOFF_WEIGHT_UNIT_MS << backoff_weight);
+ } while(/*timeout*/0);
+ backoff_weight += TX_BACKOFF_WEIGHT_INCR_STEP;
+ if(backoff_weight > TX_BACKOFF_WEIGHT_MAX) {
+ backoff_weight = TX_BACKOFF_WEIGHT_MAX;
+ }
+ } else {
+ if(backoff_weight > TX_BACKOFF_WEIGHT_MIN) {
+ backoff_weight -= TX_BACKOFF_WEIGHT_DECR_STEP;
+ if(backoff_weight < TX_BACKOFF_WEIGHT_MIN) {
+ backoff_weight = TX_BACKOFF_WEIGHT_MIN;
+ }
+ }
+ }
+ /*TODO: drop packets after a certain time/number of retry count. */
+ } while(ret == NMI_TX_ERR_NO_BUF&&!pd->close); /* retry sending packets if no more buffers in chip. */
+#endif
+ }
+ return 0;
+}
+
+static void linux_wlan_rx_complete(void){
+ PRINT_D(RX_DBG,"RX completed\n");
+}
+int linux_wlan_get_firmware(linux_wlan_t* p_nic){
+
+ linux_wlan_t* nic = p_nic;
+ int ret = 0;
+ const struct firmware* nmc_firmware;
+ char *firmware;
+
+
+ if(nic->iftype == AP_MODE)
+ firmware = AP_FIRMWARE;
+ else
+ firmware = STA_FIRMWARE;
+
+
+ if(nic == NULL){
+ PRINT_ER("NIC is NULL\n");
+ goto _fail_;
+ }
+
+ if(&nic->nmc_netdev->dev == NULL){
+ PRINT_ER("&nic->nmc_netdev->dev is NULL\n");
+ goto _fail_;
+ }
+
+
+ /* the firmare should be located in /lib/firmware in
+ root file system with the name specified above */
+
+#ifdef NMI_SDIO
+ if( request_firmware(&nmc_firmware,firmware, &nic->nmc_sdio_func->dev) != 0){
+ PRINT_ER("%s - firmare not available\n",firmware);
+ ret = -1;
+ goto _fail_;
+ }
+#else
+ if( request_firmware(&nmc_firmware,firmware, &nic->nmc_spidev->dev) != 0){
+ PRINT_ER("%s - firmare not available\n",firmware);
+ ret = -1;
+ goto _fail_;
+ }
+#endif
+ nic->nmc_firmware = nmc_firmware; /* Bug 4703 */
+
+_fail_:
+
+ return ret;
+
+}
+
+static int linux_wlan_start_firmware(linux_wlan_t* nic){
+
+ int ret = 0;
+ /* start firmware */
+ PRINT_D(INIT_DBG,"Starting Firmware ...\n");
+ ret = nic->oup.wlan_start();
+ if(ret < 0){
+ PRINT_ER("Failed to start Firmware\n");
+ goto _fail_;
+ }
+#if defined(PLAT_AML8726_M3)//[[ johnny : because of dummy irq
+ _available_irq_ready = 1;
+#endif
+
+ /* wait for mac ready */
+ PRINT_D(INIT_DBG,"Waiting for Firmware to get ready ...\n");
+ linux_wlan_lock(&nic->sync_event);
+ /*
+ TODO: Driver shouoldn't wait forever for firmware to get started -
+ in case of timeout this should be handled properly
+ */
+ PRINT_D(INIT_DBG,"Firmware successfully started\n");
+
+_fail_:
+ return ret;
+}
+static int linux_wlan_firmware_download(linux_wlan_t* p_nic){
+
+ int ret = 0;
+ linux_wlan_t* nic = p_nic;
+
+ if(nic->nmc_firmware == NULL){
+ PRINT_ER("Firmware buffer is NULL\n");
+ ret = -ENOBUFS;
+ goto _FAIL_;
+ }
+ /**
+ do the firmware download
+ **/
+ PRINT_D(INIT_DBG,"Downloading Firmware ...\n");
+ ret = nic->oup.wlan_firmware_download(nic->nmc_firmware->data, nic->nmc_firmware->size);
+ if(ret < 0){
+ goto _FAIL_;
+ }
+
+ /* Freeing FW buffer */
+ PRINT_D(INIT_DBG,"Freeing FW buffer ...\n");
+ PRINT_D(GENERIC_DBG,"Releasing firmware\n");
+ release_firmware(nic->nmc_firmware);
+ nic->nmc_firmware = NULL;
+
+ PRINT_D(INIT_DBG,"Download Succeeded \n");
+
+_FAIL_:
+ return ret;
+}
+
+
+/* startup configuration - could be changed later using iconfig*/
+static int linux_wlan_init_test_config(linux_wlan_t* p_nic){
+
+ linux_wlan_t* nic = p_nic;
+ unsigned char c_val[64];
+ unsigned char mac_add[] = {0x00, 0x80, 0xC2, 0x5E, 0xa2, 0xb2};
+ unsigned int chipid = 0;
+ PRINT_D(TX_DBG,"Start configuring Firmware\n");
+
+ get_random_bytes(&mac_add[5], 1);
+
+ printk("MAC address is : %02x-%02x-%02x-%02x-%02x-%02x\n", mac_add[0],mac_add[1],mac_add[2],mac_add[3],mac_add[4],mac_add[5]);
+ chipid = nmi_get_chipid(0);
+
+
+
+ /*to tell fw that we are going to use PC test - NMI specific*/
+ c_val[0] = 0;
+ if (!nic->oup.wlan_cfg_set(1, WID_PC_TEST_MODE, c_val, 1, 0))
+ goto _fail_;
+
+ c_val[0] = INFRASTRUCTURE;
+ if (!nic->oup.wlan_cfg_set(0, WID_BSS_TYPE, c_val, 1, 0))
+ goto _fail_;
+
+ c_val[0] = G_MIXED_11B_2_MODE;
+ if (!nic->oup.wlan_cfg_set(0, WID_11G_OPERATING_MODE, c_val, 1, 0))
+ goto _fail_;
+
+ c_val[0] = RATE_AUTO; /* bug 4275: Enable autorate and limit it to 24Mbps */
+ if (!nic->oup.wlan_cfg_set(0, WID_CURRENT_TX_RATE, c_val, 1, 0))
+ goto _fail_;
+
+ c_val[0] = 1;
+ if (!nic->oup.wlan_cfg_set(0, WID_CURRENT_CHANNEL, c_val, 1, 0))
+ goto _fail_;
+
+ c_val[0] = G_SHORT_PREAMBLE;
+ if (!nic->oup.wlan_cfg_set(0, WID_PREAMBLE, c_val, 1, 0))
+ goto _fail_;
+
+ c_val[0] = AUTO_PROT;
+ if (!nic->oup.wlan_cfg_set(0, WID_11N_PROT_MECH, c_val, 1, 0))
+ goto _fail_;
+
+ c_val[0] = ACTIVE_SCAN;
+ if (!nic->oup.wlan_cfg_set(0, WID_SCAN_TYPE, c_val, 1, 0))
+ goto _fail_;
+
+ c_val[0] = SITE_SURVEY_OFF;
+ if (!nic->oup.wlan_cfg_set(0, WID_SITE_SURVEY, c_val, 1, 0))
+ goto _fail_;
+
+ *((int *)c_val) = 0xffff; /* Never use RTS-CTS */
+ if (!nic->oup.wlan_cfg_set(0, WID_RTS_THRESHOLD, c_val, 2, 0))
+ goto _fail_;
+
+ *((int *)c_val) = 2346;
+ if (!nic->oup.wlan_cfg_set(0, WID_FRAG_THRESHOLD, c_val, 2, 0))
+ goto _fail_;
+
+ /* SSID */
+ /* -------------------------------------------------------------- */
+ /* Configuration : String with length less than 32 bytes */
+ /* Values to set : Any string with length less than 32 bytes */
+ /* ( In BSS Station Set SSID to "" (null string) */
+ /* to enable Broadcast SSID suppport ) */
+ /* -------------------------------------------------------------- */
+#ifndef USE_WIRELESS
+ strcpy(c_val, "nwifi");
+ if (!nic->oup.wlan_cfg_set(0, WID_SSID, c_val, (strlen(c_val)+1), 0))
+ goto _fail_;
+#endif
+
+ c_val[0] = 0;
+ if (!nic->oup.wlan_cfg_set(0, WID_BCAST_SSID, c_val, 1, 0))
+ goto _fail_;
+
+ c_val[0] = 1;
+ if (!nic->oup.wlan_cfg_set(0, WID_QOS_ENABLE, c_val, 1, 0))
+ goto _fail_;
+
+ c_val[0] = NO_POWERSAVE;
+ if (!nic->oup.wlan_cfg_set(0, WID_POWER_MANAGEMENT, c_val, 1, 0))
+ goto _fail_;
+
+ c_val[0] = NO_ENCRYPT; //NO_ENCRYPT, 0x79
+ if (!nic->oup.wlan_cfg_set(0, WID_11I_MODE, c_val, 1, 0))
+ goto _fail_;
+
+ c_val[0] = OPEN_SYSTEM;
+ if (!nic->oup.wlan_cfg_set(0, WID_AUTH_TYPE, c_val, 1, 0))
+ goto _fail_;
+
+ /* WEP/802 11I Configuration */
+ /* ------------------------------------------------------------------ */
+ /* Configuration : WEP Key */
+ /* Values (0x) : 5 byte for WEP40 and 13 bytes for WEP104 */
+ /* In case more than 5 bytes are passed on for WEP 40 */
+ /* only first 5 bytes will be used as the key */
+ /* ------------------------------------------------------------------ */
+
+ strcpy(c_val, "123456790abcdef1234567890");
+ if (!nic->oup.wlan_cfg_set(0, WID_WEP_KEY_VALUE, c_val, (strlen(c_val)+1), 0))
+ goto _fail_;
+
+ /* WEP/802 11I Configuration */
+ /* ------------------------------------------------------------------ */
+ /* Configuration : AES/TKIP WPA/RSNA Pre-Shared Key */
+ /* Values to set : Any string with length greater than equal to 8 bytes */
+ /* and less than 64 bytes */
+ /* ------------------------------------------------------------------ */
+ strcpy(c_val, "12345678");
+ if (!nic->oup.wlan_cfg_set(0, WID_11I_PSK, c_val, (strlen(c_val)), 0))
+ goto _fail_;
+
+ /* IEEE802.1X Key Configuration */
+ /* ------------------------------------------------------------------ */
+ /* Configuration : Radius Server Access Secret Key */
+ /* Values to set : Any string with length greater than equal to 8 bytes */
+ /* and less than 65 bytes */
+ /* ------------------------------------------------------------------ */
+ strcpy(c_val, "password");
+ if (!nic->oup.wlan_cfg_set(0, WID_1X_KEY, c_val, (strlen(c_val)+1), 0))
+ goto _fail_;
+
+ /* IEEE802.1X Server Address Configuration */
+ /* ------------------------------------------------------------------ */
+ /* Configuration : Radius Server IP Address */
+ /* Values to set : Any valid IP Address */
+ /* ------------------------------------------------------------------ */
+ c_val[0] = 192;
+ c_val[1] = 168;
+ c_val[2] = 1;
+ c_val[3] = 112;
+ if (!nic->oup.wlan_cfg_set(0, WID_1X_SERV_ADDR, c_val, 4, 0))
+ goto _fail_;
+
+ c_val[0] = 3;
+ if (!nic->oup.wlan_cfg_set(0, WID_LISTEN_INTERVAL, c_val, 1, 0))
+ goto _fail_;
+
+ c_val[0] = 3;
+ if (!nic->oup.wlan_cfg_set(0, WID_DTIM_PERIOD, c_val, 1, 0))
+ goto _fail_;
+
+ c_val[0] = NORMAL_ACK;
+ if (!nic->oup.wlan_cfg_set(0, WID_ACK_POLICY, c_val, 1, 0))
+ goto _fail_;
+
+ c_val[0] = 0;
+ if (!nic->oup.wlan_cfg_set(0, WID_USER_CONTROL_ON_TX_POWER, c_val, 1, 0))
+ goto _fail_;
+
+ c_val[0] = 48;
+ if (!nic->oup.wlan_cfg_set(0, WID_TX_POWER_LEVEL_11A, c_val, 1, 0))
+ goto _fail_;
+
+ c_val[0] = 28;
+ if (!nic->oup.wlan_cfg_set(0, WID_TX_POWER_LEVEL_11B, c_val, 1, 0))
+ goto _fail_;
+
+ /* Beacon Interval */
+ /* -------------------------------------------------------------------- */
+ /* Configuration : Sets the beacon interval value */
+ /* Values to set : Any 16-bit value */
+ /* -------------------------------------------------------------------- */
+
+ *((int *)c_val) = 100;
+ if (!nic->oup.wlan_cfg_set(0, WID_BEACON_INTERVAL, c_val, 2, 0))
+ goto _fail_;
+
+ c_val[0] = REKEY_DISABLE;
+ if (!nic->oup.wlan_cfg_set(0, WID_REKEY_POLICY, c_val, 1, 0))
+ goto _fail_;
+
+ /* Rekey Time (s) (Used only when the Rekey policy is 2 or 4) */
+ /* -------------------------------------------------------------------- */
+ /* Configuration : Sets the Rekey Time (s) */
+ /* Values to set : 32-bit value */
+ /* -------------------------------------------------------------------- */
+ *((int *)c_val) = 84600;
+ if (!nic->oup.wlan_cfg_set(0, WID_REKEY_PERIOD, c_val, 4, 0))
+ goto _fail_;
+
+ /* Rekey Packet Count (in 1000s; used when Rekey Policy is 3) */
+ /* -------------------------------------------------------------------- */
+ /* Configuration : Sets Rekey Group Packet count */
+ /* Values to set : 32-bit Value */
+ /* -------------------------------------------------------------------- */
+ *((int *)c_val) = 500;
+ if (!nic->oup.wlan_cfg_set(0, WID_REKEY_PACKET_COUNT, c_val, 4, 0))
+ goto _fail_;
+
+ c_val[0] = 1;
+ if (!nic->oup.wlan_cfg_set(0, WID_SHORT_SLOT_ALLOWED, c_val, 1, 0))
+ goto _fail_;
+
+ c_val[0] = G_SELF_CTS_PROT;
+ if (!nic->oup.wlan_cfg_set(0, WID_11N_ERP_PROT_TYPE, c_val, 1, 0))
+ goto _fail_;
+
+ if((chipid & 0xfff) > 0xd0)
+ c_val[0] = 1; /* Enable N */
+ else
+ c_val[0] = 0; /* Disable N */
+
+ if (!nic->oup.wlan_cfg_set(0, WID_11N_ENABLE, c_val, 1, 0))
+ goto _fail_;
+
+ c_val[0] = HT_MIXED_MODE;
+ if (!nic->oup.wlan_cfg_set(0, WID_11N_OPERATING_MODE, c_val, 1, 0))
+ goto _fail_;
+
+ c_val[0] = 1; /* TXOP Prot disable in N mode: No RTS-CTS on TX A-MPDUs to save air-time. */
+ if (!nic->oup.wlan_cfg_set(0, WID_11N_TXOP_PROT_DISABLE, c_val, 1, 0))
+ goto _fail_;
+
+ memcpy(c_val, mac_add, 6);
+
+ if (!nic->oup.wlan_cfg_set(0, WID_MAC_ADDR, c_val, 6, 0))
+ goto _fail_;
+
+ /**
+ AP only
+ **/
+ c_val[0] = DETECT_PROTECT_REPORT;
+ if (!nic->oup.wlan_cfg_set(0, WID_11N_OBSS_NONHT_DETECTION, c_val, 1, 0))
+ goto _fail_;
+
+ c_val[0] = RTS_CTS_NONHT_PROT;
+ if (!nic->oup.wlan_cfg_set(0, WID_11N_HT_PROT_TYPE, c_val, 1, 0))
+ goto _fail_;
+
+ c_val[0] = 0;
+ if (!nic->oup.wlan_cfg_set(0, WID_11N_RIFS_PROT_ENABLE, c_val, 1, 0))
+ goto _fail_;
+
+ c_val[0] = MIMO_MODE;
+ if (!nic->oup.wlan_cfg_set(0, WID_11N_SMPS_MODE, c_val, 1, 0))
+ goto _fail_;
+
+ c_val[0] = 6; /* Limit TX rate below MCS-7 for NMC1000F0. Should be changed in to 7 in NMC1002. */
+ if (!nic->oup.wlan_cfg_set(0, WID_11N_CURRENT_TX_MCS, c_val, 1, 0))
+ goto _fail_;
+
+ c_val[0] = 1; /* Enable N with immediate block ack. */
+ if (!nic->oup.wlan_cfg_set(0, WID_11N_IMMEDIATE_BA_ENABLED, c_val, 1, 0))
+ goto _fail_;
+
+ /*Adde by Amr - BugID 4707*/
+ /*A mandatory restart mac has to be done initially.*/
+ /*So wid reset is sent with startup configrations*/
+ c_val[0] = 1;
+ if (!nic->oup.wlan_cfg_set(0, WID_RESET, c_val, 1, 1))
+ goto _fail_;
+
+ return 0;
+
+_fail_:
+ return -1;
+}
+
+
+/**************************/
+void nmc1000_wlan_deinit(linux_wlan_t *nic) {
+
+ if(nic->nmc1000_initialized)
+ {
+
+ PRINT_D(INIT_DBG,"Deinitializing nmc1000 ...\n");
+
+ if(nic == NULL){
+ PRINT_ER("nic is NULL\n");
+ return;
+ }
+
+ nmi_bus_set_default_speed();
+
+ PRINT_D(INIT_DBG,"Disabling IRQ\n");
+ #if (!defined NMI_SDIO) || (defined NMI_SDIO_IRQ_GPIO)
+ linux_wlan_disable_irq(IRQ_WAIT);
+ #else
+ disable_sdio_interrupt();
+ #endif
+
+
+ /* not sure if the following unlocks are needed or not*/
+ if(&nic->rxq_event != NULL){
+ linux_wlan_unlock(&nic->rxq_event);
+ }
+
+ if(&nic->txq_event != NULL){
+ linux_wlan_unlock(&nic->txq_event);
+ }
+
+
+ #if (RX_BH_TYPE == RX_BH_WORK_QUEUE)
+ /*Removing the work struct from the linux kernel workqueue*/
+ if(&nic->rx_work_queue != NULL)
+ flush_work(&nic->rx_work_queue);
+
+ #elif (RX_BH_TYPE == RX_BH_KTHREAD)
+ //if(&nic->rx_sem != NULL)
+ //linux_wlan_unlock(&nic->rx_sem);
+ #endif
+
+ PRINT_D(INIT_DBG,"Deinitializing Threads\n");
+ wlan_deinitialize_threads(nic);
+
+ PRINT_D(INIT_DBG,"Deinitializing IRQ\n");
+ deinit_irq(nic);
+
+
+ if(&nic->oup != NULL){
+ if(nic->oup.wlan_stop != NULL)
+ nic->oup.wlan_stop();
+ }
+
+ PRINT_D(INIT_DBG,"Deinitializing NMI Wlan\n");
+ nmi_wlan_deinit(nic);
+
+ /*De-Initialize locks*/
+ PRINT_D(INIT_DBG,"Deinitializing Locks\n");
+ wlan_deinit_locks(nic);
+
+ /* announce that nmc1000 is not initialized */
+ nic->nmc1000_initialized = 0;
+
+ PRINT_D(INIT_DBG,"nmc1000 deinitialization Done\n");
+
+ }else{
+ PRINT_D(INIT_DBG,"nmc1000 is not initialized\n");
+ }
+
+ return;
+}
+
+int wlan_init_locks(linux_wlan_t* p_nic){
+
+ linux_wlan_t* nic = p_nic;
+
+ PRINT_D(INIT_DBG,"Initializing Locks ...\n");
+
+ /*initialize mutexes*/
+ linux_wlan_init_mutex("hif_lock/hif_cs",&nic->hif_cs,1);
+ linux_wlan_init_mutex("rxq_lock/rxq_cs",&nic->rxq_cs,1);
+ linux_wlan_init_mutex("txq_lock/txq_cs",&nic->txq_cs,1);
+
+ linux_wlan_init_lock("txq_wait/txq_event",&nic->txq_event,0);
+ linux_wlan_init_lock("rxq_wait/rxq_event",&nic->rxq_event,0);
+
+ linux_wlan_init_lock("cfg_wait/cfg_event",&nic->cfg_event,0);
+ linux_wlan_init_lock("sync_event",&nic->sync_event,0);
+
+ linux_wlan_init_lock("rxq_lock/rxq_started",&nic->rxq_thread_started,0);
+ linux_wlan_init_lock("rxq_lock/txq_started",&nic->txq_thread_started,0);
+
+ #if (RX_BH_TYPE == RX_BH_KTHREAD)
+ linux_wlan_init_lock("BH_SEM", &nic->rx_sem, 0);
+ #endif
+
+ return 0;
+}
+
+static int wlan_deinit_locks(linux_wlan_t* nic){
+ PRINT_D(INIT_DBG,"De-Initializing Locks\n");
+
+ if(&nic->hif_cs != NULL)
+ linux_wlan_deinit_mutex(&nic->hif_cs);
+
+ if(&nic->rxq_cs != NULL)
+ linux_wlan_deinit_mutex(&nic->rxq_cs);
+
+ if(&nic->txq_cs != NULL)
+ linux_wlan_deinit_mutex(&nic->txq_cs);
+
+ if(&nic->rxq_event != NULL)
+ linux_wlan_deinit_lock(&nic->rxq_event);
+
+ if(&nic->txq_event != NULL)
+ linux_wlan_deinit_lock(&nic->txq_event);
+
+ if(&nic->rxq_thread_started != NULL)
+ linux_wlan_deinit_lock(&nic->rxq_thread_started);
+
+ if(&nic->txq_thread_started != NULL)
+ linux_wlan_deinit_lock(&nic->txq_thread_started);
+
+ if(&nic->cfg_event != NULL)
+ linux_wlan_deinit_lock(&nic->cfg_event);
+
+ if(&nic->sync_event != NULL)
+ linux_wlan_deinit_lock(&nic->sync_event);
+
+ return 0;
+}
+void linux_to_wlan(nmi_wlan_inp_t* nwi,linux_wlan_t* nic){
+
+ PRINT_D(INIT_DBG,"Linux to Wlan services ...\n");
+
+ nwi->os_context.hif_critical_section = (void *)&nic->hif_cs;
+ nwi->os_context.os_private = (void *)nic;
+ nwi->os_context.tx_buffer_size = LINUX_TX_SIZE;
+ nwi->os_context.txq_critical_section = (void *)&nic->txq_cs;
+ nwi->os_context.txq_wait_event = (void *)&nic->txq_event;
+ //nwi.os_context.rx_buffer_size = LINUX_RX_SIZE;
+ nwi->os_context.rxq_critical_section = (void *)&nic->rxq_cs;
+ nwi->os_context.rxq_wait_event = (void *)&nic->rxq_event;
+ nwi->os_context.cfg_wait_event = (void *)&nic->cfg_event;
+
+ nwi->os_func.os_sleep = linux_wlan_msleep;
+ nwi->os_func.os_atomic_sleep = linux_wlan_atomic_msleep;
+ nwi->os_func.os_debug = linux_wlan_dbg;
+ nwi->os_func.os_malloc = linux_wlan_malloc;
+ nwi->os_func.os_malloc_atomic = linux_wlan_malloc_atomic;
+ nwi->os_func.os_free = linux_wlan_free;
+ nwi->os_func.os_lock = linux_wlan_lock;
+ nwi->os_func.os_unlock = linux_wlan_unlock;
+ nwi->os_func.os_wait = linux_wlan_lock_timeout;
+ nwi->os_func.os_signal = linux_wlan_unlock;
+ nwi->os_func.os_enter_cs = linux_wlan_lock_mutex;
+ nwi->os_func.os_leave_cs = linux_wlan_unlock_mutex;
+#ifdef NMI_SDIO
+ nwi->io_func.io_type = HIF_SDIO;
+ nwi->io_func.io_init = linux_sdio_init;
+ nwi->io_func.io_deinit = linux_sdio_deinit;
+ nwi->io_func.u.sdio.sdio_cmd52 = linux_sdio_cmd52;
+ nwi->io_func.u.sdio.sdio_cmd53 = linux_sdio_cmd53;
+ nwi->io_func.u.sdio.sdio_set_max_speed = linux_sdio_set_max_speed;
+ nwi->io_func.u.sdio.sdio_set_default_speed = linux_sdio_set_default_speed;
+#else
+ nwi->io_func.io_type = HIF_SPI;
+ nwi->io_func.io_init = linux_spi_init;
+ nwi->io_func.io_deinit = linux_spi_deinit;
+ nwi->io_func.u.spi.spi_tx = linux_spi_write;
+ nwi->io_func.u.spi.spi_rx = linux_spi_read;
+ nwi->io_func.u.spi.spi_trx = linux_spi_write_read;
+ nwi->io_func.u.spi.spi_max_speed = linux_spi_set_max_speed;
+#endif
+
+ /*for now - to be revised*/
+ nwi->net_func.rx_indicate = frmw_to_linux;
+ nwi->net_func.rx_complete = linux_wlan_rx_complete;
+ nwi->indicate_func.mac_indicate = linux_wlan_mac_indicate;
+}
+
+int wlan_initialize_threads(linux_wlan_t* nic){
+
+ int ret = 0;
+ PRINT_D(INIT_DBG,"Initializing Threads ...\n");
+
+#if (RX_BH_TYPE == RX_BH_WORK_QUEUE)
+ /*Initialize rx work queue task*/
+ INIT_WORK(&nic->rx_work_queue, isr_bh_routine);
+#elif (RX_BH_TYPE == RX_BH_KTHREAD)
+ PRINT_D(INIT_DBG,"Creating kthread for Rxq BH\n");
+ nic->rx_bh_thread = kthread_run(isr_bh_routine,(void*)nic,"K_RXQ_BH");
+ if(nic->rx_bh_thread == 0){
+ PRINT_ER("couldn't create RX BH thread\n");
+ ret = -ENOBUFS;
+ goto _fail_;
+ }
+#endif
+
+ /* create rx task */
+ PRINT_D(INIT_DBG,"Creating kthread for reception\n");
+ nic->rxq_thread = kthread_run(linux_wlan_rxq_task,(void*)nic,"K_RXQ_TASK");
+ if(nic->rxq_thread == 0){
+ PRINT_ER("couldn't create RXQ thread\n");
+ ret = -ENOBUFS;
+ goto _fail_1;
+ }
+
+ /* wait for RXQ task to start. */
+ linux_wlan_lock(&nic->rxq_thread_started);
+
+ /* create tx task */
+ PRINT_D(INIT_DBG,"Creating kthread for transmission\n");
+ nic->txq_thread = kthread_run(linux_wlan_txq_task,(void*)nic,"K_TXQ_TASK");
+ if(nic->txq_thread == 0){
+ PRINT_ER("couldn't create TXQ thread\n");
+ ret = -ENOBUFS;
+ goto _fail_2;
+ }
+#ifdef DEBUG_MODE
+ PRINT_D(INIT_DBG,"Creating kthread for Debugging\n");
+ nic->txq_thread = kthread_run(DebuggingThreadTask,(void*)nic,"DebugThread");
+ if(nic->txq_thread == 0){
+ PRINT_ER("couldn't create TXQ thread\n");
+ ret = -ENOBUFS;
+ goto _fail_2;
+ }
+#endif
+ /* wait for TXQ task to start. */
+ linux_wlan_lock(&nic->txq_thread_started);
+
+ return 0;
+
+ _fail_2:
+ /*De-Initialize 2nd thread*/
+ nic->close = 1;
+ linux_wlan_unlock(&nic->rxq_event);
+ kthread_stop(nic->rxq_thread);
+
+ _fail_1:
+ #if(RX_BH_TYPE == RX_BH_KTHREAD)
+ /*De-Initialize 1st thread*/
+ nic->close = 1;
+ linux_wlan_unlock(&nic->rx_sem);
+ kthread_stop(nic->rx_bh_thread);
+ _fail_:
+ #endif
+ nic->close = 0;
+ return ret;
+}
+
+static void wlan_deinitialize_threads(linux_wlan_t* nic){
+
+ nic->close = 1;
+ PRINT_D(INIT_DBG,"Deinitializing Threads\n");
+ if(&nic->rxq_event != NULL)
+ linux_wlan_unlock(&nic->rxq_event);
+
+
+ if(nic->rxq_thread != NULL){
+ kthread_stop(nic->rxq_thread);
+ nic->rxq_thread = NULL;
+ }
+
+
+ if(&nic->txq_event != NULL)
+ linux_wlan_unlock(&nic->txq_event);
+
+
+ if(nic->txq_thread != NULL){
+ kthread_stop(nic->txq_thread);
+ nic->txq_thread = NULL;
+ }
+
+ #if(RX_BH_TYPE == RX_BH_KTHREAD)
+ if(&nic->rx_sem != NULL)
+ linux_wlan_unlock(&nic->rx_sem);
+
+ if(nic->rx_bh_thread != NULL){
+ kthread_stop(nic->rx_bh_thread);
+ nic->rx_bh_thread= NULL;
+ }
+ #endif
+}
+
+int nmc1000_wlan_init(linux_wlan_t* p_nic)
+{
+ nmi_wlan_inp_t nwi;
+ nmi_wlan_oup_t nwo;
+ linux_wlan_t* nic = p_nic;
+ int ret = 0;
+
+ if(!nic->nmc1000_initialized){
+ nic->mac_status = NMI_MAC_STATUS_INIT;
+ nic->close = 0;
+ nic->nmc1000_initialized = 0;
+#if defined(PLAT_AML8726_M3)//[[ johnny : because of dummy irq
+ _available_irq_ready = 0;
+#endif
+ wlan_init_locks(nic);
+
+ linux_to_wlan(&nwi,nic);
+
+ ret = nmi_wlan_init(&nwi, &nwo);
+ if (ret < 0) {
+ PRINT_ER("Initializing NMI_Wlan FAILED\n");
+ goto _fail_locks_;
+ }
+ memcpy(&nic->oup, &nwo, sizeof(nmi_wlan_oup_t));
+
+ /*Save the oup structre into global pointer*/
+ gpstrWlanOps = &nic->oup;
+
+
+ ret = wlan_initialize_threads(nic);
+ if (ret < 0) {
+ PRINT_ER("Initializing Threads FAILED\n");
+ goto _fail_irq_;
+ }
+
+#if (!defined NMI_SDIO) || (defined NMI_SDIO_IRQ_GPIO)
+ if(init_irq(nic)){
+ PRINT_ER("couldn't initialize IRQ\n");
+ ret = -EIO;
+ goto _fail_locks_;
+ }
+#endif
+
+#if (defined NMI_SDIO) && (!defined NMI_SDIO_IRQ_GPIO)
+ enable_sdio_interrupt();
+#endif
+
+ if(linux_wlan_get_firmware(nic)){
+ PRINT_ER("Can't get firmware \n");
+ goto _fail_threads_;
+ }
+
+ /*Download firmware*/
+ ret = linux_wlan_firmware_download(nic);
+ if(ret < 0){
+ PRINT_ER("Failed to download firmware\n");
+ goto _fail_threads_;
+ }
+
+ /* Start firmware*/
+ ret = linux_wlan_start_firmware(nic);
+ if(ret < 0){
+ PRINT_ER("Failed to start firmware\n");
+ goto _fail_threads_;
+ }
+
+ nmi_bus_set_max_speed();
+
+ /* Initialize firmware with default configuration */
+ ret = linux_wlan_init_test_config(nic);
+
+ if(ret < 0){
+ PRINT_ER("Failed to configure firmware\n");
+ goto _fail_threads_;
+ }
+
+ nic->nmc1000_initialized = 1;
+ return 0; /*success*/
+
+_fail_threads_:
+ wlan_deinitialize_threads(nic);
+_fail_irq_:
+#if (!defined NMI_SDIO) || (defined NMI_SDIO_IRQ_GPIO)
+ deinit_irq(nic);
+
+#endif
+_fail_locks_:
+ wlan_deinit_locks(nic);
+ PRINT_ER("WLAN Iinitialization FAILED\n");
+ }else{
+ PRINT_D(INIT_DBG,"nmc1000 already initialized\n");
+ }
+ return ret;
+}
+
+
+/*
+ - this function will be called automatically by OS when module inserted.
+*/
+
+#if !defined (NM73131_0_BOARD)
+int mac_init_fn(struct net_device *ndev){
+
+ /*Why we do this !!!*/
+ netif_start_queue(ndev); //ma
+ netif_stop_queue(ndev); //ma
+
+ return 0;
+}
+#else
+int mac_init_fn(struct net_device *ndev){
+
+ unsigned char mac_add[] = {0x00,0x50,0xc2,0x5e,0x10,0x00};
+ /* TODO: get MAC address whenever the source is EPROM - hardcoded and copy it to ndev*/
+ memcpy(ndev->dev_addr, mac_add, 6);
+
+ if(!is_valid_ether_addr(ndev->dev_addr)){
+ PRINT_ER("Error: Wrong MAC address\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+#endif
+
+/* This fn is called, when this device is setup using ifconfig */
+#if !defined (NM73131_0_BOARD)
+int mac_open(struct net_device *ndev){
+
+ linux_wlan_t* nic;
+ unsigned char mac_add[] = {0x00, 0x80, 0xC2, 0x5E, 0xa2, 0xb2};
+ int status;
+ int ret = 0;
+ struct NMI_WFI_priv* priv;
+
+ nic = netdev_priv(ndev);
+
+ linux_wlan_lock(&close_exit_sync);
+
+ /*initialize platform*/
+ ret = nmc1000_wlan_init(nic);
+ if(ret < 0)
+ {
+ PRINT_ER("Failed to initialize nmc1000\n");
+ linux_wlan_unlock(&close_exit_sync);
+ return ret;
+ }
+
+#ifdef USE_WIRELESS
+ ret = NMI_WFI_InitHostInt(ndev);
+ if(ret < 0)
+ {
+ PRINT_ER("Failed to initialize host interface\n");
+ nmc1000_wlan_deinit(nic);
+ linux_wlan_unlock(&close_exit_sync);
+ return ret;
+ }
+#endif
+
+
+ get_random_bytes(&mac_add[5], 1);
+
+
+#ifdef USE_WIRELESS
+ priv = wiphy_priv(nic->nmc_netdev->ieee80211_ptr->wiphy);
+ status = host_int_get_MacAddress(priv->hNMIWFIDrv, mac_add);
+#else
+ host_int_set_MacAddress(NULL, mac_add);
+ status = host_int_get_MacAddress(NULL, mac_add);
+#endif
+ /* TODO: get MAC address whenever the source is EPROM - hardcoded and copy it to ndev*/
+ memcpy(ndev->dev_addr, mac_add, ETH_ALEN);
+
+ if(!is_valid_ether_addr(ndev->dev_addr)){
+ PRINT_ER("Error: Wrong MAC address\n");
+ linux_wlan_unlock(&close_exit_sync);
+ return -EINVAL;
+ }
+ /* Start the network interface queue for this device */
+ PRINT_D(INIT_DBG,"Starting netifQ\n");
+ //netif_start_queue(ndev); ma
+ //enable interrupts
+ //enable_irq(g_linux_wlan->dev_irq_num);
+
+ netif_wake_queue(ndev);
+
+ //linux_wlan_lock(&close_exit_sync);
+
+ return 0;
+}
+#else
+int mac_open(struct net_device *ndev)
+{
+
+ linux_wlan_t* nic;
+ nic = netdev_priv(ndev);
+
+ /*initialize platform*/
+ if(nmc1000_wlan_init(nic)){
+ PRINT_ER("Failed to initialize platform\n");
+ return 1;
+ }
+ /* Start the network interface queue for this device */
+ PRINT_D(INIT_DBG,"Starting netifQ\n");
+ netif_start_queue(ndev);
+ linux_wlan_lock(&close_exit_sync);
+ return 0;
+}
+#endif
+
+struct net_device_stats *mac_stats(struct net_device *dev)
+{
+ linux_wlan_t* nic= netdev_priv(dev);
+
+
+ return &nic->netstats;
+}
+
+static void linux_wlan_tx_complete(void* priv, int status){
+
+ struct tx_complete_data* pv_data = (struct tx_complete_data*)priv;
+ if(status == 1){
+ PRINT_D(TX_DBG,"Packet sent successfully - Size = %d - Address = %p - SKB = %p\n",pv_data->size,pv_data->buff, pv_data->skb);
+ } else {
+ PRINT_D(TX_DBG,"Couldn't send packet - Size = %d - Address = %p - SKB = %p\n",pv_data->size,pv_data->buff, pv_data->skb);
+ }
+ /* Free the SK Buffer, its work is done */
+ dev_kfree_skb(pv_data->skb);
+ linux_wlan_free(pv_data);
+}
+
+int mac_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+ linux_wlan_t* nic;
+ struct tx_complete_data* tx_data = NULL;
+ int QueueCount;
+ //char* saddr,*daddr,*pu8UdpBuffer;
+ char *pu8UdpBuffer;
+ struct iphdr *ih;
+// struct ethhdr *eth;
+// char* ethsaddr,*ethdaddr;
+// int i;
+ //char* TestBuff;
+
+ PRINT_D(INT_DBG,"\n========\n IntUH: %d - IntBH: %d - IntCld: %d \n========\n",int_rcvdU,int_rcvdB,int_clrd);
+ nic = netdev_priv(ndev);
+
+ PRINT_D(TX_DBG,"Sending packet just received from TCP/IP\n");
+
+ /* Stop the network interface queue */
+ // netif_stop_queue(ndev);
+
+ if(skb->dev != ndev){
+ PRINT_ER("Packet not destined to this device\n");
+ return 0;
+ }
+
+ /* allocate memory for the frame - there is no need to allocate the fixed packet size 1496.
+ * just allocat memory with the length of the packet received - also don't put any constraint
+ * on the size of the packet to be received because this restriction is already handled inside firmware.
+ */
+/*
+ if(skb->len > 1496){
+ PRINT_ER("Unable to handle this large packet - Size = %d\n",skb->len);
+ }
+
+*/
+
+ tx_data = (struct tx_complete_data*)internal_alloc(sizeof(struct tx_complete_data),GFP_ATOMIC);
+ if(tx_data == NULL){
+ PRINT_ER("Failed to allocate memory for tx_data structure\n");
+ dev_kfree_skb(skb);
+ netif_wake_queue(ndev);
+ return 0;
+ }
+
+ tx_data->buff = skb->data;
+ tx_data->size = skb->len;
+ tx_data->skb = skb;
+ /*get source and dest ip addresses*/
+ ih = (struct iphdr *)(skb->data+sizeof(struct ethhdr));
+ //saddr = &ih->saddr;
+ //daddr = &ih->daddr;
+ //NMI_PRINTF("Source IP = %d:%d:%d:%d \n",saddr[0],saddr[1],
+ // saddr[2],saddr[3]);
+// NMI_PRINTF("Dest IP = %d:%d:%d:%d \n",daddr[0],daddr[1],
+ // daddr[2],daddr[3]);
+
+ pu8UdpBuffer = (char*)ih + sizeof(struct iphdr);
+ if(pu8UdpBuffer[1] == 68 && pu8UdpBuffer[3] == 67)
+ {
+ PRINT_D(TX_DBG,"DHCP Message transmitted\n");
+ }
+ PRINT_D(TX_DBG,"Sending packet - Size = %d - Address = %p - SKB = %p\n",tx_data->size,tx_data->buff,tx_data->skb);
+
+ /*eth = (struct ethhdr *)(skb->data);
+
+ ethsaddr = ð->h_source;
+ ethdaddr = ð->h_dest;
+
+ NMI_PRINTF("Source MAC = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x \n",ethsaddr[0],ethsaddr[1],
+ ethsaddr[2],ethsaddr[3],ethsaddr[4],ethsaddr[5]);
+ NMI_PRINTF("Dest MAC = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x \n",ethdaddr[0],ethdaddr[1],
+ ethdaddr[2],ethdaddr[3],ethdaddr[4],ethdaddr[5]);*/
+
+ //NMI_PRINTF("sending pkt \n");
+
+ // NMI_PRINTF("skb->data[12] = %2x, skb->data[13] = %2x \n");
+ /*TestBuff = (char*)(skb->data + sizeof(struct ethhdr));
+
+ for(i = 0; i < 30; i++)
+ {
+ if(i < skb->len)
+ {
+ NMI_PRINTF("TestBuff[%d] = %2x \n", i, TestBuff[i]);
+ }
+ }*/
+
+ /* Send packet to MAC HW - for now the tx_complete function will be just status
+ * indicator. still not sure if I need to suspend host transmission till the tx_complete
+ * function called or not?
+ * allocated buffer will be freed in tx_complete function.
+ */
+ PRINT_D(TX_DBG,"Adding tx packet to TX Queue\n");
+ nic->netstats.tx_packets++;
+ nic->netstats.tx_bytes+=tx_data->size;
+ QueueCount = nic->oup.wlan_add_to_tx_que((void*)tx_data,
+ tx_data->buff,
+ tx_data->size,
+ linux_wlan_tx_complete);
+
+
+ if(QueueCount > FLOW_CONTROL_UPPER_THRESHOLD)
+ {
+ // printk("Stopping queue\n");
+ netif_stop_queue(ndev);
+
+ }
+
+
+ /* Wake up the network interface queue */
+ //netif_wake_queue(ndev);
+
+
+ return 0;
+}
+
+
+int mac_close(struct net_device *ndev)
+{
+
+ linux_wlan_t* nic;
+
+ nic = netdev_priv(ndev);
+
+ PRINT_D(GENERIC_DBG,"Mac close\n");
+
+ /* Stop the network interface queue */
+ netif_stop_queue(ndev);
+
+#ifdef USE_WIRELESS
+ NMI_WFI_DeInitHostInt(ndev);
+#endif
+
+ PRINT_D(GENERIC_DBG,"Deinitializing nmc1000\n");
+ nmc1000_wlan_deinit(nic);
+
+#ifdef USE_WIRELESS
+#ifdef NMI_AP_EXTERNAL_MLME
+ NMI_WFI_deinit_mon_interface();
+#endif
+#endif
+ linux_wlan_unlock(&close_exit_sync);
+
+ return 0;
+}
+
+
+int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd){
+
+ NMI_Uint8 *buff= NULL;
+ NMI_Sint8 rssi;
+ NMI_Uint32 size=0,length=0;
+ linux_wlan_t* nic;
+ struct NMI_WFI_priv* priv;
+ NMI_Sint32 s32Error = NMI_SUCCESS;
+
+
+
+ //struct iwreq *wrq = (struct iwreq *) req; // tony moved to case SIOCSIWPRIV
+ #ifdef USE_WIRELESS
+ nic = netdev_priv(ndev);
+
+ if(!nic->nmc1000_initialized)
+ return 0;
+
+ #endif
+
+ switch(cmd){
+ // [[ added by tony for SIOCDEVPRIVATE
+ case SIOCDEVPRIVATE+1:
+ {
+ android_wifi_priv_cmd priv_cmd;
+
+ PRINT_D(GENERIC_DBG, "in SIOCDEVPRIVATE+1\n");
+
+ if (copy_from_user(&priv_cmd, req->ifr_data, sizeof(android_wifi_priv_cmd))) {
+ s32Error = -EFAULT;
+ goto done;
+ }
+
+ buff = kmalloc(priv_cmd.total_len, GFP_KERNEL);
+ if (!buff)
+ {
+ s32Error = -ENOMEM;
+ goto done;
+ }
+
+ if (copy_from_user(buff, priv_cmd.buf, priv_cmd.total_len)) {
+ s32Error = -EFAULT;
+ goto done;
+ }
+
+ PRINT_D(GENERIC_DBG, "%s: Android private cmd \"%s\" on %s\n", __FUNCTION__, buff, req->ifr_name);
+
+ if (strnicmp(buff, "SCAN-ACTIVE", strlen("SCAN-ACTIVE")) == 0) {
+ PRINT_D(GENERIC_DBG, "%s, SCAN-ACTIVE command\n", __FUNCTION__);
+ }else if (strnicmp(buff, "SCAN-PASSIVE", strlen("SCAN-PASSIVE")) == 0) {
+ PRINT_D(GENERIC_DBG, "%s, SCAN-PASSIVE command\n", __FUNCTION__);
+ }else if (strnicmp(buff, "RXFILTER-START", strlen("RXFILTER-START")) == 0) {
+ PRINT_D(GENERIC_DBG, "%s, RXFILTER-START command\n", __FUNCTION__);
+ }else if (strnicmp(buff, "RXFILTER-STOP", strlen("RXFILTER-STOP")) == 0) {
+ PRINT_D(GENERIC_DBG, "%s, RXFILTER-STOP command\n", __FUNCTION__);
+ }else if (strnicmp(buff, "RXFILTER-ADD", strlen("RXFILTER-ADD")) == 0) {
+ int filter_num = *(buff + strlen("RXFILTER-ADD") + 1) - '0';
+ PRINT_D(GENERIC_DBG, "%s, RXFILTER-ADD command, filter_num=%d\n", __FUNCTION__, filter_num);
+ }else if (strnicmp(buff, "RXFILTER-REMOVE", strlen("RXFILTER-REMOVE")) == 0) {
+ int filter_num = *(buff + strlen("RXFILTER-REMOVE") + 1) - '0';
+ PRINT_D(GENERIC_DBG, "%s, RXFILTER-REMOVE command, filter_num=%d\n", __FUNCTION__, filter_num);
+ }else if (strnicmp(buff, "BTCOEXSCAN-START", strlen("BTCOEXSCAN-START")) == 0) {
+ PRINT_D(GENERIC_DBG, "%s, BTCOEXSCAN-START command\n", __FUNCTION__);
+ }else if (strnicmp(buff, "BTCOEXSCAN-STOP", strlen("BTCOEXSCAN-STOP")) == 0) {
+ PRINT_D(GENERIC_DBG, "%s, BTCOEXSCAN-STOP command\n", __FUNCTION__);
+ }else if (strnicmp(buff, "BTCOEXMODE", strlen("BTCOEXMODE")) == 0) {
+ PRINT_D(GENERIC_DBG, "%s, BTCOEXMODE command\n", __FUNCTION__);
+ }else if (strnicmp(buff, "SETBAND", strlen("SETBAND")) == 0) {
+ uint band = *(buff + strlen("SETBAND") + 1) - '0';
+ PRINT_D(GENERIC_DBG, "%s, SETBAND command, band=%d\n", __FUNCTION__, band);
+ }else if (strnicmp(buff, "GETBAND", strlen("GETBAND")) == 0) {
+ PRINT_D(GENERIC_DBG, "%s, GETBAND command\n", __FUNCTION__);
+ }else if (strnicmp(buff, "COUNTRY", strlen("COUNTRY")) == 0) {
+ char *country_code = buff + strlen("COUNTRY") + 1;
+ PRINT_D(GENERIC_DBG, "%s, COUNTRY command, country_code=%s\n", __FUNCTION__, country_code);
+ }else {
+ PRINT_D(GENERIC_DBG, "%s, Unknown command\n", __FUNCTION__);
+ }
+ }break;
+ // ]] 2013-06-24
+ case SIOCSIWPRIV:
+ {
+ struct iwreq *wrq = (struct iwreq *) req; // added by tony
+
+ size = wrq->u.data.length;
+
+ if (size&& wrq->u.data.pointer)
+ {
+ buff = kmalloc(size, GFP_KERNEL);
+ if (!buff)
+ {
+ s32Error = -ENOMEM;
+ goto done;
+ }
+
+ if (copy_from_user
+ (buff, wrq->u.data.pointer,
+ wrq->u.data.length))
+ {
+ s32Error = -EFAULT;
+ goto done;
+ }
+
+ if(strnicmp(buff,"RSSI",length) == 0)
+ {
+
+ #ifdef USE_WIRELESS
+ priv = wiphy_priv(nic->nmc_netdev->ieee80211_ptr->wiphy);
+ s32Error = host_int_get_rssi(priv->hNMIWFIDrv, &(rssi));
+ if(s32Error)
+ PRINT_ER("Failed to send get rssi param's message queue ");
+ #endif
+ PRINT_INFO(GENERIC_DBG,"RSSI :%d\n",rssi);
+
+ /*Rounding up the rssi negative value*/
+ rssi+=5;
+
+ snprintf(buff, size, "rssi %d", rssi);
+
+ if (copy_to_user(wrq->u.data.pointer, buff, size)) {
+ PRINT_ER("%s: failed to copy data to user buffer\n", __FUNCTION__);
+ s32Error = -EFAULT;
+ goto done;
+ }
+ }
+ }
+ }
+ break;
+ default:
+ {
+ PRINT_INFO(GENERIC_DBG,"Command - %d - has been received\n",cmd);
+ s32Error = -EOPNOTSUPP;
+ goto done;
+ }
+ }
+
+done:
+
+ if(buff != NULL)
+ {
+ kfree(buff);
+ }
+
+ return s32Error;
+}
+
+void frmw_to_linux(uint8_t *buff, uint32_t size){
+
+ unsigned int frame_len = 0;
+ int stats;
+ unsigned char* buff_to_send = NULL;
+ struct sk_buff *skb;
+ //char *saddr,*daddr;
+ char*pu8UdpBuffer;
+ struct iphdr *ih;
+// static int once = 1;
+// int i;
+ linux_wlan_t *nic;
+
+ if(size > 0){
+
+ frame_len = size;
+ buff_to_send = buff;
+
+
+ /* Need to send the packet up to the host, allocate a skb buffer */
+ skb = dev_alloc_skb(frame_len);
+ if(skb == NULL){
+ PRINT_ER("Low memory - packet droped\n");
+ return;
+ }
+
+ skb_reserve(skb, (unsigned int)skb->data & 0x3);
+
+ if(g_linux_wlan == NULL || g_linux_wlan->nmc_netdev == NULL){
+ PRINT_ER("nmc_netdev in g_linux_wlan is NULL");
+ }
+ skb->dev = g_linux_wlan->nmc_netdev;
+
+ if(skb->dev == NULL){
+ PRINT_ER("skb->dev is NULL\n");
+ }
+
+ /*
+ for(i=0;i<40;i++)
+ {
+ if(i<frame_len)
+ NMI_PRINTF("buff_to_send[%d]=%2x\n",i,buff_to_send[i]);
+
+ }*/
+
+ //skb_put(skb, frame_len);
+ memcpy(skb_put(skb, frame_len),buff_to_send, frame_len);
+
+ //NMI_PRINTF("After MEM_CPY\n");
+
+ nic = netdev_priv(g_linux_wlan->nmc_netdev);
+#ifdef USE_WIRELESS
+ /* if(nic->monitor_flag)
+ {
+ NMI_WFI_monitor_rx(g_linux_wlan->nmc_netdev,skb);
+ return;
+ }*/
+#endif
+ skb->protocol = eth_type_trans(skb, g_linux_wlan->nmc_netdev);
+ /*get source and dest ip addresses*/
+ ih = (struct iphdr *)(skb->data+sizeof(struct ethhdr));
+ //saddr = &ih->saddr;
+ //daddr = &ih->daddr;
+ //NMI_PRINTF("[REC]Source IP = %.2x:%.2x:%.2x:%.2x",saddr[0],saddr[1],
+ //saddr[2],saddr[3]);
+ //NMI_PRINTF("[REC]Dest IP = %.2x:%.2x:%.2x:%.2x",daddr[0],daddr[1],
+ // daddr[2],daddr[3]);
+ //NMI_PRINTF("Protocol = %4x\n",skb->protocol);
+ pu8UdpBuffer = (char*)ih + sizeof(struct iphdr);
+ //printk("Port No = %d,%d\n",pu8UdpBuffer[1],pu8UdpBuffer[3]);
+ if(buff_to_send[35] == 67 && buff_to_send[37] == 68)
+ {
+ PRINT_D(RX_DBG,"DHCP Message received\n");
+ }
+
+ /* Send the packet to the stack by giving it to the bridge */
+ nic->netstats.rx_packets++;
+ nic->netstats.rx_bytes+=frame_len;
+ stats = netif_rx(skb);
+ //printk("netif_rx ret value is: %d\n",stats);
+ PRINT_D(RX_DBG,"netif_rx ret value is: %d\n",stats);
+ }else{
+ PRINT_ER("Discard sending packet with len = %d\n",size);
+ }
+}
+
+int nmc_netdev_init(void){
+
+ linux_wlan_t* nic;
+ struct net_device* ndev;
+
+ linux_wlan_init_lock("close_exit_sync",&close_exit_sync,1);
+
+ /*allocate ethernet device with linux_wlan_t as its private data*/
+ if(! (ndev = alloc_etherdev(sizeof(linux_wlan_t)))){
+ PRINT_ER("Failed to allocate ethernet dev\n");
+ return -1;
+ }
+
+ nic = netdev_priv(ndev);
+ memset(nic,sizeof(linux_wlan_t),0);
+
+ nic->nmc_netdev = ndev;
+
+
+ /*Reset interrupt count debug*/
+ int_rcvdU= 0;
+ int_rcvdB= 0;
+ int_clrd = 0;
+
+ g_linux_wlan = nic;
+
+ ether_setup(ndev);
+
+#if defined(NM73131) // tony, 2012-09-20
+ strcpy(ndev->name,"nmc_eth%d");
+#else //PANDA_BOARD, PLAT_ALLWINNER_A10, PLAT_ALLWINNER_A20, PLAT_AML8726_M3 or PLAT_WMS8304
+ strcpy(ndev->name,"wlan%d");
+#endif
+ nmc_set_netdev_ops(ndev);
+#ifdef USE_WIRELESS
+{
+ struct wireless_dev *wdev;
+ /*Register WiFi*/
+ wdev = NMI_WFI_WiphyRegister(ndev);
+ if(wdev == NULL){
+ PRINT_ER("Can't register NMI Wiphy\n");
+ return -1;
+ }
+
+ /*Pointing the priv structure the netdev*/
+
+ /*linking the wireless_dev structure with the netdevice*/
+ nic->nmc_netdev->ieee80211_ptr = wdev;
+ nic->nmc_netdev->ml_priv = nic;
+ wdev->netdev = nic->nmc_netdev;
+ nic->netstats.rx_packets=0;
+ nic->netstats.tx_packets=0;
+ nic->netstats.rx_bytes=0;
+ nic->netstats.tx_bytes=0;
+
+}
+#endif
+
+
+ if(register_netdev(ndev)){
+ PRINT_ER("Device couldn't be registered - %s\n", ndev->name);
+ return -1; /* ERROR */
+ }
+
+
+
+#ifndef NMI_SDIO
+ if(!linux_spi_init(&nic->nmc_spidev)){
+ PRINT_ER("Can't initialize SPI \n");
+ return -1; /* ERROR */
+ }
+ nic->nmc_spidev = nmc_spi_dev;
+#else
+ nic->nmc_sdio_func= local_sdio_func;
+#endif
+
+ nic->iftype = STATION_MODE;
+
+
+ return 0;
+}
+
+#if defined(PLAT_AML8726_M3)
+ #include <mach/gpio.h>
+ #include <mach/gpio_data.h>
+ #include <mach/pinmux.h>
+ extern void sdio_reinit(void);
+ extern void extern_wifi_set_enable(int is_on);
+
+#elif defined(PLAT_ALLWINNER_A10)
+ extern void sunximmc_rescan_card(unsigned id, unsigned insert);
+ extern void mmc_pm_power(int mode, int* updown);
+ extern int mmc_pm_get_io_val(char* name);
+ extern int mmc_pm_gpio_ctrl(char* name, int level);
+ #define NMC1000_SDIO_CARD_ID 3
+ int nmc1000_power_val = 0;
+
+#elif defined(PLAT_ALLWINNER_A20)
+ extern void sw_mci_rescan_card(unsigned id, unsigned insert);
+ extern void wifi_pm_power(int on); // tony to keep allwinner's rule
+#define NMC1000_SDIO_CARD_ID 3
+
+#elif defined(PLAT_WM8880)
+ /*simulate virtual sdio card insert and removal*/
+ extern void force_remove_sdio2(void);
+ extern void wmt_detect_sdio2(void);
+
+#endif
+
+/*The 1st function called after module inserted*/
+static int __init init_nmc_driver(void){
+
+
+#if defined (NMC_DEBUGFS)
+ if(nmc_debugfs_init() < 0) {
+ NMI_PRINTF("fail to create debugfs for nmc driver\n");
+ return -1;
+ }
+#endif
+
+ printk("IN INIT FUNCTION\n");
+ printk("*** NMC1000 driver VERSION=[%s] REVISON=[%s] FW_VER=[%s] ***\n", NMC1000_DRIVER_VERSION, SVNREV, STA_FIRMWARE);
+
+#if defined(PLAT_AML8726_M3)
+ extern_wifi_set_enable(1);
+ sdio_reinit();
+
+#elif defined(PLAT_ALLWINNER_A10)
+ nmc1000_power_val = 1;
+ mmc_pm_power(0, &nmc1000_power_val); // POWER UP
+ sunximmc_rescan_card(NMC1000_SDIO_CARD_ID, 1);
+
+#elif defined(PLAT_ALLWINNER_A20)
+
+ wifi_pm_power(1);
+ sw_mci_rescan_card(NMC1000_SDIO_CARD_ID, 1);
+
+#elif defined(PLAT_WMS8304) // added by rachel
+ NmiWifiCardPower(0);
+ msleep(100);
+ NmiWifiCardPower(1);
+
+#elif defined(PLAT_WM8880)
+ NmiWifiCardPower(1);
+ wmt_detect_sdio2();
+#endif
+
+#ifdef NMI_SDIO
+ {
+ int ret;
+
+ ret = sdio_register_driver(&nmc_bus);
+ if (ret < 0) {
+ printk("init_nmc_driver: Failed register sdio driver\n");
+ }
+
+ return ret;
+ }
+#else
+ PRINT_D(INIT_DBG,"Initializing netdev\n");
+ if(nmc_netdev_init()){
+ PRINT_ER("Couldn't initialize netdev\n");
+ }
+
+ PRINT_D(INIT_DBG,"Device has been initialized successfully\n");
+ return 0;
+#endif
+}
+module_init(init_nmc_driver);
+
+static void __exit exit_nmc_driver(void){
+
+ #define CLOSE_TIMEOUT 12*1000
+
+ if((g_linux_wlan != NULL) &&g_linux_wlan->nmc_firmware != NULL) {
+ release_firmware(g_linux_wlan->nmc_firmware);
+ g_linux_wlan->nmc_firmware = NULL;
+ }
+
+ if( (g_linux_wlan != NULL) && ((g_linux_wlan->nmc_netdev) != NULL) )
+ {
+ PRINT_D(INIT_DBG,"Waiting for mac_close ....\n");
+
+ if(linux_wlan_lock_timeout(&close_exit_sync, CLOSE_TIMEOUT) < 0)
+ PRINT_D(INIT_DBG,"Closed TimedOUT\n");
+ else
+ PRINT_D(INIT_DBG,"mac_closed\n");
+
+ PRINT_D(INIT_DBG,"Unregistering netdev...\n");
+ unregister_netdev(g_linux_wlan->nmc_netdev);
+
+
+ #ifdef USE_WIRELESS
+ PRINT_D(INIT_DBG,"Freeing Wiphy...\n");
+ NMI_WFI_WiphyFree(g_linux_wlan->nmc_netdev);
+ #endif
+
+ PRINT_D(INIT_DBG,"Freeing netdev...\n");
+ free_netdev(g_linux_wlan->nmc_netdev);
+
+
+ }
+
+#ifdef USE_WIRELESS
+#ifdef NMI_AP_EXTERNAL_MLME
+ // Bug 4600 : NMI_WFI_deinit_mon_interface was already called at mac_close
+ //NMI_WFI_deinit_mon_interface();
+#endif
+#endif
+ if((&nmc_bus) != NULL)
+ {
+ #ifndef NMI_SDIO
+ PRINT_D(INIT_DBG,"SPI unregsiter...\n");
+ spi_unregister_driver(&nmc_bus);
+ #else
+ PRINT_D(INIT_DBG,"SDIO unregsiter...\n");
+ sdio_unregister_driver(&nmc_bus);
+ #endif
+ }
+
+ linux_wlan_deinit_lock(&close_exit_sync);
+ g_linux_wlan = NULL;
+ PRINT_D(INIT_DBG,"Module_exit Done.\n");
+#if defined (NMC_DEBUGFS)
+ nmc_debugfs_remove();
+#endif
+
+#if defined(PLAT_AML8726_M3)
+ extern_wifi_set_enable(0);
+
+#elif defined(PLAT_ALLWINNER_A10)
+ nmc1000_power_val = 0;
+ mmc_pm_power(0, &nmc1000_power_val); // POWER DOWN
+ sunximmc_rescan_card(NMC1000_SDIO_CARD_ID, 0);
+
+#elif defined(PLAT_ALLWINNER_A20)
+ wifi_pm_power(0);
+ sw_mci_rescan_card(NMC1000_SDIO_CARD_ID, 0);
+
+#elif defined(PLAT_WMS8304) // added by rachel
+ NmiWifiCardPower(0);
+
+#elif defined(PLAT_WM8880)
+ force_remove_sdio2();
+ NmiWifiCardPower(0); // simon
+#endif
+}
+module_exit(exit_nmc_driver);
+
+MODULE_LICENSE("GPL");
+#endif
diff --git a/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/linux_wlan_sdio.c b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/linux_wlan_sdio.c new file mode 100755 index 00000000..5eaf80ec --- /dev/null +++ b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/linux_wlan_sdio.c @@ -0,0 +1,252 @@ +#include "NMI_WFI_NetDevice.h"
+
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/host.h>
+
+
+
+#if defined (NM73131_0_BOARD)
+#define SDIO_MODALIAS "nmi_sdio"
+#else
+#define SDIO_MODALIAS "nmc1000_sdio"
+#endif
+
+#ifdef NMC_ASIC_A0
+#if defined (NM73131_0_BOARD)
+#define MAX_SPEED 50000000
+#elif defined (PLAT_ALLWINNER_A10)
+#define MAX_SPEED 50000000/*15000000*/
+#elif defined (PLAT_ALLWINNER_A20)
+#define MAX_SPEED 45000000 //40000000 //50000000
+#elif defined (PLAT_PANDA_ES_OMAP4460)
+#define MAX_SPEED 25000000 //johnny change
+#elif defined(PLAT_WM8880)
+#define MAX_SPEED 20000000
+#else
+#define MAX_SPEED 50000000
+#endif
+#else /* NMC_ASIC_A0 */
+/* Limit clk to 6MHz on FPGA. */
+#define MAX_SPEED 6000000
+#endif /* NMC_ASIC_A0 */
+
+
+struct sdio_func* local_sdio_func;
+extern linux_wlan_t* g_linux_wlan;
+extern int nmc_netdev_init(void);
+extern int sdio_clear_int(void);
+extern void nmi_handle_isr(void);
+
+static unsigned int sdio_default_speed=0;
+
+#define SDIO_VENDOR_ID_NMI 0x0296
+#define SDIO_DEVICE_ID_NMI 0x5347
+
+static const struct sdio_device_id nmi_sdio_ids[] = {
+ { SDIO_DEVICE(SDIO_VENDOR_ID_NMI,SDIO_DEVICE_ID_NMI) },
+};
+
+static void nmi_sdio_interrupt(struct sdio_func *func)
+{
+#ifndef NMI_SDIO_IRQ_GPIO
+ sdio_release_host(func);
+ nmi_handle_isr();
+ sdio_claim_host(func);
+#endif
+}
+
+
+int linux_sdio_cmd52(sdio_cmd52_t *cmd){
+ struct sdio_func *func = g_linux_wlan->nmc_sdio_func;
+ int ret;
+ u8 data;
+
+ sdio_claim_host(func);
+
+ func->num = cmd->function;
+ if (cmd->read_write) { /* write */
+ if (cmd->raw) {
+ sdio_writeb(func, cmd->data, cmd->address, &ret);
+ data = sdio_readb(func, cmd->address, &ret);
+ cmd->data = data;
+ } else {
+ sdio_writeb(func, cmd->data, cmd->address, &ret);
+ }
+ } else { /* read */
+ data = sdio_readb(func, cmd->address, &ret);
+ cmd->data = data;
+ }
+
+ sdio_release_host(func);
+
+ if (ret < 0) {
+ printk("nmi_sdio_cmd52..failed, err(%d)\n", ret);
+ return 0;
+ }
+ return 1;
+}
+
+
+ int linux_sdio_cmd53(sdio_cmd53_t *cmd){
+ struct sdio_func *func = g_linux_wlan->nmc_sdio_func;
+ int size, ret;
+
+ sdio_claim_host(func);
+
+ func->num = cmd->function;
+ func->cur_blksize = cmd->block_size;
+ if (cmd->block_mode)
+ size = cmd->count * cmd->block_size;
+ else
+ size = cmd->count;
+
+ if (cmd->read_write) { /* write */
+ ret = sdio_memcpy_toio(func, cmd->address, (void *)cmd->buffer, size);
+ } else { /* read */
+ ret = sdio_memcpy_fromio(func, (void *)cmd->buffer, cmd->address, size);
+ }
+
+ sdio_release_host(func);
+
+
+ if (ret < 0) {
+ printk("nmi_sdio_cmd53..failed, err(%d)\n", ret);
+ return 0;
+ }
+
+ return 1;
+}
+
+extern void set_wifi_name(char * name);
+static int linux_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id){
+ PRINT_D(INIT_DBG,"SDIO probe \n");
+ local_sdio_func = func;
+ PRINT_D(INIT_DBG,"Initializing netdev\n");
+ if(nmc_netdev_init()){
+ PRINT_ER("Couldn't initialize netdev\n");
+ return -1;
+ }
+ //added by rubbitxiao
+ set_wifi_name("nmc1000.ko");
+ return 0;
+}
+
+static void linux_sdio_remove(struct sdio_func *func)
+{
+ /**
+ TODO
+ **/
+
+}
+
+struct sdio_driver nmc_bus = {
+ .name = SDIO_MODALIAS,
+ .id_table = nmi_sdio_ids,
+ .probe = linux_sdio_probe,
+ .remove = linux_sdio_remove,
+};
+
+void enable_sdio_interrupt(void){
+ int ret;
+
+#ifndef NMI_SDIO_IRQ_GPIO
+ sdio_claim_host(local_sdio_func);
+ ret = sdio_claim_irq(local_sdio_func, nmi_sdio_interrupt);
+ sdio_release_host(local_sdio_func);
+
+ if (ret < 0) {
+ PRINT_ER("can't claim sdio_irq, err(%d)\n", ret);
+ }
+#endif
+}
+
+void disable_sdio_interrupt(void)
+{
+#ifndef NMI_SDIO_IRQ_GPIO
+ int ret;
+ sdio_claim_host(local_sdio_func);
+
+ ret = sdio_release_irq(local_sdio_func);
+
+ if (ret < 0) {
+ PRINT_ER("can't release sdio_irq, err(%d)\n", ret);
+ }
+ sdio_release_host(local_sdio_func);
+#endif
+}
+
+static int linux_sdio_set_speed(int speed)
+{
+#if defined(PLAT_AML8726_M3)
+// system down when clock speed is changed on amlogic platform
+ PRINT_ER("@@@@@@@@@@@@ Not change SDIO speed to %d @@@@@@@@@\n", speed);
+#else
+ struct mmc_ios ios;
+ sdio_claim_host(local_sdio_func);
+
+ memcpy((void *)&ios,(void *)&local_sdio_func->card->host->ios,sizeof(struct mmc_ios));
+ local_sdio_func->card->host->ios.clock = speed;
+ ios.clock = speed;
+ local_sdio_func->card->host->ops->set_ios(local_sdio_func->card->host,&ios);
+ sdio_release_host(local_sdio_func);
+ PRINT_ER("@@@@@@@@@@@@ change SDIO speed to %d @@@@@@@@@\n", speed);
+#endif
+ return 1;
+}
+
+static int linux_sdio_get_speed(void)
+{
+ return local_sdio_func->card->host->ios.clock;
+}
+
+int linux_sdio_init(void* pv){
+
+#if defined(PLAT_AML8726_M3)
+//[[ rachel - copy from v.3.0 (by johnny)
+ #ifdef NMC1000_SINGLE_TRANSFER
+ #define NMI_SDIO_BLOCK_SIZE 256
+ #else
+ #define NMI_SDIO_BLOCK_SIZE 512
+ #endif
+
+ int err;
+
+ sdio_claim_host(local_sdio_func);
+
+ printk("johnny linux_sdio_init %d\n", local_sdio_func->num );
+
+ local_sdio_func->num = 0;
+ sdio_set_block_size(local_sdio_func, NMI_SDIO_BLOCK_SIZE);
+
+ local_sdio_func->num = 1;
+ sdio_enable_func(local_sdio_func);
+ sdio_set_block_size(local_sdio_func, NMI_SDIO_BLOCK_SIZE);
+
+ sdio_release_host(local_sdio_func);
+
+ printk("johnny linux_sdio_init\n");
+#endif
+
+ sdio_default_speed = linux_sdio_get_speed();
+ return 1;
+}
+
+void linux_sdio_deinit(void *pv){
+ sdio_unregister_driver(&nmc_bus);
+}
+
+int linux_sdio_set_max_speed(void)
+{
+ return linux_sdio_set_speed(MAX_SPEED);
+}
+
+int linux_sdio_set_default_speed(void)
+{
+ return linux_sdio_set_speed(sdio_default_speed);
+}
+
+
+
diff --git a/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/linux_wlan_sdio.h b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/linux_wlan_sdio.h new file mode 100755 index 00000000..68b3da25 --- /dev/null +++ b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/linux_wlan_sdio.h @@ -0,0 +1,14 @@ +extern struct sdio_func *local_sdio_func;
+extern struct sdio_driver nmc_bus;
+
+#include <linux/mmc/sdio_func.h>
+
+int linux_sdio_init(void*);
+void linux_sdio_deinit(void*);
+int linux_sdio_cmd52(sdio_cmd52_t *cmd);
+int linux_sdio_cmd53(sdio_cmd53_t *cmd);
+void enable_sdio_interrupt(void);
+void disable_sdio_interrupt(void);
+int linux_sdio_set_max_speed(void);
+int linux_sdio_set_default_speed(void);
+
diff --git a/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/linux_wlan_spi.c b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/linux_wlan_spi.c new file mode 100755 index 00000000..47f1a668 --- /dev/null +++ b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/linux_wlan_spi.c @@ -0,0 +1,495 @@ +#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/cdev.h>
+#include <asm/uaccess.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+
+#include "linux_wlan_common.h"
+
+#define USE_SPI_DMA 0 //johnny add
+
+#ifdef NMC_ASIC_A0
+#if defined(PLAT_PANDA_ES_OMAP4460)
+#define MIN_SPEED 12000000
+#define MAX_SPEED 24000000
+#elif defined(PLAT_WMS8304)
+#define MIN_SPEED 12000000
+#define MAX_SPEED 24000000 //4000000
+#else
+#define MIN_SPEED 24000000
+#define MAX_SPEED 48000000
+#endif
+#else /* NMC_ASIC_A0 */
+/* Limit clk to 6MHz on FPGA. */
+#define MIN_SPEED 6000000
+#define MAX_SPEED 6000000
+#endif /* NMC_ASIC_A0 */
+
+static uint32_t SPEED = MIN_SPEED;
+
+struct spi_device* nmc_spi_dev;
+void linux_spi_deinit(void* vp);
+
+static int __init nmc_bus_probe(struct spi_device* spi){
+
+ PRINT_D(BUS_DBG,"spiModalias: %s\n",spi->modalias);
+ PRINT_D(BUS_DBG,"spiMax-Speed: %d\n",spi->max_speed_hz);
+ nmc_spi_dev = spi;
+
+ return 0;
+}
+
+static int __devexit nmc_bus_remove(struct spi_device* spi){
+
+ //linux_spi_deinit(NULL);
+
+ return 0;
+}
+
+
+struct spi_driver nmc_bus __refdata = {
+ .driver = {
+ .name = MODALIAS,
+ },
+ .probe = nmc_bus_probe,
+ .remove = __devexit_p(nmc_bus_remove),
+};
+
+
+void linux_spi_deinit(void* vp){
+
+ spi_unregister_driver(&nmc_bus);
+
+ SPEED = MIN_SPEED;
+ PRINT_ER("@@@@@@@@@@@@ restore SPI speed to %d @@@@@@@@@\n", SPEED);
+
+}
+
+
+
+int linux_spi_init(void* vp){
+ int ret = 1;
+ static int called = 0;
+
+
+ if(called == 0){
+ called++;
+ if(&nmc_bus == NULL){
+ PRINT_ER("nmc_bus address is NULL\n");
+ }
+ ret = spi_register_driver(&nmc_bus);
+ }
+
+ /* change return value to match NMI interface */
+ (ret<0)? (ret = 0):(ret = 1);
+
+ return ret;
+}
+
+#if defined(PLAT_WMS8304) // rachel
+#define TXRX_PHASE_SIZE (4096)
+#endif
+
+#if defined (NM73131_0_BOARD)
+
+int linux_spi_write(uint8_t* b, uint32_t len){
+
+ int ret;
+
+ if(len > 0 && b != NULL) {
+ struct spi_message msg;
+ PRINT_D(BUS_DBG,"Request writing %d bytes\n",len);
+ struct spi_transfer tr = {
+ .tx_buf = b,
+ .len = len,
+ .speed_hz = SPEED,
+ .delay_usecs = 0,
+ };
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&tr,&msg);
+ ret = spi_sync(nmc_spi_dev,&msg);
+ if(ret < 0){
+ PRINT_ER( "SPI transaction failed\n");
+ }
+
+ } else{
+ PRINT_ER("can't write data with the following length: %d\n",len);
+ PRINT_ER("FAILED due to NULL buffer or ZERO length check the following length: %d\n",len);
+ ret = -1;
+ }
+
+ /* change return value to match NMI interface */
+ (ret<0)? (ret = 0):(ret = 1);
+
+
+ return ret;
+}
+
+#elif defined(TXRX_PHASE_SIZE)
+
+int linux_spi_write(uint8_t* b, uint32_t len){
+ int ret;
+ if(len > 0 && b != NULL) {
+ int i = 0;
+ int blk = len/TXRX_PHASE_SIZE;
+ int remainder = len%TXRX_PHASE_SIZE;
+
+ //printk("[MMM] linux_spi_write in (t: %d), (blk:%d), (rem:%d), (%d)\n", len, blk, remainder, TXRX_PHASE_SIZE);
+
+ char *r_buffer = (char*) kzalloc(TXRX_PHASE_SIZE, GFP_KERNEL);
+ if(! r_buffer){
+ PRINT_ER("Failed to allocate memory for r_buffer\n");
+ }
+
+ if(blk)
+ {
+ while(i<blk)
+ {
+ struct spi_message msg;
+ struct spi_transfer tr = {
+ .tx_buf = b + (i*TXRX_PHASE_SIZE),
+ //.rx_buf = NULL,
+ .len = TXRX_PHASE_SIZE,
+ .speed_hz = SPEED,
+ .bits_per_word = 8,
+ .delay_usecs = 0,
+ };
+ /*
+ char *r_buffer = (char*) kzalloc(TXRX_PHASE_SIZE, GFP_KERNEL);
+ if(! r_buffer){
+ PRINT_ER("Failed to allocate memory for r_buffer\n");
+ }
+ */
+ tr.rx_buf = r_buffer;
+
+ memset(&msg, 0, sizeof(msg));
+ spi_message_init(&msg);
+ msg.spi = nmc_spi_dev;
+ msg.is_dma_mapped = USE_SPI_DMA; // rachel
+
+ spi_message_add_tail(&tr, &msg);
+ ret = spi_sync(nmc_spi_dev, &msg);
+ if(ret < 0) {
+ PRINT_ER( "SPI transaction failed\n");
+ }
+ //i += MJ_WRITE_SIZE;
+ i++;
+
+ }
+ }
+ if(remainder)
+ {
+ struct spi_message msg;
+ struct spi_transfer tr = {
+ .tx_buf = b + (blk*TXRX_PHASE_SIZE),
+ //.rx_buf = NULL,
+ .len = remainder,
+ .speed_hz = SPEED,
+ .bits_per_word = 8,
+ .delay_usecs = 0,
+ };
+ /*
+ char *r_buffer = (char*) kzalloc(remainder, GFP_KERNEL);
+ if(! r_buffer){
+ PRINT_ER("Failed to allocate memory for r_buffer\n");
+ }
+ */
+ tr.rx_buf = r_buffer;
+
+ memset(&msg, 0, sizeof(msg));
+ spi_message_init(&msg);
+ msg.spi = nmc_spi_dev;
+ msg.is_dma_mapped = USE_SPI_DMA; // rachel
+
+ spi_message_add_tail(&tr, &msg);
+ ret = spi_sync(nmc_spi_dev, &msg);
+ if(ret < 0) {
+ PRINT_ER( "SPI transaction failed\n");
+ }
+ }
+ if(r_buffer)
+ kfree(r_buffer);
+ } else {
+ PRINT_ER("can't write data with the following length: %d\n",len);
+ PRINT_ER("FAILED due to NULL buffer or ZERO length check the following length: %d\n",len);
+ ret = -1;
+ }
+
+ /* change return value to match NMI interface */
+ (ret<0)? (ret = 0):(ret = 1);
+
+ return ret;
+
+}
+
+#else
+int linux_spi_write(uint8_t* b, uint32_t len){
+
+ int ret;
+ struct spi_message msg;
+
+ if(len > 0 && b != NULL){
+ struct spi_transfer tr = {
+ .tx_buf = b,
+ //.rx_buf = r_buffer,
+ .len = len,
+ .speed_hz = SPEED,
+ .delay_usecs = 0,
+ };
+ char *r_buffer = (char*) kzalloc(len, GFP_KERNEL);
+ if(! r_buffer){
+ PRINT_ER("Failed to allocate memory for r_buffer\n");
+ }
+ tr.rx_buf = r_buffer;
+ PRINT_D(BUS_DBG,"Request writing %d bytes\n",len);
+
+ memset(&msg, 0, sizeof(msg));
+ spi_message_init(&msg);
+//[[johnny add
+ msg.spi = nmc_spi_dev;
+ msg.is_dma_mapped = USE_SPI_DMA; // rachel
+//]]
+ spi_message_add_tail(&tr,&msg);
+
+ ret = spi_sync(nmc_spi_dev,&msg);
+ if(ret < 0){
+ PRINT_ER( "SPI transaction failed\n");
+ }
+
+ kfree(r_buffer);
+ }else{
+ PRINT_ER("can't write data with the following length: %d\n",len);
+ PRINT_ER("FAILED due to NULL buffer or ZERO length check the following length: %d\n",len);
+ ret = -1;
+ }
+
+ /* change return value to match NMI interface */
+ (ret<0)? (ret = 0):(ret = 1);
+
+
+ return ret;
+}
+
+#endif
+
+#if defined (NM73131_0_BOARD)
+
+int linux_spi_read(unsigned char*rb, unsigned long rlen){
+
+ int ret;
+
+ if(rlen > 0) {
+ struct spi_message msg;
+ struct spi_transfer tr = {
+ .rx_buf = rb,
+ .len = rlen,
+ .speed_hz = SPEED,
+ .delay_usecs = 0,
+
+ };
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&tr,&msg);
+ ret = spi_sync(nmc_spi_dev,&msg);
+ if(ret < 0){
+ PRINT_ER("SPI transaction failed\n");
+ }
+ }else{
+ PRINT_ER("can't read data with the following length: %ld\n",rlen);
+ ret = -1;
+ }
+ /* change return value to match NMI interface */
+ (ret<0)? (ret = 0):(ret = 1);
+
+ return ret;
+}
+
+#elif defined(TXRX_PHASE_SIZE)
+
+int linux_spi_read(unsigned char*rb, unsigned long rlen){
+ int ret;
+ //printk("[MMM] linux_spi_read in, (%d)\n", rlen);
+
+ if(rlen > 0) {
+ int i =0;
+
+ int blk = rlen/TXRX_PHASE_SIZE;
+ int remainder = rlen%TXRX_PHASE_SIZE;
+
+ char *t_buffer = (char*) kzalloc(TXRX_PHASE_SIZE, GFP_KERNEL);
+ if(! t_buffer){
+ PRINT_ER("Failed to allocate memory for t_buffer\n");
+ }
+
+ //printk("[MMM] read size (%d), seperated (%d)\n", rlen, MJ_READ_SIZE);
+ //printk("[MMM] linux_spi_read in (t: %d), (blk:%d), (rem:%d), (%d)\n", rlen, blk, remainder, TXRX_PHASE_SIZE);
+
+ if(blk)
+ {
+ //printk(" read blk %d cnt\n", blk);
+ while(i<blk)
+ {
+ struct spi_message msg;
+ struct spi_transfer tr = {
+ //.tx_buf = NULL,
+ .rx_buf = rb + (i*TXRX_PHASE_SIZE),
+ .len = TXRX_PHASE_SIZE,
+ .speed_hz = SPEED,
+ .bits_per_word = 8,
+ .delay_usecs = 0,
+ };
+ tr.tx_buf = t_buffer;
+
+ memset(&msg, 0, sizeof(msg));
+ spi_message_init(&msg);
+ msg.spi = nmc_spi_dev;
+ msg.is_dma_mapped = USE_SPI_DMA; // rachel
+
+ spi_message_add_tail(&tr, &msg);
+ ret = spi_sync(nmc_spi_dev, &msg);
+ if(ret < 0) {
+ PRINT_ER( "SPI transaction failed\n");
+ }
+ i ++;
+ }
+ }
+ if(remainder)
+ {
+ struct spi_message msg;
+ struct spi_transfer tr = {
+ //.tx_buf = NULL,
+ .rx_buf = rb + (blk*TXRX_PHASE_SIZE),
+ .len = remainder,
+ .speed_hz = SPEED,
+ .bits_per_word = 8,
+ .delay_usecs = 0,
+ };
+ /*
+ char *t_buffer = (char*) kzalloc(remainder, GFP_KERNEL);
+ if(! t_buffer){
+ PRINT_ER("Failed to allocate memory for t_buffer\n");
+ }
+ */
+ tr.tx_buf = t_buffer;
+
+ //printk(" read remain, %d bytes\n", remainder);
+ memset(&msg, 0, sizeof(msg));
+ spi_message_init(&msg);
+ msg.spi = nmc_spi_dev;
+ msg.is_dma_mapped = USE_SPI_DMA; // rachel
+
+ spi_message_add_tail(&tr, &msg);
+ ret = spi_sync(nmc_spi_dev, &msg);
+ if(ret < 0) {
+ PRINT_ER( "SPI transaction failed\n");
+ }
+ }
+
+ if(t_buffer)
+ kfree(t_buffer);
+ }else {
+ PRINT_ER("can't read data with the following length: %ld\n",rlen);
+ ret = -1;
+ }
+ /* change return value to match NMI interface */
+ (ret<0)? (ret = 0):(ret = 1);
+
+ return ret;
+}
+
+#else
+int linux_spi_read(unsigned char*rb, unsigned long rlen){
+
+ int ret;
+
+ if(rlen > 0){
+ struct spi_message msg;
+ struct spi_transfer tr = {
+ // .tx_buf = t_buffer,
+ .rx_buf = rb,
+ .len = rlen,
+ .speed_hz = SPEED,
+ .delay_usecs = 0,
+
+ };
+ char *t_buffer = (char*) kzalloc(rlen, GFP_KERNEL);
+ if(! t_buffer){
+ PRINT_ER("Failed to allocate memory for t_buffer\n");
+ }
+ tr.tx_buf = t_buffer;
+
+ memset(&msg, 0, sizeof(msg));
+ spi_message_init(&msg);
+//[[ johnny add
+ msg.spi = nmc_spi_dev;
+ msg.is_dma_mapped = USE_SPI_DMA; // rachel
+//]]
+ spi_message_add_tail(&tr,&msg);
+
+ ret = spi_sync(nmc_spi_dev,&msg);
+ if(ret < 0){
+ PRINT_ER("SPI transaction failed\n");
+ }
+ kfree(t_buffer);
+ }else{
+ PRINT_ER("can't read data with the following length: %ld\n",rlen);
+ ret = -1;
+ }
+ /* change return value to match NMI interface */
+ (ret<0)? (ret = 0):(ret = 1);
+
+ return ret;
+}
+
+#endif
+
+int linux_spi_write_read(unsigned char*wb, unsigned char*rb, unsigned int rlen)
+{
+
+ int ret;
+
+ if(rlen > 0) {
+ struct spi_message msg;
+ struct spi_transfer tr = {
+ .rx_buf = rb,
+ .tx_buf = wb,
+ .len = rlen,
+ .speed_hz = SPEED,
+ .bits_per_word = 8,
+ .delay_usecs = 0,
+
+ };
+
+ memset(&msg, 0, sizeof(msg)); // rachel
+ spi_message_init(&msg);
+ msg.spi = nmc_spi_dev; // rachel
+ msg.is_dma_mapped = USE_SPI_DMA; // rachel for DMA
+
+ spi_message_add_tail(&tr,&msg);
+ ret = spi_sync(nmc_spi_dev,&msg);
+ if(ret < 0){
+ PRINT_ER("SPI transaction failed\n");
+ }
+ }else{
+ PRINT_ER("can't read data with the following length: %d\n",rlen);
+ ret = -1;
+ }
+ /* change return value to match NMI interface */
+ (ret<0)? (ret = 0):(ret = 1);
+
+ return ret;
+}
+
+int linux_spi_set_max_speed(void)
+{
+ SPEED = MAX_SPEED;
+
+ PRINT_ER("@@@@@@@@@@@@ change SPI speed to %d @@@@@@@@@\n", SPEED);
+ return 1;
+}
diff --git a/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/linux_wlan_spi.h b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/linux_wlan_spi.h new file mode 100755 index 00000000..6f5eb1ae --- /dev/null +++ b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/linux_wlan_spi.h @@ -0,0 +1,14 @@ +#ifndef LINUX_WLAN_SPI_H
+#define LINUX_WLAN_SPI_H
+
+#include <linux/spi/spi.h>
+extern struct spi_device* nmc_spi_dev;
+extern struct spi_driver nmc_bus;
+
+int linux_spi_init(void* vp);
+void linux_spi_deinit(void* vp);
+int linux_spi_write(uint8_t* b, uint32_t len);
+int linux_spi_read(uint8_t *rb, uint32_t rlen);
+int linux_spi_write_read(unsigned char*wb, unsigned char*rb, unsigned int rlen);
+int linux_spi_set_max_speed(void);
+#endif
diff --git a/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/nmi_debugfs.c b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/nmi_debugfs.c new file mode 100755 index 00000000..b11572f4 --- /dev/null +++ b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/nmi_debugfs.c @@ -0,0 +1,264 @@ +/*
+* NewportMedia WiFi chipset driver test tools - nmi-debug
+* Copyright (c) 2012 NewportMedia Inc.
+* Author: SSW <sswd@nmisemic.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+*/
+
+#if defined(NMC_DEBUGFS)
+#include <linux/module.h>
+#include <linux/debugfs.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+
+#include "nmi_queue.h"
+#include "nmi_wlan_if.h"
+
+
+static struct dentry *nmc_dir;
+
+/*
+--------------------------------------------------------------------------------
+*/
+
+// [[ linux_wlan_common.h
+#define DBG_REGION_ALL (GENERIC_DBG | HOSTAPD_DBG | HOSTINF_DBG | CORECONFIG_DBG | CFG80211_DBG | INT_DBG | TX_DBG | RX_DBG | LOCK_DBG | INIT_DBG | BUS_DBG | MEM_DBG)
+
+#define DBG_LEVEL_ALL (DEBUG | INFO | WRN | ERR)
+
+atomic_t REGION = ATOMIC_INIT(INIT_DBG | GENERIC_DBG | CFG80211_DBG);
+
+// [[ debug level: DEBUG, INFO, WRN, added by tony 2012-01-09
+atomic_t DEBUG_LEVEL = ATOMIC_INIT(DEBUG | ERR); // if DEBUG_LEVEL is zero, silent, if DEBUG_LEVEL is 0xFFFFFFFF, verbose
+// ]]
+
+// debug_kmsg
+queue g_dumpqueue = {NULL, };
+#define DUMP_QUEUE_MAX (8*1024)
+DECLARE_WAIT_QUEUE_HEAD(nmc_msgdump_waitqueue);
+
+
+/*
+--------------------------------------------------------------------------------
+*/
+static int nmc_debug_level_open(struct inode *inode, struct file *file)
+{
+ /*DEBUG_LEVEL = *((unsigned int *)inode->i_private);*/
+ printk("nmc_debug_level_open: current debug-level=%x\n", atomic_read(&DEBUG_LEVEL));
+ return 0;
+}
+
+static int nmc_debug_region_open(struct inode *inode, struct file *file)
+{
+ /*REGION = *((unsigned int *)inode->i_private);*/
+ printk("nmc_debug_region_open: current debug-region=%x\n", atomic_read(®ION));
+ return 0;
+}
+
+static int nmc_debug_dump_open(struct inode *inode, struct file *file)
+{
+ printk("nmc_debug_dump_open\n");
+ return 0;
+}
+
+static ssize_t nmc_debug_level_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
+{
+ if(copy_to_user(buf, (const void*)(&atomic_read(&DEBUG_LEVEL)), sizeof(unsigned int))) {
+ return -EFAULT;
+ }
+
+ return sizeof(unsigned int);
+}
+
+static ssize_t nmc_debug_level_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
+{
+ unsigned int flag = 0;
+
+ if(copy_from_user(&flag, buf, sizeof(unsigned int))) {
+ return -EFAULT;
+ }
+
+ if(flag > DBG_LEVEL_ALL) {
+ printk("%s, value (0x%08x) is out of range, stay previous flag (0x%08x)\n", __func__, flag, atomic_read(&DEBUG_LEVEL));
+ return -EFAULT;
+ }
+
+ atomic_set(&DEBUG_LEVEL, (int)flag);
+ printk("new debug-level is %x\n", atomic_read(&DEBUG_LEVEL));
+
+ return sizeof(unsigned int);
+}
+
+static ssize_t nmc_debug_region_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
+{
+ if(copy_to_user(buf, (const void*)(&atomic_read(®ION)), sizeof(unsigned int))) {
+ return -EFAULT;
+ }
+
+ return sizeof(unsigned int);
+}
+
+static ssize_t nmc_debug_region_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
+{
+ uint32_t flag = 0;
+
+ if(copy_from_user(&flag, buf, sizeof(unsigned int))) {
+ return -EFAULT;
+ }
+
+ if(flag > DBG_REGION_ALL) {
+ printk("%s, value (0x%08x) is out of range, stay previous flag (0x%08x)\n", __func__, flag, atomic_read(®ION));
+ return -EFAULT;
+ }
+
+ atomic_set(®ION, (int)flag);
+ printk("new debug-region is %x\n", atomic_read(®ION));
+
+ return sizeof(unsigned int);
+}
+
+void kmsgdump_write(char *fmt, ...)
+{
+ char buf[256] = {0,};
+ va_list args;
+ int len;
+
+ va_start(args, fmt);
+ len = vsprintf(buf, fmt, args);
+ va_end(args);
+
+ if((len>=256) || (len<0))
+ buf[256-1] = '\n';
+
+#if !defined (NM73131_0_BOARD)
+//#define LOG_TIME_STAMP //NM73131 is not support : rachel check required
+#endif
+
+#ifdef LOG_TIME_STAMP
+ {
+ char buf_t[30] = {0,};
+ unsigned long rem_nsec;
+ u64 ts = local_clock();
+
+ rem_nsec = do_div(ts, 1000000000);
+ sprintf(buf_t, "[%5lu.%06lu] ", (unsigned long)ts, rem_nsec / 1000);
+
+ queue_write(&g_dumpqueue, (void*)buf_t, strlen(buf_t));
+ }
+#endif
+
+ queue_write(&g_dumpqueue, (void*)buf, strlen(buf));
+ wake_up(&nmc_msgdump_waitqueue);
+
+}
+
+static ssize_t kmsgdump_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
+{
+ int read_size = 0;
+ int buf_size = queue_data_size(&g_dumpqueue);
+
+ if(buf_size > 0)
+ {
+ unsigned char *text = kmalloc(buf_size, GFP_KERNEL);
+ read_size = queue_read(&g_dumpqueue, (void*)text, (int)buf_size);
+ if(copy_to_user(buf, text, read_size)) {
+ kfree(text);
+ return -EFAULT;
+ }
+ kfree(text);
+ return read_size;
+ }
+ // return -EAGAIN;
+ return 0;
+}
+
+static unsigned int kmsgdump_poll(struct file *file, poll_table *wait)
+{
+ if(queue_data_size(&g_dumpqueue))
+ return POLLIN | POLLRDNORM;
+ poll_wait(file, &nmc_msgdump_waitqueue, wait);
+ if(queue_data_size(&g_dumpqueue))
+ return POLLIN | POLLRDNORM;
+ return 0;
+}
+
+
+/*
+--------------------------------------------------------------------------------
+*/
+
+#define FOPS(_open, _read, _write, _poll) { \
+ .owner = THIS_MODULE, \
+ .open = (_open), \
+ .read = (_read), \
+ .write = (_write), \
+ .poll = (_poll), \
+}
+
+struct nmc_debugfs_info_t {
+ const char *name;
+ int perm;
+ unsigned int data;
+ struct file_operations fops;
+};
+
+static struct nmc_debugfs_info_t debugfs_info[] = {
+ { "nmc_debug_level", 0666, (DEBUG | ERR), FOPS(nmc_debug_level_open, nmc_debug_level_read, nmc_debug_level_write,NULL), },
+ { "nmc_debug_region", 0666, (INIT_DBG | GENERIC_DBG | CFG80211_DBG), FOPS(nmc_debug_region_open, nmc_debug_region_read, nmc_debug_region_write, NULL), },
+ { "nmc_debug_dump", 0666, 0, FOPS(nmc_debug_dump_open, kmsgdump_read, NULL, kmsgdump_poll), },
+};
+
+int nmc_debugfs_init(void)
+{
+ int i;
+
+ struct dentry *debugfs_files;
+ struct nmc_debugfs_info_t *info;
+
+ nmc_dir = debugfs_create_dir("nmi_wifi", NULL);
+ if(nmc_dir == ERR_PTR(-ENODEV)) {
+ /* it's not error. the debugfs is just not being enabled. */
+ printk("ERR, kernel has built without debugfs support\n");
+ return 0;
+ }
+
+ if(!nmc_dir) {
+ printk("ERR, debugfs create dir\n");
+ return -1;
+ }
+
+ for(i=0; i<ARRAY_SIZE(debugfs_info) ; i++)
+ {
+ info = &debugfs_info[i];
+ printk("create the debugfs file, %s\n", info->name);
+ debugfs_files = debugfs_create_file(info->name,
+ info->perm,
+ nmc_dir,
+ &info->data,
+ &info->fops);
+
+ if(!debugfs_files) {
+ printk("fail to create the debugfs file, %s\n", info->name);
+ debugfs_remove_recursive(nmc_dir);
+ return -1;
+ }
+ }
+
+ queue_init(&g_dumpqueue, DUMP_QUEUE_MAX);
+
+ return 0;
+}
+
+void nmc_debugfs_remove(void)
+{
+ queue_deinit(&g_dumpqueue);
+
+ debugfs_remove_recursive(nmc_dir);
+}
+
+#endif
+
diff --git a/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/nmi_queue.c b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/nmi_queue.c new file mode 100755 index 00000000..3b46fb43 --- /dev/null +++ b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/nmi_queue.c @@ -0,0 +1,235 @@ +/* + Copyright (c) Newport Media Inc. All rights reserved. + Copyright (c) WRG Inc. All rights reserved. + + Use of this sample source code is subject to the terms of the Newport Media Inc. + license agreement under which you licensed this sample source code. If you did not + accept the terms of the license agreement, you are not authorized to use this + sample source code. For the terms of the license, please see the license agreement + between you and Newport Media Inc. + THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES. +*/ +/** + @file queue.c + @description generic QUEUE object with auto drop. + @author Austin Shin (austin.shin@wrg.co.kr) + @date 2009-02-17 +*/ + +//#include <stdio.h> +//#include <stdlib.h> +//#include <string.h> +//#include <android/log.h> //added + +#include "nmi_queue.h" + +#ifdef _MSC_VER +#define inline __inline +#endif + +#include <linux/spinlock.h> +#include <linux/slab.h> + +static spinlock_t g_lock; + +/* read write option */ +#define OPTION_PARTIAL_READ // enable partial read +//#define OPTION_PARTIAL_WRITE // enable partial write +#define OPTION_AUTO_DROP // force write with auto dropping. + + +/* debugging */ +#define ASSERT(x) +//#define ASSERT(x) (!(x)) ? assert(x); + +static inline int __align(int v, unsigned int n) +{ + return (v + (n-1)) & ~(n-1); +} + +int queue_init(queue* p, int len) +{ + ASSERT(p); + ASSERT(p->buffer); + ASSERT(len > 0); + + spin_lock_init(&g_lock); + + //p->buffer = malloc(len); + p->buffer = kmalloc(len, GFP_KERNEL); + + if ( p->buffer == NULL ) + { + return 0; + } + + p->size = len; + + queue_reset(p); + + return len; +} + +int queue_deinit(queue* p) +{ + if( p->buffer == NULL ) + return -1; + + queue_reset(p); + + kfree(p->buffer); p->buffer = NULL; + + return 0; +} + +int queue_reset(queue* p) +{ + ASSERT(p); + ASSERT(p->buffer); + ASSERT(p->size > 0); + + if(p->buffer == NULL) + return 0; + + spin_lock(&g_lock); + + memset(p->buffer, 0, p->size); + p->wr = 0; + p->rd = 0; + + spin_unlock(&g_lock); + + return 0; +} + +int queue_data_size(queue* p) +{ + ASSERT(p); + + if(p->wr >= p->rd) + return (p->wr - p->rd); + else + return (p->wr + (p->size - p->rd)); +} + +int queue_free_size(queue* p) +{ + ASSERT(p); + + return p->size - queue_data_size(p); +} + +int queue_drop(queue* p, int len) +{ + ASSERT(p); + ASSERT(len < p->size); + + if(p->rd + len < p->size) + { + p->rd += len; + } + else + { + p->rd = p->rd + len - p->size; + } + + return len; +} + +int queue_write(queue* p, void* data, int len) +{ + int freesize; + + ASSERT(p); + ASSERT(data); + ASSERT(len < p->size); + + if(p->buffer == NULL) + return 0; + + spin_lock(&g_lock); + + freesize = queue_free_size(p); + + if(len > freesize) + { +#if defined(OPTION_PARTIAL_WRITE) + len = freesize; +#elif defined(OPTION_AUTO_DROP) + queue_drop(p, __align(len - freesize, 1)+1); +#else + spin_unlock(&g_lock); + return 0; +#endif + } + + if(p->wr + len < p->size) + { + memcpy(p->buffer + p->wr, data, len); + p->wr += len; + } + else + { + int part1 = p->size - p->wr; + int part2 = len - part1; + + memcpy(p->buffer + p->wr, data, part1); + memcpy(p->buffer, (char*)(data) + part1, part2); + p->wr = part2; + + } + + spin_unlock(&g_lock); + + return len; +} + + +int queue_read(queue* p, void* data, int len) +{ + int datasize; + + ASSERT(p); + ASSERT(data); + ASSERT(len < p->size); + + if(p->buffer == NULL) + return 0; + + spin_lock(&g_lock); + + datasize = queue_data_size(p); + + if (len > datasize) + { + //printk("queue underrun\n"); +#if defined(OPTION_PARTIAL_READ) + len = datasize; +#else + spin_unlock(&g_lock); + + return 0; +#endif + } + + if(p->rd + len < p->size) + { + memcpy(data, p->buffer + p->rd, len); + p->rd += len; + } + else + { + int part1 = p->size - p->rd; + int part2 = len - part1; + + memcpy(data, p->buffer + p->rd, part1); + memcpy((char*)(data) + part1, p->buffer, part2); + p->rd = part2; + } + + spin_unlock(&g_lock); + + return len; +} + + diff --git a/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/nmi_queue.h b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/nmi_queue.h new file mode 100755 index 00000000..cdfc8fbe --- /dev/null +++ b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/nmi_queue.h @@ -0,0 +1,56 @@ +/* + Copyright (c) Newport Media Inc. All rights reserved. + Copyright (c) WRG Inc. All rights reserved. + + Use of this sample source code is subject to the terms of the Newport Media Inc. + license agreement under which you licensed this sample source code. If you did not + accept the terms of the license agreement, you are not authorized to use this + sample source code. For the terms of the license, please see the license agreement + between you and Newport Media Inc. + THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES. +*/ +/** + @file queue.h + @description generic QUEUE object with auto drop. + @author Austin Shin (austin.shin@wrg.co.kr) + @date 2009-02-17 +*/ + +#ifndef _QUEUE_H_ +#define _QUEUE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if 1 +#define QUE_BUFFER_MAX_SIZE ((188*16*5)+1) //(188*16*8)//(188*30*4)//8192 +#else +#define QUE_BUFFER_MAX_SIZE (188*30*8)//(188*30*4) +#endif + +typedef struct _queue +{ + char* buffer; // data buffer + int size; // buffer size + int rd, wr; // r/w offset. +} queue; + + +int queue_init(queue* p, int len); +int queue_deinit(queue* p); +int queue_reset(queue* p); +int queue_data_size(queue* p); +int queue_free_size(queue* p); +int queue_write(queue* p, void* data, int len); +int queue_read(queue* p, void* data, int len); +int queue_drop(queue* p, int len); + + +#ifdef __cplusplus +} +#endif + +#endif // _QUEUE_H_ + + diff --git a/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/nmi_wm8880_gpio.c b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/nmi_wm8880_gpio.c new file mode 100755 index 00000000..993d265b --- /dev/null +++ b/drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/nmi_wm8880_gpio.c @@ -0,0 +1,88 @@ +/* + +* $Id: nmi_custom_gpio.c, Exp $ +*/ +#include <linux/mmc/host.h> +#include <linux/gpio.h> +#include <linux/delay.h> + + +#include <mach/gpio_customize_ease.h> +#include <mach/hardware.h> +#include <mach/wmt_gpio.h> + +#include <linux/gpio.h> +#include <mach/wmt_iomux.h> + + +static int gpio_chipen_ctrl = -1; +static int gpio_reset_ctrl = -1; + + +static void wifi_gpio_reset(int high_or_low) +{ + printk("%s======hi= %d\n",__FUNCTION__,high_or_low); + + gpio_direction_output(gpio_reset_ctrl, high_or_low); +} + +static void wifi_card_init_gpios(void) +{ + int ret; + + gpio_chipen_ctrl = WMT_PIN_GP62_SUSGPIO1; // ??? simon + gpio_reset_ctrl = WMT_PIN_GP1_GPIO14; + + ret = gpio_request(gpio_chipen_ctrl, "nmc1000 chipen pin"); + if (ret < 0) { + printk("reques gpio:%x failed!!! for nmc1000\n", gpio_chipen_ctrl); + return ; + } else { + printk("request gpio:%d for nmc1000 success!!!\n", gpio_chipen_ctrl); + } + gpio_direction_output(gpio_chipen_ctrl, 0); + + ret = gpio_request(gpio_reset_ctrl, "nmc1000 reset pin"); + if (ret < 0) { + printk("reques gpio:%x failed!!! for nmc1000\n", gpio_reset_ctrl); + return ; + } else { + printk("request gpio:%d for nmc1000 success!!!\n", gpio_reset_ctrl); + } + gpio_direction_output(gpio_reset_ctrl, 0); +} + +static void wifi_card_release_gpios(void) +{ + gpio_free(gpio_chipen_ctrl); + gpio_free(gpio_reset_ctrl); +} + +static void wifi_card_chipen_gpios(int high_or_low) +{ + gpio_direction_output(gpio_chipen_ctrl, high_or_low); +} + +/* Customer function to control hw specific wlan gpios */ +void NmiWifiCardPower(int power) +{ + printk("%s, power=%d\n", __FUNCTION__, power); + + + if(power){ + wifi_card_init_gpios(); + wifi_gpio_reset(0); + wifi_card_chipen_gpios (power); + msleep(35); + wifi_gpio_reset(1); + msleep(20); + }else{ + wifi_gpio_reset(0); + msleep(10); + wifi_card_chipen_gpios (power); + msleep(10); + wifi_card_release_gpios(); + } +} + + |