From 871480933a1c28f8a9fed4c4d34d06c439a7a422 Mon Sep 17 00:00:00 2001 From: Srikant Patnaik Date: Sun, 11 Jan 2015 12:28:04 +0530 Subject: Moved, renamed, and deleted files The original directory structure was scattered and unorganized. Changes are basically to make it look like kernel structure. --- .../Nmc1000_Release6.2/src/driver/linux/Makefile | 153 ++ .../src/driver/linux/allwinner_run_eval.sh | 4 + .../src/driver/linux/ap_soft.conf | 30 + .../driver/linux/include/NMI_WFI_CfgOperations.h | 75 + .../src/driver/linux/include/NMI_WFI_NetDevice.h | 231 ++ .../src/driver/linux/init_deinit_test.sh | 51 + .../src/driver/linux/nmi_wfi_load | 10 + .../src/driver/linux/nmi_wfi_unload | 6 + .../src/driver/linux/panda_run_eval.sh | 6 + .../src/driver/linux/panda_run_fpga.sh | 4 + .../driver/linux/source/NMI_WFI_CfgOperations.c | 2673 ++++++++++++++++++++ .../src/driver/linux/source/NMI_WFI_NetDevice.c | 969 +++++++ .../src/driver/linux/source/linux_mon.c | 521 ++++ .../src/driver/linux/source/linux_wlan.c | 2357 +++++++++++++++++ .../src/driver/linux/source/linux_wlan_sdio.c | 252 ++ .../src/driver/linux/source/linux_wlan_sdio.h | 14 + .../src/driver/linux/source/linux_wlan_spi.c | 495 ++++ .../src/driver/linux/source/linux_wlan_spi.h | 14 + .../src/driver/linux/source/nmi_debugfs.c | 264 ++ .../src/driver/linux/source/nmi_queue.c | 235 ++ .../src/driver/linux/source/nmi_queue.h | 56 + .../src/driver/linux/source/nmi_wm8880_gpio.c | 88 + 22 files changed, 8508 insertions(+) create mode 100755 drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/Makefile create mode 100755 drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/allwinner_run_eval.sh create mode 100755 drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/ap_soft.conf create mode 100755 drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/include/NMI_WFI_CfgOperations.h create mode 100755 drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/include/NMI_WFI_NetDevice.h create mode 100755 drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/init_deinit_test.sh create mode 100755 drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/nmi_wfi_load create mode 100755 drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/nmi_wfi_unload create mode 100755 drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/panda_run_eval.sh create mode 100755 drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/panda_run_fpga.sh create mode 100755 drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/NMI_WFI_CfgOperations.c create mode 100755 drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/NMI_WFI_NetDevice.c create mode 100755 drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/linux_mon.c create mode 100755 drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/linux_wlan.c create mode 100755 drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/linux_wlan_sdio.c create mode 100755 drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/linux_wlan_sdio.h create mode 100755 drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/linux_wlan_spi.c create mode 100755 drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/linux_wlan_spi.h create mode 100755 drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/nmi_debugfs.c create mode 100755 drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/nmi_queue.c create mode 100755 drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/nmi_queue.h create mode 100755 drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux/source/nmi_wm8880_gpio.c (limited to 'drivers/net/wireless/nmi/Nmc1000_Release6.2/src/driver/linux') 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 +#include +#include +#include +#include /* printk() */ +#include /* kmalloc() */ +#include /* error codes */ +#include /* size_t */ +#include /* mark_bh */ +#include +#include +#include /* struct device, and other headers */ +#include /* eth_type_trans */ +#include /* struct iphdr */ +#include /* struct tcphdr */ +#include + +#include +#include + +#include +#include +#include +#include + + +#include +#include +#include "host_interface.h" + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,30) +#include +#else +#include // 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 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;in_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;ikey_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;ikey_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;ikey_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;ikey_len;i++) + PRINT_INFO(CFG80211_DBG, "Adding group key value[%d] = %x\n", i, params->key[i]); + for(i=0;iseq_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;ikey_len;i++) + PRINT_INFO(CFG80211_DBG, "Adding pairwise key value[%d] = %x\n", i, params->key[i]); + + for(i=0;iseq_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;ikey_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;inmi_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; iassoc_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 ; ilen; 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 ; isaddr; + 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;ihdr.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;ilen;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; ilen ; 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 +#include +#include +#include +#include +#include +#ifndef PLAT_ALLWINNER_A10 // tony +#include +#endif +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#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 // simon, rachel +#include +#include +#include +#include +#include + +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(inmc_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 + #include + #include + 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 +#include +#include +#include +#include + + + +#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 + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 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 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 +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 +* +* 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 +#include +#include +#include + +#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; iname); + 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 +//#include +//#include +//#include //added + +#include "nmi_queue.h" + +#ifdef _MSC_VER +#define inline __inline +#endif + +#include +#include + +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 +#include +#include + + +#include +#include +#include + +#include +#include + + +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(); + } +} + + -- cgit