| /******************************************************************************* |
| * Agere Systems Inc. |
| * Wireless device driver for Linux (wlags49). |
| * |
| * Copyright (c) 1998-2003 Agere Systems Inc. |
| * All rights reserved. |
| * http://www.agere.com |
| * |
| * Initially developed by TriplePoint, Inc. |
| * http://www.triplepoint.com |
| * |
| *------------------------------------------------------------------------------ |
| * |
| * This file contains the main driver entry points and other adapter |
| * specific routines. |
| * |
| *------------------------------------------------------------------------------ |
| * |
| * SOFTWARE LICENSE |
| * |
| * This software is provided subject to the following terms and conditions, |
| * which you should read carefully before using the software. Using this |
| * software indicates your acceptance of these terms and conditions. If you do |
| * not agree with these terms and conditions, do not use the software. |
| * |
| * Copyright © 2003 Agere Systems Inc. |
| * All rights reserved. |
| * |
| * Redistribution and use in source or binary forms, with or without |
| * modifications, are permitted provided that the following conditions are met: |
| * |
| * . Redistributions of source code must retain the above copyright notice, this |
| * list of conditions and the following Disclaimer as comments in the code as |
| * well as in the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * . Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following Disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * . Neither the name of Agere Systems Inc. nor the names of the contributors |
| * may be used to endorse or promote products derived from this software |
| * without specific prior written permission. |
| * |
| * Disclaimer |
| * |
| * THIS SOFTWARE IS PROVIDED AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, |
| * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY |
| * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN |
| * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY |
| * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT |
| * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
| * DAMAGE. |
| * |
| ******************************************************************************/ |
| |
| /******************************************************************************* |
| * constant definitions |
| ******************************************************************************/ |
| |
| /* Allow support for calling system fcns to access F/W iamge file */ |
| #define __KERNEL_SYSCALLS__ |
| |
| /******************************************************************************* |
| * include files |
| ******************************************************************************/ |
| #include <wl_version.h> |
| |
| #include <linux/module.h> |
| #include <linux/proc_fs.h> |
| #include <linux/types.h> |
| #include <linux/kernel.h> |
| // #include <linux/sched.h> |
| // #include <linux/ptrace.h> |
| // #include <linux/slab.h> |
| // #include <linux/ctype.h> |
| // #include <linux/string.h> |
| // #include <linux/timer.h> |
| //#include <linux/interrupt.h> |
| // #include <linux/tqueue.h> |
| // #include <linux/in.h> |
| // #include <linux/delay.h> |
| // #include <asm/io.h> |
| // #include <asm/system.h> |
| // #include <asm/bitops.h> |
| #include <linux/unistd.h> |
| #include <asm/uaccess.h> |
| |
| #include <linux/netdevice.h> |
| #include <linux/etherdevice.h> |
| // #include <linux/skbuff.h> |
| // #include <linux/if_arp.h> |
| // #include <linux/ioport.h> |
| |
| #define BIN_DL 0 |
| #if BIN_DL |
| #include <linux/vmalloc.h> |
| #endif // BIN_DL |
| |
| |
| #include <debug.h> |
| |
| #include <hcf.h> |
| #include <dhf.h> |
| //in order to get around:: wl_main.c:2229: `HREG_EV_RDMAD' undeclared (first use in this function) |
| #include <hcfdef.h> |
| |
| #include <wl_if.h> |
| #include <wl_internal.h> |
| #include <wl_util.h> |
| #include <wl_main.h> |
| #include <wl_netdev.h> |
| #include <wl_wext.h> |
| |
| #ifdef USE_PROFILE |
| #include <wl_profile.h> |
| #endif /* USE_PROFILE */ |
| |
| #ifdef BUS_PCMCIA |
| #include <wl_cs.h> |
| #endif /* BUS_PCMCIA */ |
| |
| #ifdef BUS_PCI |
| #include <wl_pci.h> |
| #endif /* BUS_PCI */ |
| /******************************************************************************* |
| * macro defintions |
| ******************************************************************************/ |
| #define VALID_PARAM(C) \ |
| { \ |
| if (!(C)) \ |
| { \ |
| printk(KERN_INFO "Wireless, parameter error: \"%s\"\n", #C); \ |
| goto failed; \ |
| } \ |
| } |
| /******************************************************************************* |
| * local functions |
| ******************************************************************************/ |
| void wl_isr_handler( unsigned long p ); |
| |
| #if 0 //SCULL_USE_PROC /* don't waste space if unused */ |
| //int scull_read_procmem(char *buf, char **start, off_t offset, int len, int unused); |
| int scull_read_procmem(char *buf, char **start, off_t offset, int len, int *eof, void *data ); |
| static int write_int(struct file *file, const char *buffer, unsigned long count, void *data); |
| static void proc_write(const char *name, write_proc_t *w, void *data); |
| |
| #endif /* SCULL_USE_PROC */ |
| |
| /******************************************************************************* |
| * module parameter definitions - set with 'insmod' |
| ******************************************************************************/ |
| static p_u16 irq_mask = 0xdeb8; // IRQ3,4,5,7,9,10,11,12,14,15 |
| static p_s8 irq_list[4] = { -1 }; |
| |
| #if 0 |
| MODULE_PARM(irq_mask, "h"); |
| MODULE_PARM_DESC(irq_mask, "IRQ mask [0xdeb8]"); |
| MODULE_PARM(irq_list, "1-4b"); |
| MODULE_PARM_DESC(irq_list, "IRQ list [<irq_mask>]"); |
| #endif |
| |
| static p_u8 PARM_AUTHENTICATION = PARM_DEFAULT_AUTHENTICATION; |
| static p_u16 PARM_AUTH_KEY_MGMT_SUITE = PARM_DEFAULT_AUTH_KEY_MGMT_SUITE; |
| static p_u16 PARM_BRSC_2GHZ = PARM_DEFAULT_BRSC_2GHZ; |
| static p_u16 PARM_BRSC_5GHZ = PARM_DEFAULT_BRSC_5GHZ; |
| static p_u16 PARM_COEXISTENCE = PARM_DEFAULT_COEXISTENCE; |
| static p_u16 PARM_CONNECTION_CONTROL = PARM_DEFAULT_CONNECTION_CONTROL; //;?rename and move |
| static p_char *PARM_CREATE_IBSS = PARM_DEFAULT_CREATE_IBSS_STR; |
| static p_char *PARM_DESIRED_SSID = PARM_DEFAULT_SSID; |
| static p_char *PARM_DOWNLOAD_FIRMWARE = ""; |
| static p_u16 PARM_ENABLE_ENCRYPTION = PARM_DEFAULT_ENABLE_ENCRYPTION; |
| static p_char *PARM_EXCLUDE_UNENCRYPTED = PARM_DEFAULT_EXCLUDE_UNENCRYPTED_STR; |
| static p_char *PARM_INTRA_BSS_RELAY = PARM_DEFAULT_INTRA_BSS_RELAY_STR; |
| static p_char *PARM_KEY1 = ""; |
| static p_char *PARM_KEY2 = ""; |
| static p_char *PARM_KEY3 = ""; |
| static p_char *PARM_KEY4 = ""; |
| static p_char *PARM_LOAD_BALANCING = PARM_DEFAULT_LOAD_BALANCING_STR; |
| static p_u16 PARM_MAX_SLEEP = PARM_DEFAULT_MAX_PM_SLEEP; |
| static p_char *PARM_MEDIUM_DISTRIBUTION = PARM_DEFAULT_MEDIUM_DISTRIBUTION_STR; |
| static p_char *PARM_MICROWAVE_ROBUSTNESS = PARM_DEFAULT_MICROWAVE_ROBUSTNESS_STR; |
| static p_char *PARM_MULTICAST_PM_BUFFERING = PARM_DEFAULT_MULTICAST_PM_BUFFERING_STR; |
| static p_u16 PARM_MULTICAST_RATE = PARM_DEFAULT_MULTICAST_RATE_2GHZ; |
| static p_char *PARM_MULTICAST_RX = PARM_DEFAULT_MULTICAST_RX_STR; |
| static p_u8 PARM_NETWORK_ADDR[ETH_ALEN] = PARM_DEFAULT_NETWORK_ADDR; |
| static p_u16 PARM_OWN_ATIM_WINDOW = PARM_DEFAULT_OWN_ATIM_WINDOW; |
| static p_u16 PARM_OWN_BEACON_INTERVAL = PARM_DEFAULT_OWN_BEACON_INTERVAL; |
| static p_u8 PARM_OWN_CHANNEL = PARM_DEFAULT_OWN_CHANNEL; |
| static p_u8 PARM_OWN_DTIM_PERIOD = PARM_DEFAULT_OWN_DTIM_PERIOD; |
| static p_char *PARM_OWN_NAME = PARM_DEFAULT_OWN_NAME; |
| static p_char *PARM_OWN_SSID = PARM_DEFAULT_SSID; |
| static p_u16 PARM_PM_ENABLED = WVLAN_PM_STATE_DISABLED; |
| static p_u16 PARM_PM_HOLDOVER_DURATION = PARM_DEFAULT_PM_HOLDOVER_DURATION; |
| static p_u8 PARM_PORT_TYPE = PARM_DEFAULT_PORT_TYPE; |
| static p_char *PARM_PROMISCUOUS_MODE = PARM_DEFAULT_PROMISCUOUS_MODE_STR; |
| static p_char *PARM_REJECT_ANY = PARM_DEFAULT_REJECT_ANY_STR; |
| #ifdef USE_WDS |
| static p_u16 PARM_RTS_THRESHOLD1 = PARM_DEFAULT_RTS_THRESHOLD; |
| static p_u16 PARM_RTS_THRESHOLD2 = PARM_DEFAULT_RTS_THRESHOLD; |
| static p_u16 PARM_RTS_THRESHOLD3 = PARM_DEFAULT_RTS_THRESHOLD; |
| static p_u16 PARM_RTS_THRESHOLD4 = PARM_DEFAULT_RTS_THRESHOLD; |
| static p_u16 PARM_RTS_THRESHOLD5 = PARM_DEFAULT_RTS_THRESHOLD; |
| static p_u16 PARM_RTS_THRESHOLD6 = PARM_DEFAULT_RTS_THRESHOLD; |
| #endif // USE_WDS |
| static p_u16 PARM_RTS_THRESHOLD = PARM_DEFAULT_RTS_THRESHOLD; |
| static p_u16 PARM_SRSC_2GHZ = PARM_DEFAULT_SRSC_2GHZ; |
| static p_u16 PARM_SRSC_5GHZ = PARM_DEFAULT_SRSC_5GHZ; |
| static p_u8 PARM_SYSTEM_SCALE = PARM_DEFAULT_SYSTEM_SCALE; |
| static p_u8 PARM_TX_KEY = PARM_DEFAULT_TX_KEY; |
| static p_u16 PARM_TX_POW_LEVEL = PARM_DEFAULT_TX_POW_LEVEL; |
| #ifdef USE_WDS |
| static p_u16 PARM_TX_RATE1 = PARM_DEFAULT_TX_RATE_2GHZ; |
| static p_u16 PARM_TX_RATE2 = PARM_DEFAULT_TX_RATE_2GHZ; |
| static p_u16 PARM_TX_RATE3 = PARM_DEFAULT_TX_RATE_2GHZ; |
| static p_u16 PARM_TX_RATE4 = PARM_DEFAULT_TX_RATE_2GHZ; |
| static p_u16 PARM_TX_RATE5 = PARM_DEFAULT_TX_RATE_2GHZ; |
| static p_u16 PARM_TX_RATE6 = PARM_DEFAULT_TX_RATE_2GHZ; |
| #endif // USE_WDS |
| static p_u16 PARM_TX_RATE = PARM_DEFAULT_TX_RATE_2GHZ; |
| #ifdef USE_WDS |
| static p_u8 PARM_WDS_ADDRESS1[ETH_ALEN] = PARM_DEFAULT_NETWORK_ADDR; |
| static p_u8 PARM_WDS_ADDRESS2[ETH_ALEN] = PARM_DEFAULT_NETWORK_ADDR; |
| static p_u8 PARM_WDS_ADDRESS3[ETH_ALEN] = PARM_DEFAULT_NETWORK_ADDR; |
| static p_u8 PARM_WDS_ADDRESS4[ETH_ALEN] = PARM_DEFAULT_NETWORK_ADDR; |
| static p_u8 PARM_WDS_ADDRESS5[ETH_ALEN] = PARM_DEFAULT_NETWORK_ADDR; |
| static p_u8 PARM_WDS_ADDRESS6[ETH_ALEN] = PARM_DEFAULT_NETWORK_ADDR; |
| #endif // USE_WDS |
| |
| |
| #if 0 |
| MODULE_PARM(PARM_DESIRED_SSID, "s"); |
| MODULE_PARM_DESC(PARM_DESIRED_SSID, "Network Name (<string>) [ANY]"); |
| MODULE_PARM(PARM_OWN_SSID, "s"); |
| MODULE_PARM_DESC(PARM_OWN_SSID, "Network Name (<string>) [ANY]"); |
| MODULE_PARM(PARM_OWN_CHANNEL, "b"); |
| MODULE_PARM_DESC(PARM_OWN_CHANNEL, "Channel (0 - 14) [0]"); |
| MODULE_PARM(PARM_SYSTEM_SCALE, "b"); |
| MODULE_PARM_DESC(PARM_SYSTEM_SCALE, "Distance Between APs (1 - 3) [1]"); |
| MODULE_PARM(PARM_TX_RATE, "b"); |
| MODULE_PARM_DESC(PARM_TX_RATE, "Transmit Rate Control"); |
| MODULE_PARM(PARM_RTS_THRESHOLD, "h"); |
| MODULE_PARM_DESC(PARM_RTS_THRESHOLD, "Medium Reservation (RTS/CTS Fragment Length) (256 - 2347) [2347]"); |
| MODULE_PARM(PARM_MICROWAVE_ROBUSTNESS, "s"); |
| MODULE_PARM_DESC(PARM_MICROWAVE_ROBUSTNESS, "Microwave Oven Robustness Enabled (<string> N or Y) [N]"); |
| MODULE_PARM(PARM_OWN_NAME, "s"); |
| MODULE_PARM_DESC(PARM_OWN_NAME, "Station Name (<string>) [Linux]"); |
| |
| MODULE_PARM(PARM_ENABLE_ENCRYPTION, "b"); |
| MODULE_PARM_DESC(PARM_ENABLE_ENCRYPTION, "Encryption Mode (0 - 7) [0]"); |
| |
| MODULE_PARM(PARM_KEY1, "s"); |
| MODULE_PARM_DESC(PARM_KEY1, "Data Encryption Key 1 (<string>) []"); |
| MODULE_PARM(PARM_KEY2, "s"); |
| MODULE_PARM_DESC(PARM_KEY2, "Data Encryption Key 2 (<string>) []"); |
| MODULE_PARM(PARM_KEY3, "s"); |
| MODULE_PARM_DESC(PARM_KEY3, "Data Encryption Key 3 (<string>) []"); |
| MODULE_PARM(PARM_KEY4, "s"); |
| MODULE_PARM_DESC(PARM_KEY4, "Data Encryption Key 4 (<string>) []"); |
| MODULE_PARM(PARM_TX_KEY, "b"); |
| MODULE_PARM_DESC(PARM_TX_KEY, "Transmit Key ID (1 - 4) [1]"); |
| MODULE_PARM(PARM_MULTICAST_RATE, "b"); |
| MODULE_PARM_DESC(PARM_MULTICAST_RATE, "Multicast Rate"); |
| MODULE_PARM(PARM_DOWNLOAD_FIRMWARE, "s"); |
| MODULE_PARM_DESC(PARM_DOWNLOAD_FIRMWARE, "filename of firmware image"); |
| |
| MODULE_PARM(PARM_AUTH_KEY_MGMT_SUITE, "b"); |
| MODULE_PARM_DESC(PARM_AUTH_KEY_MGMT_SUITE, "Authentication Key Management suite (0-4) [0]"); |
| |
| MODULE_PARM(PARM_LOAD_BALANCING, "s"); |
| MODULE_PARM_DESC(PARM_LOAD_BALANCING, "Load Balancing Enabled (<string> N or Y) [Y]"); |
| MODULE_PARM(PARM_MEDIUM_DISTRIBUTION, "s"); |
| MODULE_PARM_DESC(PARM_MEDIUM_DISTRIBUTION, "Medium Distribution Enabled (<string> N or Y) [Y]"); |
| MODULE_PARM(PARM_TX_POW_LEVEL, "b"); |
| MODULE_PARM_DESC(PARM_TX_POW_LEVEL, "Transmit Power (0 - 6) [3]"); |
| MODULE_PARM(PARM_SRSC_2GHZ, "b"); |
| MODULE_PARM_DESC(PARM_SRSC_2GHZ, "Supported Rate Set Control 2.4 GHz"); |
| MODULE_PARM(PARM_SRSC_5GHZ, "b"); |
| MODULE_PARM_DESC(PARM_SRSC_5GHZ, "Supported Rate Set Control 5.0 GHz"); |
| MODULE_PARM(PARM_BRSC_2GHZ, "b"); |
| MODULE_PARM_DESC(PARM_BRSC_2GHZ, "Basic Rate Set Control 2.4 GHz"); |
| MODULE_PARM(PARM_BRSC_5GHZ, "b"); |
| MODULE_PARM_DESC(PARM_BRSC_5GHZ, "Basic Rate Set Control 5.0 GHz"); |
| #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA |
| //;?seems reasonable that even an AP-only driver could afford this small additional footprint |
| MODULE_PARM(PARM_PM_ENABLED, "h"); |
| MODULE_PARM_DESC(PARM_PM_ENABLED, "Power Management State (0 - 2, 8001 - 8002) [0]"); |
| MODULE_PARM(PARM_PORT_TYPE, "b"); |
| MODULE_PARM_DESC(PARM_PORT_TYPE, "Port Type (1 - 3) [1]"); |
| //;?MODULE_PARM(PARM_CREATE_IBSS, "s"); |
| //;?MODULE_PARM_DESC(PARM_CREATE_IBSS, "Create IBSS (<string> N or Y) [N]"); |
| //;?MODULE_PARM(PARM_MULTICAST_RX, "s"); |
| //;?MODULE_PARM_DESC(PARM_MULTICAST_RX, "Multicast Receive Enable (<string> N or Y) [Y]"); |
| //;?MODULE_PARM(PARM_MAX_SLEEP, "h"); |
| //;?MODULE_PARM_DESC(PARM_MAX_SLEEP, "Maximum Power Management Sleep Duration (0 - 65535) [100]"); |
| //;?MODULE_PARM(PARM_NETWORK_ADDR, "6b"); |
| //;?MODULE_PARM_DESC(PARM_NETWORK_ADDR, "Hardware Ethernet Address ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [<factory value>]"); |
| //;?MODULE_PARM(PARM_AUTHENTICATION, "b"); |
| // |
| //tracker 12448 |
| //;?MODULE_PARM_DESC(PARM_AUTHENTICATION, "Authentication Type (0-2) [0] 0=Open 1=SharedKey 2=LEAP"); |
| //;?MODULE_PARM_DESC(authentication, "Authentication Type (1-2) [1] 1=Open 2=SharedKey"); |
| //tracker 12448 |
| // |
| //;?MODULE_PARM(PARM_OWN_ATIM_WINDOW, "b"); |
| //;?MODULE_PARM_DESC(PARM_OWN_ATIM_WINDOW, "ATIM Window time in TU for IBSS creation (0-100) [0]"); |
| //;?MODULE_PARM(PARM_PM_HOLDOVER_DURATION, "b"); |
| //;?MODULE_PARM_DESC(PARM_PM_HOLDOVER_DURATION, "Time station remains awake after MAC frame transfer when PM is on (0-65535) [100]"); |
| //;?MODULE_PARM(PARM_PROMISCUOUS_MODE, "s"); |
| //;?MODULE_PARM_DESC(PARM_PROMISCUOUS_MODE, "Promiscuous Mode Enable (<string> Y or N ) [N]" ); |
| //;? |
| MODULE_PARM(PARM_CONNECTION_CONTROL, "b"); |
| MODULE_PARM_DESC(PARM_CONNECTION_CONTROL, "Connection Control (0 - 3) [2]"); |
| #endif /* HCF_STA */ |
| #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP |
| //;?should we restore this to allow smaller memory footprint |
| MODULE_PARM(PARM_OWN_DTIM_PERIOD, "b"); |
| MODULE_PARM_DESC(PARM_OWN_DTIM_PERIOD, "DTIM Period (0 - 255) [1]"); |
| MODULE_PARM(PARM_REJECT_ANY, "s"); |
| MODULE_PARM_DESC(PARM_REJECT_ANY, "Closed System (<string> N or Y) [N]"); |
| MODULE_PARM(PARM_EXCLUDE_UNENCRYPTED, "s"); |
| MODULE_PARM_DESC(PARM_EXCLUDE_UNENCRYPTED, "Deny non-encrypted (<string> N or Y) [Y]"); |
| MODULE_PARM(PARM_MULTICAST_PM_BUFFERING,"s"); |
| MODULE_PARM_DESC(PARM_MULTICAST_PM_BUFFERING, "Buffer MAC frames for Tx after DTIM (<string> Y or N) [Y]"); |
| MODULE_PARM(PARM_INTRA_BSS_RELAY, "s"); |
| MODULE_PARM_DESC(PARM_INTRA_BSS_RELAY, "IntraBSS Relay (<string> N or Y) [Y]"); |
| MODULE_PARM(PARM_RTS_THRESHOLD1, "h"); |
| MODULE_PARM_DESC(PARM_RTS_THRESHOLD1, "RTS Threshold, WDS Port 1 (256 - 2347) [2347]"); |
| MODULE_PARM(PARM_RTS_THRESHOLD2, "h"); |
| MODULE_PARM_DESC(PARM_RTS_THRESHOLD2, "RTS Threshold, WDS Port 2 (256 - 2347) [2347]"); |
| MODULE_PARM(PARM_RTS_THRESHOLD3, "h"); |
| MODULE_PARM_DESC(PARM_RTS_THRESHOLD3, "RTS Threshold, WDS Port 3 (256 - 2347) [2347]"); |
| MODULE_PARM(PARM_RTS_THRESHOLD4, "h"); |
| MODULE_PARM_DESC(PARM_RTS_THRESHOLD4, "RTS Threshold, WDS Port 4 (256 - 2347) [2347]"); |
| MODULE_PARM(PARM_RTS_THRESHOLD5, "h"); |
| MODULE_PARM_DESC(PARM_RTS_THRESHOLD5, "RTS Threshold, WDS Port 5 (256 - 2347) [2347]"); |
| MODULE_PARM(PARM_RTS_THRESHOLD6, "h"); |
| MODULE_PARM_DESC(PARM_RTS_THRESHOLD6, "RTS Threshold, WDS Port 6 (256 - 2347) [2347]"); |
| MODULE_PARM(PARM_TX_RATE1, "b"); |
| MODULE_PARM_DESC(PARM_TX_RATE1, "Transmit Rate Control, WDS Port 1 (1 - 7) [3]"); |
| MODULE_PARM(PARM_TX_RATE2, "b"); |
| MODULE_PARM_DESC(PARM_TX_RATE2, "Transmit Rate Control, WDS Port 2 (1 - 7) [3]"); |
| MODULE_PARM(PARM_TX_RATE3, "b"); |
| MODULE_PARM_DESC(PARM_TX_RATE3, "Transmit Rate Control, WDS Port 3 (1 - 7) [3]"); |
| MODULE_PARM(PARM_TX_RATE4, "b"); |
| MODULE_PARM_DESC(PARM_TX_RATE4, "Transmit Rate Control, WDS Port 4 (1 - 7) [3]"); |
| MODULE_PARM(PARM_TX_RATE5, "b"); |
| MODULE_PARM_DESC(PARM_TX_RATE5, "Transmit Rate Control, WDS Port 5 (1 - 7) [3]"); |
| MODULE_PARM(PARM_TX_RATE6, "b"); |
| MODULE_PARM_DESC(PARM_TX_RATE6, "Transmit Rate Control, WDS Port 6 (1 - 7) [3]"); |
| MODULE_PARM(PARM_WDS_ADDRESS1, "6b"); |
| MODULE_PARM_DESC(PARM_WDS_ADDRESS1, "MAC Address, WDS Port 1 ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [{0}]"); |
| MODULE_PARM(PARM_WDS_ADDRESS2, "6b"); |
| MODULE_PARM_DESC(PARM_WDS_ADDRESS2, "MAC Address, WDS Port 2 ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [{0}]"); |
| MODULE_PARM(PARM_WDS_ADDRESS3, "6b"); |
| MODULE_PARM_DESC(PARM_WDS_ADDRESS3, "MAC Address, WDS Port 3 ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [{0}]"); |
| MODULE_PARM(PARM_WDS_ADDRESS4, "6b"); |
| MODULE_PARM_DESC(PARM_WDS_ADDRESS4, "MAC Address, WDS Port 4 ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [{0}]"); |
| MODULE_PARM(PARM_WDS_ADDRESS5, "6b"); |
| MODULE_PARM_DESC(PARM_WDS_ADDRESS5, "MAC Address, WDS Port 5 ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [{0}]"); |
| MODULE_PARM(PARM_WDS_ADDRESS6, "6b"); |
| MODULE_PARM_DESC(PARM_WDS_ADDRESS6, "MAC Address, WDS Port 6 ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [{0}]"); |
| |
| MODULE_PARM(PARM_OWN_BEACON_INTERVAL, "b"); |
| MODULE_PARM_DESC(PARM_OWN_BEACON_INTERVAL, "Own Beacon Interval (20 - 200) [100]"); |
| MODULE_PARM(PARM_COEXISTENCE, "b"); |
| MODULE_PARM_DESC(PARM_COEXISTENCE, "Coexistence (0-7) [0]"); |
| |
| #endif /* HCF_AP */ |
| #endif |
| |
| /* END NEW PARAMETERS */ |
| /******************************************************************************* |
| * debugging specifics |
| ******************************************************************************/ |
| #if DBG |
| |
| static p_u32 pc_debug = DBG_LVL; |
| //MODULE_PARM(pc_debug, "i"); |
| /*static ;?conflicts with my understanding of CL parameters and breaks now I moved |
| * the correspondig logic to wl_profile |
| */ p_u32 DebugFlag = ~0; //recognizable "undefined value" rather then DBG_DEFAULTS; |
| //MODULE_PARM(DebugFlag, "l"); |
| |
| dbg_info_t wl_info = { DBG_MOD_NAME, 0, 0 }; |
| dbg_info_t *DbgInfo = &wl_info; |
| |
| #endif /* DBG */ |
| #ifdef USE_RTS |
| |
| static p_char *useRTS = "N"; |
| MODULE_PARM( useRTS, "s" ); |
| MODULE_PARM_DESC( useRTS, "Use RTS test interface (<string> N or Y) [N]" ); |
| |
| #endif /* USE_RTS */ |
| /******************************************************************************* |
| * firmware download specifics |
| ******************************************************************************/ |
| extern struct CFG_RANGE2_STRCT BASED |
| cfg_drv_act_ranges_pri; // describes primary-actor range of HCF |
| |
| #if 0 //;? (HCF_TYPE) & HCF_TYPE_AP |
| extern memimage ap; // AP firmware image to be downloaded |
| #endif /* HCF_AP */ |
| |
| #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA |
| //extern memimage station; // STA firmware image to be downloaded |
| extern memimage fw_image; // firmware image to be downloaded |
| #endif /* HCF_STA */ |
| |
| |
| /******************************************************************************* |
| * wl_insert() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * wl_insert() is scheduled to run after a CARD_INSERTION event is |
| * received, to configure the PCMCIA socket, and to make the ethernet device |
| * available to the system. |
| * |
| * PARAMETERS: |
| * |
| * dev - a pointer to the net_device struct of the wireless device |
| * |
| * RETURNS: |
| * |
| * TRUE or FALSE |
| * |
| ******************************************************************************/ |
| int wl_insert( struct net_device *dev ) |
| { |
| int result = 0; |
| int hcf_status = HCF_SUCCESS; |
| int i; |
| unsigned long flags = 0; |
| struct wl_private *lp = wl_priv(dev); |
| /*------------------------------------------------------------------------*/ |
| DBG_FUNC( "wl_insert" ); |
| DBG_ENTER( DbgInfo ); |
| |
| /* Initialize the adapter hardware. */ |
| memset( &( lp->hcfCtx ), 0, sizeof( IFB_STRCT )); |
| |
| /* Initialize the adapter parameters. */ |
| spin_lock_init( &( lp->slock )); |
| |
| /* Intialize states */ |
| //lp->lockcount = 0; //PE1DNN |
| lp->is_handling_int = WL_NOT_HANDLING_INT; |
| lp->firmware_present = WL_FRIMWARE_NOT_PRESENT; |
| |
| lp->dev = dev; |
| |
| DBG_PARAM( DbgInfo, "irq_mask", "0x%04x", irq_mask & 0x0FFFF ); |
| DBG_PARAM( DbgInfo, "irq_list", "0x%02x 0x%02x 0x%02x 0x%02x", |
| irq_list[0] & 0x0FF, irq_list[1] & 0x0FF, |
| irq_list[2] & 0x0FF, irq_list[3] & 0x0FF ); |
| DBG_PARAM( DbgInfo, PARM_NAME_DESIRED_SSID, "\"%s\"", PARM_DESIRED_SSID ); |
| DBG_PARAM( DbgInfo, PARM_NAME_OWN_SSID, "\"%s\"", PARM_OWN_SSID ); |
| DBG_PARAM( DbgInfo, PARM_NAME_OWN_CHANNEL, "%d", PARM_OWN_CHANNEL); |
| DBG_PARAM( DbgInfo, PARM_NAME_SYSTEM_SCALE, "%d", PARM_SYSTEM_SCALE ); |
| DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE, "%d", PARM_TX_RATE ); |
| DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD, "%d", PARM_RTS_THRESHOLD ); |
| DBG_PARAM( DbgInfo, PARM_NAME_MICROWAVE_ROBUSTNESS, "\"%s\"", PARM_MICROWAVE_ROBUSTNESS ); |
| DBG_PARAM( DbgInfo, PARM_NAME_OWN_NAME, "\"%s\"", PARM_OWN_NAME ); |
| //;? DBG_PARAM( DbgInfo, PARM_NAME_ENABLE_ENCRYPTION, "\"%s\"", PARM_ENABLE_ENCRYPTION ); |
| DBG_PARAM( DbgInfo, PARM_NAME_KEY1, "\"%s\"", PARM_KEY1 ); |
| DBG_PARAM( DbgInfo, PARM_NAME_KEY2, "\"%s\"", PARM_KEY2 ); |
| DBG_PARAM( DbgInfo, PARM_NAME_KEY3, "\"%s\"", PARM_KEY3 ); |
| DBG_PARAM( DbgInfo, PARM_NAME_KEY4, "\"%s\"", PARM_KEY4 ); |
| DBG_PARAM( DbgInfo, PARM_NAME_TX_KEY, "%d", PARM_TX_KEY ); |
| DBG_PARAM( DbgInfo, PARM_NAME_MULTICAST_RATE, "%d", PARM_MULTICAST_RATE ); |
| DBG_PARAM( DbgInfo, PARM_NAME_DOWNLOAD_FIRMWARE, "\"%s\"", PARM_DOWNLOAD_FIRMWARE ); |
| DBG_PARAM( DbgInfo, PARM_NAME_AUTH_KEY_MGMT_SUITE, "%d", PARM_AUTH_KEY_MGMT_SUITE ); |
| //;?#if (HCF_TYPE) & HCF_TYPE_STA |
| //;?should we make this code conditional depending on in STA mode |
| //;? DBG_PARAM( DbgInfo, PARM_NAME_PORT_TYPE, "%d", PARM_PORT_TYPE ); |
| DBG_PARAM( DbgInfo, PARM_NAME_PM_ENABLED, "%04x", PARM_PM_ENABLED ); |
| //;? DBG_PARAM( DbgInfo, PARM_NAME_CREATE_IBSS, "\"%s\"", PARM_CREATE_IBSS ); |
| //;? DBG_PARAM( DbgInfo, PARM_NAME_MULTICAST_RX, "\"%s\"", PARM_MULTICAST_RX ); |
| //;? DBG_PARAM( DbgInfo, PARM_NAME_MAX_SLEEP, "%d", PARM_MAX_SLEEP ); |
| //;? DBG_PARAM( DbgInfo, PARM_NAME_NETWORK_ADDR, "\"%s\"", DbgHwAddr( PARM_NETWORK_ADDR )); |
| //;? DBG_PARAM( DbgInfo, PARM_NAME_AUTHENTICATION, "%d", PARM_AUTHENTICATION ); |
| //;? DBG_PARAM( DbgInfo, PARM_NAME_OWN_ATIM_WINDOW, "%d", PARM_OWN_ATIM_WINDOW ); |
| //;? DBG_PARAM( DbgInfo, PARM_NAME_PM_HOLDOVER_DURATION, "%d", PARM_PM_HOLDOVER_DURATION ); |
| //;? DBG_PARAM( DbgInfo, PARM_NAME_PROMISCUOUS_MODE, "\"%s\"", PARM_PROMISCUOUS_MODE ); |
| //;?#endif /* HCF_STA */ |
| #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP |
| //;?should we restore this to allow smaller memory footprint |
| //;?I guess: no, since this is Debug mode only |
| DBG_PARAM( DbgInfo, PARM_NAME_OWN_DTIM_PERIOD, "%d", PARM_OWN_DTIM_PERIOD ); |
| DBG_PARAM( DbgInfo, PARM_NAME_REJECT_ANY, "\"%s\"", PARM_REJECT_ANY ); |
| DBG_PARAM( DbgInfo, PARM_NAME_EXCLUDE_UNENCRYPTED, "\"%s\"", PARM_EXCLUDE_UNENCRYPTED ); |
| DBG_PARAM( DbgInfo, PARM_NAME_MULTICAST_PM_BUFFERING, "\"%s\"", PARM_MULTICAST_PM_BUFFERING ); |
| DBG_PARAM( DbgInfo, PARM_NAME_INTRA_BSS_RELAY, "\"%s\"", PARM_INTRA_BSS_RELAY ); |
| #ifdef USE_WDS |
| DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD1, "%d", PARM_RTS_THRESHOLD1 ); |
| DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD2, "%d", PARM_RTS_THRESHOLD2 ); |
| DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD3, "%d", PARM_RTS_THRESHOLD3 ); |
| DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD4, "%d", PARM_RTS_THRESHOLD4 ); |
| DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD5, "%d", PARM_RTS_THRESHOLD5 ); |
| DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD6, "%d", PARM_RTS_THRESHOLD6 ); |
| DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE1, "%d", PARM_TX_RATE1 ); |
| DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE2, "%d", PARM_TX_RATE2 ); |
| DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE3, "%d", PARM_TX_RATE3 ); |
| DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE4, "%d", PARM_TX_RATE4 ); |
| DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE5, "%d", PARM_TX_RATE5 ); |
| DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE6, "%d", PARM_TX_RATE6 ); |
| DBG_PARAM( DbgInfo, PARM_NAME_WDS_ADDRESS1, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS1 )); |
| DBG_PARAM( DbgInfo, PARM_NAME_WDS_ADDRESS2, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS2 )); |
| DBG_PARAM( DbgInfo, PARM_NAME_WDS_ADDRESS3, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS3 )); |
| DBG_PARAM( DbgInfo, PARM_NAME_WDS_ADDRESS4, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS4 )); |
| DBG_PARAM( DbgInfo, PARM_NAME_WDS_ADDRESS5, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS5 )); |
| DBG_PARAM( DbgInfo, PARM_NAME_WDS_ADDRESS6, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS6 )); |
| #endif /* USE_WDS */ |
| #endif /* HCF_AP */ |
| |
| VALID_PARAM( !PARM_DESIRED_SSID || ( strlen( PARM_DESIRED_SSID ) <= PARM_MAX_NAME_LEN )); |
| VALID_PARAM( !PARM_OWN_SSID || ( strlen( PARM_OWN_SSID ) <= PARM_MAX_NAME_LEN )); |
| VALID_PARAM(( PARM_OWN_CHANNEL <= PARM_MAX_OWN_CHANNEL )); |
| VALID_PARAM(( PARM_SYSTEM_SCALE >= PARM_MIN_SYSTEM_SCALE ) && ( PARM_SYSTEM_SCALE <= PARM_MAX_SYSTEM_SCALE )); |
| VALID_PARAM(( PARM_TX_RATE >= PARM_MIN_TX_RATE ) && ( PARM_TX_RATE <= PARM_MAX_TX_RATE )); |
| VALID_PARAM(( PARM_RTS_THRESHOLD <= PARM_MAX_RTS_THRESHOLD )); |
| VALID_PARAM( !PARM_MICROWAVE_ROBUSTNESS || strchr( "NnYy", PARM_MICROWAVE_ROBUSTNESS[0] ) != NULL ); |
| VALID_PARAM( !PARM_OWN_NAME || ( strlen( PARM_NAME_OWN_NAME ) <= PARM_MAX_NAME_LEN )); |
| VALID_PARAM(( PARM_ENABLE_ENCRYPTION <= PARM_MAX_ENABLE_ENCRYPTION )); |
| VALID_PARAM( is_valid_key_string( PARM_KEY1 )); |
| VALID_PARAM( is_valid_key_string( PARM_KEY2 )); |
| VALID_PARAM( is_valid_key_string( PARM_KEY3 )); |
| VALID_PARAM( is_valid_key_string( PARM_KEY4 )); |
| VALID_PARAM(( PARM_TX_KEY >= PARM_MIN_TX_KEY ) && ( PARM_TX_KEY <= PARM_MAX_TX_KEY )); |
| |
| VALID_PARAM(( PARM_MULTICAST_RATE >= PARM_MIN_MULTICAST_RATE ) && |
| ( PARM_MULTICAST_RATE <= PARM_MAX_MULTICAST_RATE )); |
| |
| VALID_PARAM( !PARM_DOWNLOAD_FIRMWARE || ( strlen( PARM_DOWNLOAD_FIRMWARE ) <= 255 /*;?*/ )); |
| VALID_PARAM(( PARM_AUTH_KEY_MGMT_SUITE < PARM_MAX_AUTH_KEY_MGMT_SUITE )); |
| |
| VALID_PARAM( !PARM_LOAD_BALANCING || strchr( "NnYy", PARM_LOAD_BALANCING[0] ) != NULL ); |
| VALID_PARAM( !PARM_MEDIUM_DISTRIBUTION || strchr( "NnYy", PARM_MEDIUM_DISTRIBUTION[0] ) != NULL ); |
| VALID_PARAM(( PARM_TX_POW_LEVEL <= PARM_MAX_TX_POW_LEVEL )); |
| |
| VALID_PARAM(( PARM_PORT_TYPE >= PARM_MIN_PORT_TYPE ) && ( PARM_PORT_TYPE <= PARM_MAX_PORT_TYPE )); |
| VALID_PARAM( PARM_PM_ENABLED <= WVLAN_PM_STATE_STANDARD || |
| ( PARM_PM_ENABLED & 0x7FFF ) <= WVLAN_PM_STATE_STANDARD ); |
| VALID_PARAM( !PARM_CREATE_IBSS || strchr( "NnYy", PARM_CREATE_IBSS[0] ) != NULL ); |
| VALID_PARAM( !PARM_MULTICAST_RX || strchr( "NnYy", PARM_MULTICAST_RX[0] ) != NULL ); |
| VALID_PARAM(( PARM_MAX_SLEEP <= PARM_MAX_MAX_PM_SLEEP )); |
| VALID_PARAM(( PARM_AUTHENTICATION <= PARM_MAX_AUTHENTICATION )); |
| VALID_PARAM(( PARM_OWN_ATIM_WINDOW <= PARM_MAX_OWN_ATIM_WINDOW )); |
| VALID_PARAM(( PARM_PM_HOLDOVER_DURATION <= PARM_MAX_PM_HOLDOVER_DURATION )); |
| VALID_PARAM( !PARM_PROMISCUOUS_MODE || strchr( "NnYy", PARM_PROMISCUOUS_MODE[0] ) != NULL ); |
| VALID_PARAM(( PARM_CONNECTION_CONTROL <= PARM_MAX_CONNECTION_CONTROL )); |
| |
| VALID_PARAM(( PARM_OWN_DTIM_PERIOD >= PARM_MIN_OWN_DTIM_PERIOD )); |
| VALID_PARAM( !PARM_REJECT_ANY || strchr( "NnYy", PARM_REJECT_ANY[0] ) != NULL ); |
| VALID_PARAM( !PARM_EXCLUDE_UNENCRYPTED || strchr( "NnYy", PARM_EXCLUDE_UNENCRYPTED[0] ) != NULL ); |
| VALID_PARAM( !PARM_MULTICAST_PM_BUFFERING || strchr( "NnYy", PARM_MULTICAST_PM_BUFFERING[0] ) != NULL ); |
| VALID_PARAM( !PARM_INTRA_BSS_RELAY || strchr( "NnYy", PARM_INTRA_BSS_RELAY[0] ) != NULL ); |
| #ifdef USE_WDS |
| VALID_PARAM(( PARM_RTS_THRESHOLD1 <= PARM_MAX_RTS_THRESHOLD )); |
| VALID_PARAM(( PARM_RTS_THRESHOLD2 <= PARM_MAX_RTS_THRESHOLD )); |
| VALID_PARAM(( PARM_RTS_THRESHOLD3 <= PARM_MAX_RTS_THRESHOLD )); |
| VALID_PARAM(( PARM_RTS_THRESHOLD4 <= PARM_MAX_RTS_THRESHOLD )); |
| VALID_PARAM(( PARM_RTS_THRESHOLD5 <= PARM_MAX_RTS_THRESHOLD )); |
| VALID_PARAM(( PARM_RTS_THRESHOLD6 <= PARM_MAX_RTS_THRESHOLD )); |
| VALID_PARAM(( PARM_TX_RATE1 >= PARM_MIN_TX_RATE ) && (PARM_TX_RATE1 <= PARM_MAX_TX_RATE )); |
| VALID_PARAM(( PARM_TX_RATE2 >= PARM_MIN_TX_RATE ) && (PARM_TX_RATE2 <= PARM_MAX_TX_RATE )); |
| VALID_PARAM(( PARM_TX_RATE3 >= PARM_MIN_TX_RATE ) && (PARM_TX_RATE3 <= PARM_MAX_TX_RATE )); |
| VALID_PARAM(( PARM_TX_RATE4 >= PARM_MIN_TX_RATE ) && (PARM_TX_RATE4 <= PARM_MAX_TX_RATE )); |
| VALID_PARAM(( PARM_TX_RATE5 >= PARM_MIN_TX_RATE ) && (PARM_TX_RATE5 <= PARM_MAX_TX_RATE )); |
| VALID_PARAM(( PARM_TX_RATE6 >= PARM_MIN_TX_RATE ) && (PARM_TX_RATE6 <= PARM_MAX_TX_RATE )); |
| #endif /* USE_WDS */ |
| |
| VALID_PARAM(( PARM_OWN_BEACON_INTERVAL >= PARM_MIN_OWN_BEACON_INTERVAL ) && ( PARM_OWN_BEACON_INTERVAL <= PARM_MAX_OWN_BEACON_INTERVAL )); |
| VALID_PARAM(( PARM_COEXISTENCE <= PARM_COEXISTENCE )); |
| |
| /* Set the driver parameters from the passed in parameters. */ |
| |
| /* THESE MODULE PARAMETERS ARE TO BE DEPRECATED IN FAVOR OF A NAMING CONVENTION |
| WHICH IS INLINE WITH THE FORTHCOMING WAVELAN API */ |
| |
| /* START NEW PARAMETERS */ |
| |
| lp->Channel = PARM_OWN_CHANNEL; |
| lp->DistanceBetweenAPs = PARM_SYSTEM_SCALE; |
| |
| /* Need to determine how to handle the new bands for 5GHz */ |
| lp->TxRateControl[0] = PARM_DEFAULT_TX_RATE_2GHZ; |
| lp->TxRateControl[1] = PARM_DEFAULT_TX_RATE_5GHZ; |
| |
| lp->RTSThreshold = PARM_RTS_THRESHOLD; |
| |
| /* Need to determine how to handle the new bands for 5GHz */ |
| lp->MulticastRate[0] = PARM_DEFAULT_MULTICAST_RATE_2GHZ; |
| lp->MulticastRate[1] = PARM_DEFAULT_MULTICAST_RATE_5GHZ; |
| |
| if ( strchr( "Yy", PARM_MICROWAVE_ROBUSTNESS[0] ) != NULL ) { |
| lp->MicrowaveRobustness = 1; |
| } else { |
| lp->MicrowaveRobustness = 0; |
| } |
| if ( PARM_DESIRED_SSID && ( strlen( PARM_DESIRED_SSID ) <= HCF_MAX_NAME_LEN )) { |
| strcpy( lp->NetworkName, PARM_DESIRED_SSID ); |
| } |
| if ( PARM_OWN_SSID && ( strlen( PARM_OWN_SSID ) <= HCF_MAX_NAME_LEN )) { |
| strcpy( lp->NetworkName, PARM_OWN_SSID ); |
| } |
| if ( PARM_OWN_NAME && ( strlen( PARM_OWN_NAME ) <= HCF_MAX_NAME_LEN )) { |
| strcpy( lp->StationName, PARM_OWN_NAME ); |
| } |
| lp->EnableEncryption = PARM_ENABLE_ENCRYPTION; |
| if ( PARM_KEY1 && ( strlen( PARM_KEY1 ) <= MAX_KEY_LEN )) { |
| strcpy( lp->Key1, PARM_KEY1 ); |
| } |
| if ( PARM_KEY2 && ( strlen( PARM_KEY2 ) <= MAX_KEY_LEN )) { |
| strcpy( lp->Key2, PARM_KEY2 ); |
| } |
| if ( PARM_KEY3 && ( strlen( PARM_KEY3 ) <= MAX_KEY_LEN )) { |
| strcpy( lp->Key3, PARM_KEY3 ); |
| } |
| if ( PARM_KEY4 && ( strlen( PARM_KEY4 ) <= MAX_KEY_LEN )) { |
| strcpy( lp->Key4, PARM_KEY4 ); |
| } |
| |
| lp->TransmitKeyID = PARM_TX_KEY; |
| |
| key_string2key( lp->Key1, &(lp->DefaultKeys.key[0] )); |
| key_string2key( lp->Key2, &(lp->DefaultKeys.key[1] )); |
| key_string2key( lp->Key3, &(lp->DefaultKeys.key[2] )); |
| key_string2key( lp->Key4, &(lp->DefaultKeys.key[3] )); |
| |
| lp->DownloadFirmware = 1 ; //;?to be upgraded PARM_DOWNLOAD_FIRMWARE; |
| lp->AuthKeyMgmtSuite = PARM_AUTH_KEY_MGMT_SUITE; |
| |
| if ( strchr( "Yy", PARM_LOAD_BALANCING[0] ) != NULL ) { |
| lp->loadBalancing = 1; |
| } else { |
| lp->loadBalancing = 0; |
| } |
| |
| if ( strchr( "Yy", PARM_MEDIUM_DISTRIBUTION[0] ) != NULL ) { |
| lp->mediumDistribution = 1; |
| } else { |
| lp->mediumDistribution = 0; |
| } |
| |
| lp->txPowLevel = PARM_TX_POW_LEVEL; |
| |
| lp->srsc[0] = PARM_SRSC_2GHZ; |
| lp->srsc[1] = PARM_SRSC_5GHZ; |
| lp->brsc[0] = PARM_BRSC_2GHZ; |
| lp->brsc[1] = PARM_BRSC_5GHZ; |
| #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA |
| //;?seems reasonable that even an AP-only driver could afford this small additional footprint |
| lp->PortType = PARM_PORT_TYPE; |
| lp->MaxSleepDuration = PARM_MAX_SLEEP; |
| lp->authentication = PARM_AUTHENTICATION; |
| lp->atimWindow = PARM_OWN_ATIM_WINDOW; |
| lp->holdoverDuration = PARM_PM_HOLDOVER_DURATION; |
| lp->PMEnabled = PARM_PM_ENABLED; //;? |
| if ( strchr( "Yy", PARM_CREATE_IBSS[0] ) != NULL ) { |
| lp->CreateIBSS = 1; |
| } else { |
| lp->CreateIBSS = 0; |
| } |
| if ( strchr( "Nn", PARM_MULTICAST_RX[0] ) != NULL ) { |
| lp->MulticastReceive = 0; |
| } else { |
| lp->MulticastReceive = 1; |
| } |
| if ( strchr( "Yy", PARM_PROMISCUOUS_MODE[0] ) != NULL ) { |
| lp->promiscuousMode = 1; |
| } else { |
| lp->promiscuousMode = 0; |
| } |
| for( i = 0; i < ETH_ALEN; i++ ) { |
| lp->MACAddress[i] = PARM_NETWORK_ADDR[i]; |
| } |
| |
| lp->connectionControl = PARM_CONNECTION_CONTROL; |
| |
| #endif /* HCF_STA */ |
| #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP |
| //;?should we restore this to allow smaller memory footprint |
| lp->DTIMPeriod = PARM_OWN_DTIM_PERIOD; |
| |
| if ( strchr( "Yy", PARM_REJECT_ANY[0] ) != NULL ) { |
| lp->RejectAny = 1; |
| } else { |
| lp->RejectAny = 0; |
| } |
| if ( strchr( "Nn", PARM_EXCLUDE_UNENCRYPTED[0] ) != NULL ) { |
| lp->ExcludeUnencrypted = 0; |
| } else { |
| lp->ExcludeUnencrypted = 1; |
| } |
| if ( strchr( "Yy", PARM_MULTICAST_PM_BUFFERING[0] ) != NULL ) { |
| lp->multicastPMBuffering = 1; |
| } else { |
| lp->multicastPMBuffering = 0; |
| } |
| if ( strchr( "Yy", PARM_INTRA_BSS_RELAY[0] ) != NULL ) { |
| lp->intraBSSRelay = 1; |
| } else { |
| lp->intraBSSRelay = 0; |
| } |
| |
| lp->ownBeaconInterval = PARM_OWN_BEACON_INTERVAL; |
| lp->coexistence = PARM_COEXISTENCE; |
| |
| #ifdef USE_WDS |
| lp->wds_port[0].rtsThreshold = PARM_RTS_THRESHOLD1; |
| lp->wds_port[1].rtsThreshold = PARM_RTS_THRESHOLD2; |
| lp->wds_port[2].rtsThreshold = PARM_RTS_THRESHOLD3; |
| lp->wds_port[3].rtsThreshold = PARM_RTS_THRESHOLD4; |
| lp->wds_port[4].rtsThreshold = PARM_RTS_THRESHOLD5; |
| lp->wds_port[5].rtsThreshold = PARM_RTS_THRESHOLD6; |
| lp->wds_port[0].txRateCntl = PARM_TX_RATE1; |
| lp->wds_port[1].txRateCntl = PARM_TX_RATE2; |
| lp->wds_port[2].txRateCntl = PARM_TX_RATE3; |
| lp->wds_port[3].txRateCntl = PARM_TX_RATE4; |
| lp->wds_port[4].txRateCntl = PARM_TX_RATE5; |
| lp->wds_port[5].txRateCntl = PARM_TX_RATE6; |
| |
| for( i = 0; i < ETH_ALEN; i++ ) { |
| lp->wds_port[0].wdsAddress[i] = PARM_WDS_ADDRESS1[i]; |
| } |
| for( i = 0; i < ETH_ALEN; i++ ) { |
| lp->wds_port[1].wdsAddress[i] = PARM_WDS_ADDRESS2[i]; |
| } |
| for( i = 0; i < ETH_ALEN; i++ ) { |
| lp->wds_port[2].wdsAddress[i] = PARM_WDS_ADDRESS3[i]; |
| } |
| for( i = 0; i < ETH_ALEN; i++ ) { |
| lp->wds_port[3].wdsAddress[i] = PARM_WDS_ADDRESS4[i]; |
| } |
| for( i = 0; i < ETH_ALEN; i++ ) { |
| lp->wds_port[4].wdsAddress[i] = PARM_WDS_ADDRESS5[i]; |
| } |
| for( i = 0; i < ETH_ALEN; i++ ) { |
| lp->wds_port[5].wdsAddress[i] = PARM_WDS_ADDRESS6[i]; |
| } |
| #endif /* USE_WDS */ |
| #endif /* HCF_AP */ |
| #ifdef USE_RTS |
| if ( strchr( "Yy", useRTS[0] ) != NULL ) { |
| lp->useRTS = 1; |
| } else { |
| lp->useRTS = 0; |
| } |
| #endif /* USE_RTS */ |
| |
| |
| /* END NEW PARAMETERS */ |
| |
| |
| wl_lock( lp, &flags ); |
| |
| /* Initialize the portState variable */ |
| lp->portState = WVLAN_PORT_STATE_DISABLED; |
| |
| /* Initialize the ScanResult struct */ |
| memset( &( lp->scan_results ), 0, sizeof( lp->scan_results )); |
| lp->scan_results.scan_complete = FALSE; |
| |
| /* Initialize the ProbeResult struct */ |
| memset( &( lp->probe_results ), 0, sizeof( lp->probe_results )); |
| lp->probe_results.scan_complete = FALSE; |
| lp->probe_num_aps = 0; |
| |
| |
| /* Initialize Tx queue stuff */ |
| memset( lp->txList, 0, sizeof( lp->txList )); |
| |
| INIT_LIST_HEAD( &( lp->txFree )); |
| |
| lp->txF.skb = NULL; |
| lp->txF.port = 0; |
| |
| |
| for( i = 0; i < DEFAULT_NUM_TX_FRAMES; i++ ) { |
| list_add_tail( &( lp->txList[i].node ), &( lp->txFree )); |
| } |
| |
| |
| for( i = 0; i < WVLAN_MAX_TX_QUEUES; i++ ) { |
| INIT_LIST_HEAD( &( lp->txQ[i] )); |
| } |
| |
| lp->netif_queue_on = TRUE; |
| lp->txQ_count = 0; |
| /* Initialize the use_dma element in the adapter structure. Not sure if |
| this should be a compile-time or run-time configurable. So for now, |
| implement as run-time and just define here */ |
| #ifdef WARP |
| #ifdef ENABLE_DMA |
| DBG_TRACE( DbgInfo, "HERMES 2.5 BUSMASTER DMA MODE\n" ); |
| lp->use_dma = 1; |
| #else |
| DBG_TRACE( DbgInfo, "HERMES 2.5 PORT I/O MODE\n" ); |
| lp->use_dma = 0; |
| #endif // ENABLE_DMA |
| #endif // WARP |
| |
| /* Register the ISR handler information here, so that it's not done |
| repeatedly in the ISR */ |
| tasklet_init(&lp->task, wl_isr_handler, (unsigned long)lp); |
| |
| /* Connect to the adapter */ |
| DBG_TRACE( DbgInfo, "Calling hcf_connect()...\n" ); |
| hcf_status = hcf_connect( &lp->hcfCtx, dev->base_addr ); |
| //HCF_ERR_INCOMP_FW is acceptable, because download must still take place |
| //HCF_ERR_INCOMP_PRI is not acceptable |
| if ( hcf_status != HCF_SUCCESS && hcf_status != HCF_ERR_INCOMP_FW ) { |
| DBG_ERROR( DbgInfo, "hcf_connect() failed, status: 0x%x\n", hcf_status ); |
| wl_unlock( lp, &flags ); |
| goto hcf_failed; |
| } |
| |
| //;?should set HCF_version and how about driver_stat |
| lp->driverInfo.IO_address = dev->base_addr; |
| lp->driverInfo.IO_range = HCF_NUM_IO_PORTS; //;?conditionally 0x40 or 0x80 seems better |
| lp->driverInfo.IRQ_number = dev->irq; |
| lp->driverInfo.card_stat = lp->hcfCtx.IFB_CardStat; |
| //;? what happened to frame_type |
| |
| /* Fill in the driver identity structure */ |
| lp->driverIdentity.len = ( sizeof( lp->driverIdentity ) / sizeof( hcf_16 )) - 1; |
| lp->driverIdentity.typ = CFG_DRV_IDENTITY; |
| lp->driverIdentity.comp_id = DRV_IDENTITY; |
| lp->driverIdentity.variant = DRV_VARIANT; |
| lp->driverIdentity.version_major = DRV_MAJOR_VERSION; |
| lp->driverIdentity.version_minor = DRV_MINOR_VERSION; |
| |
| |
| /* Start the card here - This needs to be done in order to get the |
| MAC address for the network layer */ |
| DBG_TRACE( DbgInfo, "Calling wvlan_go() to perform a card reset...\n" ); |
| hcf_status = wl_go( lp ); |
| |
| if ( hcf_status != HCF_SUCCESS ) { |
| DBG_ERROR( DbgInfo, "wl_go() failed\n" ); |
| wl_unlock( lp, &flags ); |
| goto hcf_failed; |
| } |
| |
| /* Certain RIDs must be set before enabling the ports */ |
| wl_put_ltv_init( lp ); |
| |
| #if 0 //;?why was this already commented out in wl_lkm_720 |
| /* Enable the ports */ |
| if ( wl_adapter_is_open( lp->dev )) { |
| /* Enable the ports */ |
| DBG_TRACE( DbgInfo, "Enabling Port 0\n" ); |
| hcf_status = wl_enable( lp ); |
| |
| if ( hcf_status != HCF_SUCCESS ) { |
| DBG_TRACE( DbgInfo, "Enable port 0 failed: 0x%x\n", hcf_status ); |
| } |
| |
| #if (HCF_TYPE) & HCF_TYPE_AP |
| DBG_TRACE( DbgInfo, "Enabling WDS Ports\n" ); |
| //wl_enable_wds_ports( lp ); |
| #endif /* (HCF_TYPE) & HCF_TYPE_AP */ |
| |
| } |
| #endif |
| |
| /* Fill out the MAC address information in the net_device struct */ |
| memcpy( lp->dev->dev_addr, lp->MACAddress, ETH_ALEN ); |
| dev->addr_len = ETH_ALEN; |
| |
| lp->is_registered = TRUE; |
| |
| #ifdef USE_PROFILE |
| /* Parse the config file for the sake of creating WDS ports if WDS is |
| configured there but not in the module options */ |
| parse_config( dev ); |
| #endif /* USE_PROFILE */ |
| |
| /* If we're going into AP Mode, register the "virtual" ethernet devices |
| needed for WDS */ |
| WL_WDS_NETDEV_REGISTER( lp ); |
| |
| /* Reset the DownloadFirmware variable in the private struct. If the |
| config file is not used, this will not matter; if it is used, it |
| will be reparsed in wl_open(). This is done because logic in wl_open |
| used to check if a firmware download is needed is broken by parsing |
| the file here; however, this parsing is needed to register WDS ports |
| in AP mode, if they are configured */ |
| lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //;?download_firmware; |
| |
| #ifdef USE_RTS |
| if ( lp->useRTS == 1 ) { |
| DBG_TRACE( DbgInfo, "ENTERING RTS MODE...\n" ); |
| wl_act_int_off( lp ); |
| lp->is_handling_int = WL_NOT_HANDLING_INT; // Not handling interrupts anymore |
| |
| wl_disable( lp ); |
| |
| hcf_connect( &lp->hcfCtx, HCF_DISCONNECT); |
| } |
| #endif /* USE_RTS */ |
| |
| wl_unlock( lp, &flags ); |
| |
| DBG_TRACE( DbgInfo, "%s: Wireless, io_addr %#03lx, irq %d, ""mac_address ", |
| dev->name, dev->base_addr, dev->irq ); |
| |
| for( i = 0; i < ETH_ALEN; i++ ) { |
| printk( "%02X%c", dev->dev_addr[i], (( i < ( ETH_ALEN-1 )) ? ':' : '\n' )); |
| } |
| |
| #if 0 //SCULL_USE_PROC /* don't waste space if unused */ |
| create_proc_read_entry( "wlags", 0, NULL, scull_read_procmem, dev ); |
| proc_mkdir("driver/wlags49", 0); |
| proc_write("driver/wlags49/wlags49_type", write_int, &lp->wlags49_type); |
| #endif /* SCULL_USE_PROC */ |
| |
| DBG_LEAVE( DbgInfo ); |
| return result; |
| |
| hcf_failed: |
| wl_hcf_error( dev, hcf_status ); |
| |
| failed: |
| |
| DBG_ERROR( DbgInfo, "wl_insert() FAILED\n" ); |
| |
| if ( lp->is_registered == TRUE ) { |
| lp->is_registered = FALSE; |
| } |
| |
| WL_WDS_NETDEV_DEREGISTER( lp ); |
| |
| result = -EFAULT; |
| |
| |
| DBG_LEAVE( DbgInfo ); |
| return result; |
| } // wl_insert |
| /*============================================================================*/ |
| |
| |
| /******************************************************************************* |
| * wl_reset() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Reset the adapter. |
| * |
| * PARAMETERS: |
| * |
| * dev - a pointer to the net_device struct of the wireless device |
| * |
| * RETURNS: |
| * |
| * an HCF status code |
| * |
| ******************************************************************************/ |
| int wl_reset(struct net_device *dev) |
| { |
| struct wl_private *lp = wl_priv(dev); |
| int hcf_status = HCF_SUCCESS; |
| /*------------------------------------------------------------------------*/ |
| DBG_FUNC( "wl_reset" ); |
| DBG_ENTER( DbgInfo ); |
| DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev ); |
| DBG_PARAM( DbgInfo, "dev->base_addr", "(%#03lx)", dev->base_addr ); |
| |
| /* |
| * The caller should already have a lock and |
| * disable the interrupts, we do not lock here, |
| * nor do we enable/disable interrupts! |
| */ |
| |
| DBG_TRACE( DbgInfo, "Device Base Address: %#03lx\n", dev->base_addr ); |
| if ( dev->base_addr ) { |
| /* Shutdown the adapter. */ |
| hcf_connect( &lp->hcfCtx, HCF_DISCONNECT ); |
| |
| /* Reset the driver information. */ |
| lp->txBytes = 0; |
| |
| /* Connect to the adapter. */ |
| hcf_status = hcf_connect( &lp->hcfCtx, dev->base_addr ); |
| if ( hcf_status != HCF_SUCCESS && hcf_status != HCF_ERR_INCOMP_FW ) { |
| DBG_ERROR( DbgInfo, "hcf_connect() failed, status: 0x%x\n", hcf_status ); |
| goto out; |
| } |
| |
| /* Check if firmware is present, if not change state */ |
| if ( hcf_status == HCF_ERR_INCOMP_FW ) { |
| lp->firmware_present = WL_FRIMWARE_NOT_PRESENT; |
| } |
| |
| /* Initialize the portState variable */ |
| lp->portState = WVLAN_PORT_STATE_DISABLED; |
| |
| /* Restart the adapter. */ |
| hcf_status = wl_go( lp ); |
| if ( hcf_status != HCF_SUCCESS ) { |
| DBG_ERROR( DbgInfo, "wl_go() failed, status: 0x%x\n", hcf_status ); |
| goto out; |
| } |
| |
| /* Certain RIDs must be set before enabling the ports */ |
| wl_put_ltv_init( lp ); |
| } else { |
| DBG_ERROR( DbgInfo, "Device Base Address INVALID!!!\n" ); |
| } |
| |
| out: |
| DBG_LEAVE( DbgInfo ); |
| return hcf_status; |
| } // wl_reset |
| /*============================================================================*/ |
| |
| |
| /******************************************************************************* |
| * wl_go() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Reset the adapter. |
| * |
| * PARAMETERS: |
| * |
| * dev - a pointer to the net_device struct of the wireless device |
| * |
| * RETURNS: |
| * |
| * an HCF status code |
| * |
| ******************************************************************************/ |
| int wl_go( struct wl_private *lp ) |
| { |
| int hcf_status = HCF_SUCCESS; |
| char *cp = NULL; //fw_image |
| int retries = 0; |
| /*------------------------------------------------------------------------*/ |
| DBG_FUNC( "wl_go" ); |
| DBG_ENTER( DbgInfo ); |
| |
| hcf_status = wl_disable( lp ); |
| if ( hcf_status != HCF_SUCCESS ) { |
| DBG_TRACE( DbgInfo, "Disable port 0 failed: 0x%x\n", hcf_status ); |
| |
| while (( hcf_status != HCF_SUCCESS ) && (retries < 10)) { |
| retries++; |
| hcf_status = wl_disable( lp ); |
| } |
| if ( hcf_status == HCF_SUCCESS ) { |
| DBG_TRACE( DbgInfo, "Disable port 0 succes : %d retries\n", retries ); |
| } else { |
| DBG_TRACE( DbgInfo, "Disable port 0 failed after: %d retries\n", retries ); |
| } |
| } |
| |
| #if 1 //;? (HCF_TYPE) & HCF_TYPE_AP |
| //DBG_TRACE( DbgInfo, "Disabling WDS Ports\n" ); |
| //wl_disable_wds_ports( lp ); |
| #endif /* (HCF_TYPE) & HCF_TYPE_AP */ |
| |
| //;?what was the purpose of this |
| // /* load the appropriate firmware image, depending on driver mode */ |
| // lp->ltvRecord.len = ( sizeof( CFG_RANGE20_STRCT ) / sizeof( hcf_16 )) - 1; |
| // lp->ltvRecord.typ = CFG_DRV_ACT_RANGES_PRI; |
| // hcf_get_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| #if BIN_DL |
| if ( strlen( lp->fw_image_filename ) ) { |
| mm_segment_t fs; |
| int file_desc; |
| int rc; |
| |
| DBG_TRACE( DbgInfo, "F/W image:%s:\n", lp->fw_image_filename ); |
| /* Obtain a user-space process context, storing the original context */ |
| fs = get_fs( ); |
| set_fs( get_ds( )); |
| file_desc = open( lp->fw_image_filename, O_RDONLY, 0 ); |
| if ( file_desc == -1 ) { |
| DBG_ERROR( DbgInfo, "No image file found\n" ); |
| } else { |
| DBG_TRACE( DbgInfo, "F/W image file found\n" ); |
| #define DHF_ALLOC_SIZE 96000 //just below 96K, let's hope it suffices for now and for the future |
| cp = (char*)vmalloc( DHF_ALLOC_SIZE ); |
| if ( cp == NULL ) { |
| DBG_ERROR( DbgInfo, "error in vmalloc\n" ); |
| } else { |
| rc = read( file_desc, cp, DHF_ALLOC_SIZE ); |
| if ( rc == DHF_ALLOC_SIZE ) { |
| DBG_ERROR( DbgInfo, "buffer too small, %d\n", DHF_ALLOC_SIZE ); |
| } else if ( rc > 0 ) { |
| DBG_TRACE( DbgInfo, "read O.K.: %d bytes %.12s\n", rc, cp ); |
| rc = read( file_desc, &cp[rc], 1 ); |
| if ( rc == 0 ) { //;/change to an until-loop at rc<=0 |
| DBG_TRACE( DbgInfo, "no more to read\n" ); |
| } |
| } |
| if ( rc != 0 ) { |
| DBG_ERROR( DbgInfo, "file not read in one swoop or other error"\ |
| ", give up, too complicated, rc = %0X\n", rc ); |
| DBG_ERROR( DbgInfo, "still have to change code to get a real download now !!!!!!!!\n" ); |
| } else { |
| DBG_TRACE( DbgInfo, "before dhf_download_binary\n" ); |
| hcf_status = dhf_download_binary( (memimage *)cp ); |
| DBG_TRACE( DbgInfo, "after dhf_download_binary, before dhf_download_fw\n" ); |
| //;?improve error flow/handling |
| hcf_status = dhf_download_fw( &lp->hcfCtx, (memimage *)cp ); |
| DBG_TRACE( DbgInfo, "after dhf_download_fw\n" ); |
| } |
| vfree( cp ); |
| } |
| close( file_desc ); |
| } |
| set_fs( fs ); /* Return to the original context */ |
| } |
| #endif // BIN_DL |
| |
| /* If firmware is present but the type is unknown then download anyway */ |
| if ( (lp->firmware_present == WL_FRIMWARE_PRESENT) |
| && |
| ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) != COMP_ID_FW_STA ) |
| && |
| ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) != COMP_ID_FW_AP ) ) { |
| /* Unknown type, download needed. */ |
| lp->firmware_present = WL_FRIMWARE_NOT_PRESENT; |
| } |
| |
| if(lp->firmware_present == WL_FRIMWARE_NOT_PRESENT) |
| { |
| if ( cp == NULL ) { |
| DBG_TRACE( DbgInfo, "Downloading STA firmware...\n" ); |
| // hcf_status = dhf_download_fw( &lp->hcfCtx, &station ); |
| hcf_status = dhf_download_fw( &lp->hcfCtx, &fw_image ); |
| } |
| if ( hcf_status != HCF_SUCCESS ) { |
| DBG_ERROR( DbgInfo, "Firmware Download failed\n" ); |
| DBG_LEAVE( DbgInfo ); |
| return hcf_status; |
| } |
| } |
| /* Report the FW versions */ |
| //;?obsolete, use the available IFB info:: wl_get_pri_records( lp ); |
| if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) { |
| DBG_TRACE( DbgInfo, "downloaded station F/W\n" ); |
| } else if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) { |
| DBG_TRACE( DbgInfo, "downloaded AP F/W\n" ); |
| } else { |
| DBG_ERROR( DbgInfo, "unknown F/W type\n" ); |
| } |
| |
| /* |
| * Downloaded, no need to repeat this next time, assume the |
| * contents stays in the card until it is powered off. Note we |
| * do not switch firmware on the fly, the firmware is fixed in |
| * the driver for now. |
| */ |
| lp->firmware_present = WL_FRIMWARE_PRESENT; |
| |
| DBG_TRACE( DbgInfo, "ComponentID:%04x variant:%04x major:%04x minor:%04x\n", |
| CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ), |
| CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.variant ), |
| CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.version_major ), |
| CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.version_minor )); |
| |
| /* now we wil get the MAC address of the card */ |
| lp->ltvRecord.len = 4; |
| if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) { |
| lp->ltvRecord.typ = CFG_NIC_MAC_ADDR; |
| } else |
| { |
| lp->ltvRecord.typ = CFG_CNF_OWN_MAC_ADDR; |
| } |
| hcf_status = hcf_get_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| if ( hcf_status != HCF_SUCCESS ) { |
| DBG_ERROR( DbgInfo, "Could not retrieve MAC address\n" ); |
| DBG_LEAVE( DbgInfo ); |
| return hcf_status; |
| } |
| memcpy( lp->MACAddress, &lp->ltvRecord.u.u8[0], ETH_ALEN ); |
| DBG_TRACE( DbgInfo, "Card MAC Address: %s\n", DbgHwAddr( lp->MACAddress )); |
| |
| /* Write out configuration to the device, enable, and reconnect. However, |
| only reconnect if in AP mode. For STA mode, need to wait for passive scan |
| completion before a connect can be issued */ |
| wl_put_ltv( lp ); |
| /* Enable the ports */ |
| hcf_status = wl_enable( lp ); |
| |
| if ( lp->DownloadFirmware == WVLAN_DRV_MODE_AP ) { |
| #ifdef USE_WDS |
| wl_enable_wds_ports( lp ); |
| #endif // USE_WDS |
| hcf_status = wl_connect( lp ); |
| } |
| DBG_LEAVE( DbgInfo ); |
| return hcf_status; |
| } // wl_go |
| /*============================================================================*/ |
| |
| |
| /******************************************************************************* |
| * wl_set_wep_keys() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Write TxKeyID and WEP keys to the adapter. This is separated from |
| * wl_apply() to allow dynamic WEP key updates through the wireless |
| * extensions. |
| * |
| * PARAMETERS: |
| * |
| * lp - a pointer to the wireless adapter's private structure |
| * |
| * RETURNS: |
| * |
| * N/A |
| * |
| ******************************************************************************/ |
| void wl_set_wep_keys( struct wl_private *lp ) |
| { |
| int count = 0; |
| /*------------------------------------------------------------------------*/ |
| DBG_FUNC( "wl_set_wep_keys" ); |
| DBG_ENTER( DbgInfo ); |
| DBG_PARAM( DbgInfo, "lp", "%s (0x%p)", lp->dev->name, lp ); |
| if ( lp->EnableEncryption ) { |
| /* NOTE: CFG_CNF_ENCRYPTION is set in wl_put_ltv() as it's a static |
| RID */ |
| |
| /* set TxKeyID */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_TX_KEY_ID; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE(lp->TransmitKeyID - 1); |
| |
| hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| DBG_TRACE( DbgInfo, "Key 1 len: %d\n", lp->DefaultKeys.key[0].len ); |
| DBG_TRACE( DbgInfo, "Key 2 len: %d\n", lp->DefaultKeys.key[1].len ); |
| DBG_TRACE( DbgInfo, "Key 3 len: %d\n", lp->DefaultKeys.key[2].len ); |
| DBG_TRACE( DbgInfo, "Key 4 len: %d\n", lp->DefaultKeys.key[3].len ); |
| |
| /* write keys */ |
| lp->DefaultKeys.len = sizeof( lp->DefaultKeys ) / sizeof( hcf_16 ) - 1; |
| lp->DefaultKeys.typ = CFG_DEFAULT_KEYS; |
| |
| /* endian translate the appropriate key information */ |
| for( count = 0; count < MAX_KEYS; count++ ) { |
| lp->DefaultKeys.key[count].len = CNV_INT_TO_LITTLE( lp->DefaultKeys.key[count].len ); |
| } |
| |
| hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->DefaultKeys )); |
| |
| /* Reverse the above endian translation, since these keys are accessed |
| elsewhere */ |
| for( count = 0; count < MAX_KEYS; count++ ) { |
| lp->DefaultKeys.key[count].len = CNV_INT_TO_LITTLE( lp->DefaultKeys.key[count].len ); |
| } |
| |
| DBG_NOTICE( DbgInfo, "encrypt: %d, ID: %d\n", lp->EnableEncryption, lp->TransmitKeyID ); |
| DBG_NOTICE( DbgInfo, "set key: %s(%d) [%d]\n", lp->DefaultKeys.key[lp->TransmitKeyID-1].key, lp->DefaultKeys.key[lp->TransmitKeyID-1].len, lp->TransmitKeyID-1 ); |
| } |
| |
| DBG_LEAVE( DbgInfo ); |
| } // wl_set_wep_keys |
| /*============================================================================*/ |
| |
| |
| /******************************************************************************* |
| * wl_apply() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Write the parameters to the adapter. (re-)enables the card if device is |
| * open. Returns hcf_status of hcf_enable(). |
| * |
| * PARAMETERS: |
| * |
| * lp - a pointer to the wireless adapter's private structure |
| * |
| * RETURNS: |
| * |
| * an HCF status code |
| * |
| ******************************************************************************/ |
| int wl_apply(struct wl_private *lp) |
| { |
| int hcf_status = HCF_SUCCESS; |
| /*------------------------------------------------------------------------*/ |
| DBG_FUNC( "wl_apply" ); |
| DBG_ENTER( DbgInfo ); |
| DBG_ASSERT( lp != NULL); |
| DBG_PARAM( DbgInfo, "lp", "%s (0x%p)", lp->dev->name, lp ); |
| |
| if ( !( lp->flags & WVLAN2_UIL_BUSY )) { |
| /* The adapter parameters have changed: |
| disable card |
| reload parameters |
| enable card |
| */ |
| |
| if ( wl_adapter_is_open( lp->dev )) { |
| /* Disconnect and disable if necessary */ |
| hcf_status = wl_disconnect( lp ); |
| if ( hcf_status != HCF_SUCCESS ) { |
| DBG_ERROR( DbgInfo, "Disconnect failed\n" ); |
| DBG_LEAVE( DbgInfo ); |
| return -1; |
| } |
| hcf_status = wl_disable( lp ); |
| if ( hcf_status != HCF_SUCCESS ) { |
| DBG_ERROR( DbgInfo, "Disable failed\n" ); |
| DBG_LEAVE( DbgInfo ); |
| return -1; |
| } else { |
| /* Write out configuration to the device, enable, and reconnect. |
| However, only reconnect if in AP mode. For STA mode, need to |
| wait for passive scan completion before a connect can be |
| issued */ |
| hcf_status = wl_put_ltv( lp ); |
| |
| if ( hcf_status == HCF_SUCCESS ) { |
| hcf_status = wl_enable( lp ); |
| |
| if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) { |
| hcf_status = wl_connect( lp ); |
| } |
| } else { |
| DBG_WARNING( DbgInfo, "wl_put_ltv() failed\n" ); |
| } |
| } |
| } |
| } |
| |
| DBG_LEAVE( DbgInfo ); |
| return hcf_status; |
| } // wl_apply |
| /*============================================================================*/ |
| |
| |
| /******************************************************************************* |
| * wl_put_ltv_init() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Used to set basic parameters for card initialization. |
| * |
| * PARAMETERS: |
| * |
| * lp - a pointer to the wireless adapter's private structure |
| * |
| * RETURNS: |
| * |
| * an HCF status code |
| * |
| ******************************************************************************/ |
| int wl_put_ltv_init( struct wl_private *lp ) |
| { |
| int i; |
| int hcf_status; |
| CFG_RID_LOG_STRCT *RidLog; |
| /*------------------------------------------------------------------------*/ |
| DBG_FUNC( "wl_put_ltv_init" ); |
| DBG_ENTER( DbgInfo ); |
| if ( lp == NULL ) { |
| DBG_ERROR( DbgInfo, "lp pointer is NULL\n" ); |
| DBG_LEAVE( DbgInfo ); |
| return -1; |
| } |
| /* DMA/IO */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_CNTL_OPT; |
| |
| /* The Card Services build must ALWAYS configure for 16-bit I/O. PCI or |
| CardBus can be set to either 16/32 bit I/O, or Bus Master DMA, but only |
| for Hermes-2.5 */ |
| #ifdef BUS_PCMCIA |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( USE_16BIT ); |
| #else |
| if ( lp->use_dma ) { |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( USE_DMA ); |
| } else { |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 ); |
| } |
| |
| #endif |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| DBG_TRACE( DbgInfo, "CFG_CNTL_OPT : 0x%04x\n", |
| lp->ltvRecord.u.u16[0] ); |
| DBG_TRACE( DbgInfo, "CFG_CNTL_OPT result : 0x%04x\n", |
| hcf_status ); |
| |
| /* Register the list of RIDs on which asynchronous notification is |
| required. Note that this mechanism replaces the mailbox, so the mailbox |
| can be queried by the host (if desired) without contention from us */ |
| i=0; |
| |
| lp->RidList[i].len = sizeof( lp->ProbeResp ); |
| lp->RidList[i].typ = CFG_ACS_SCAN; |
| lp->RidList[i].bufp = (wci_recordp)&lp->ProbeResp; |
| //lp->ProbeResp.infoType = 0xFFFF; |
| i++; |
| |
| lp->RidList[i].len = sizeof( lp->assoc_stat ); |
| lp->RidList[i].typ = CFG_ASSOC_STAT; |
| lp->RidList[i].bufp = (wci_recordp)&lp->assoc_stat; |
| lp->assoc_stat.len = 0xFFFF; |
| i++; |
| |
| lp->RidList[i].len = 4; |
| lp->RidList[i].typ = CFG_UPDATED_INFO_RECORD; |
| lp->RidList[i].bufp = (wci_recordp)&lp->updatedRecord; |
| lp->updatedRecord.len = 0xFFFF; |
| i++; |
| |
| lp->RidList[i].len = sizeof( lp->sec_stat ); |
| lp->RidList[i].typ = CFG_SECURITY_STAT; |
| lp->RidList[i].bufp = (wci_recordp)&lp->sec_stat; |
| lp->sec_stat.len = 0xFFFF; |
| i++; |
| |
| lp->RidList[i].typ = 0; // Terminate List |
| |
| RidLog = (CFG_RID_LOG_STRCT *)&lp->ltvRecord; |
| RidLog->len = 3; |
| RidLog->typ = CFG_REG_INFO_LOG; |
| RidLog->recordp = (RID_LOGP)&lp->RidList[0]; |
| |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| DBG_TRACE( DbgInfo, "CFG_REG_INFO_LOG\n" ); |
| DBG_TRACE( DbgInfo, "CFG_REG_INFO_LOG result : 0x%04x\n", |
| hcf_status ); |
| DBG_LEAVE( DbgInfo ); |
| return hcf_status; |
| } // wl_put_ltv_init |
| /*============================================================================*/ |
| |
| |
| /******************************************************************************* |
| * wl_put_ltv() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Used by wvlan_apply() and wvlan_go to set the card's configuration. |
| * |
| * PARAMETERS: |
| * |
| * lp - a pointer to the wireless adapter's private structure |
| * |
| * RETURNS: |
| * |
| * an HCF status code |
| * |
| ******************************************************************************/ |
| int wl_put_ltv( struct wl_private *lp ) |
| { |
| int len; |
| int hcf_status; |
| /*------------------------------------------------------------------------*/ |
| DBG_FUNC( "wl_put_ltv" ); |
| DBG_ENTER( DbgInfo ); |
| |
| if ( lp == NULL ) { |
| DBG_ERROR( DbgInfo, "lp pointer is NULL\n" ); |
| return -1; |
| } |
| if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) { |
| lp->maxPort = 6; //;?why set this here and not as part of download process |
| } else { |
| lp->maxPort = 0; |
| } |
| |
| /* Send our configuration to the card. Perform any endian translation |
| necessary */ |
| /* Register the Mailbox; VxWorks does this elsewhere; why;? */ |
| lp->ltvRecord.len = 4; |
| lp->ltvRecord.typ = CFG_REG_MB; |
| lp->ltvRecord.u.u32[0] = (u_long)&( lp->mailbox ); |
| lp->ltvRecord.u.u16[2] = ( MB_SIZE / sizeof( hcf_16 )); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* Max Data Length */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_CNF_MAX_DATA_LEN; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( HCF_MAX_PACKET_SIZE ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* System Scale / Distance between APs */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_CNF_SYSTEM_SCALE; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->DistanceBetweenAPs ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* Channel */ |
| if ( lp->CreateIBSS && ( lp->Channel == 0 )) { |
| DBG_TRACE( DbgInfo, "Create IBSS" ); |
| lp->Channel = 10; |
| } |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_CNF_OWN_CHANNEL; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->Channel ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* Microwave Robustness */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_CNF_MICRO_WAVE; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->MicrowaveRobustness ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* Load Balancing */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_CNF_LOAD_BALANCING; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->loadBalancing ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* Medium Distribution */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_CNF_MEDIUM_DISTRIBUTION; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->mediumDistribution ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| /* Country Code */ |
| |
| #ifdef WARP |
| /* Tx Power Level (for supported cards) */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_CNF_TX_POW_LVL; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->txPowLevel ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* Short Retry Limit */ |
| /*lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = 0xFC32; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->shortRetryLimit ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| */ |
| |
| /* Long Retry Limit */ |
| /*lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = 0xFC33; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->longRetryLimit ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| */ |
| |
| /* Supported Rate Set Control */ |
| lp->ltvRecord.len = 3; |
| lp->ltvRecord.typ = CFG_SUPPORTED_RATE_SET_CNTL; //0xFC88; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->srsc[0] ); |
| lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( lp->srsc[1] ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* Basic Rate Set Control */ |
| lp->ltvRecord.len = 3; |
| lp->ltvRecord.typ = CFG_BASIC_RATE_SET_CNTL; //0xFC89; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->brsc[0] ); |
| lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( lp->brsc[1] ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* Frame Burst Limit */ |
| /* Defined, but not currently available in Firmware */ |
| |
| #endif // WARP |
| |
| #ifdef WARP |
| /* Multicast Rate */ |
| lp->ltvRecord.len = 3; |
| lp->ltvRecord.typ = CFG_CNF_MCAST_RATE; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->MulticastRate[0] ); |
| lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( lp->MulticastRate[1] ); |
| #else |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_CNF_MCAST_RATE; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->MulticastRate[0] ); |
| #endif // WARP |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* Own Name (Station Nickname) */ |
| if (( len = ( strlen( lp->StationName ) + 1 ) & ~0x01 ) != 0 ) { |
| //DBG_TRACE( DbgInfo, "CFG_CNF_OWN_NAME : %s\n", |
| // lp->StationName ); |
| |
| lp->ltvRecord.len = 2 + ( len / sizeof( hcf_16 )); |
| lp->ltvRecord.typ = CFG_CNF_OWN_NAME; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( strlen( lp->StationName )); |
| |
| memcpy( &( lp->ltvRecord.u.u8[2] ), lp->StationName, len ); |
| } else { |
| //DBG_TRACE( DbgInfo, "CFG_CNF_OWN_NAME : EMPTY\n" ); |
| |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_CNF_OWN_NAME; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 ); |
| } |
| |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| //DBG_TRACE( DbgInfo, "CFG_CNF_OWN_NAME result : 0x%04x\n", |
| // hcf_status ); |
| |
| /* The following are set in STA mode only */ |
| if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA ) { |
| |
| /* RTS Threshold */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_RTS_THRH; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->RTSThreshold ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* Port Type */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_CNF_PORT_TYPE; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->PortType ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* Tx Rate Control */ |
| #ifdef WARP |
| lp->ltvRecord.len = 3; |
| lp->ltvRecord.typ = CFG_TX_RATE_CNTL; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->TxRateControl[0] ); |
| lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( lp->TxRateControl[1] ); |
| #else |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_TX_RATE_CNTL; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->TxRateControl[0] ); |
| #endif // WARP |
| |
| //;?skip temporarily to see whether the RID or something else is the probelm hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL 2.4GHz : 0x%04x\n", |
| lp->TxRateControl[0] ); |
| DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL 5.0GHz : 0x%04x\n", |
| lp->TxRateControl[1] ); |
| DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL result : 0x%04x\n", |
| hcf_status ); |
| /* Power Management */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_CNF_PM_ENABLED; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->PMEnabled ); |
| // lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0x8001 ); |
| DBG_TRACE( DbgInfo, "CFG_CNF_PM_ENABLED : 0x%04x\n", lp->PMEnabled ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| /* Multicast Receive */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_CNF_MCAST_RX; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->MulticastReceive ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* Max Sleep Duration */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_CNF_MAX_SLEEP_DURATION; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->MaxSleepDuration ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* Create IBSS */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_CREATE_IBSS; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->CreateIBSS ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* Desired SSID */ |
| if ((( len = ( strlen( lp->NetworkName ) + 1 ) & ~0x01 ) != 0 ) && |
| ( strcmp( lp->NetworkName, "ANY" ) != 0 ) && |
| ( strcmp( lp->NetworkName, "any" ) != 0 )) { |
| //DBG_TRACE( DbgInfo, "CFG_DESIRED_SSID : %s\n", |
| // lp->NetworkName ); |
| |
| lp->ltvRecord.len = 2 + (len / sizeof(hcf_16)); |
| lp->ltvRecord.typ = CFG_DESIRED_SSID; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( strlen( lp->NetworkName )); |
| |
| memcpy( &( lp->ltvRecord.u.u8[2] ), lp->NetworkName, len ); |
| } else { |
| //DBG_TRACE( DbgInfo, "CFG_DESIRED_SSID : ANY\n" ); |
| |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_DESIRED_SSID; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 ); |
| } |
| |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| //DBG_TRACE( DbgInfo, "CFG_DESIRED_SSID result : 0x%04x\n", |
| // hcf_status ); |
| /* Own ATIM window */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_CNF_OWN_ATIM_WINDOW; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->atimWindow ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| |
| /* Holdover Duration */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_CNF_HOLDOVER_DURATION; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->holdoverDuration ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* Promiscuous Mode */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_PROMISCUOUS_MODE; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->promiscuousMode ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* Authentication */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_CNF_AUTHENTICATION; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->authentication ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| #ifdef WARP |
| /* Connection Control */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_CNF_CONNECTION_CNTL; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->connectionControl ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| |
| |
| /* Probe data rate */ |
| /*lp->ltvRecord.len = 3; |
| lp->ltvRecord.typ = CFG_PROBE_DATA_RATE; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->probeDataRates[0] ); |
| lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( lp->probeDataRates[1] ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| DBG_TRACE( DbgInfo, "CFG_PROBE_DATA_RATE 2.4GHz : 0x%04x\n", |
| lp->probeDataRates[0] ); |
| DBG_TRACE( DbgInfo, "CFG_PROBE_DATA_RATE 5.0GHz : 0x%04x\n", |
| lp->probeDataRates[1] ); |
| DBG_TRACE( DbgInfo, "CFG_PROBE_DATA_RATE result : 0x%04x\n", |
| hcf_status );*/ |
| #endif // WARP |
| } else { |
| /* The following are set in AP mode only */ |
| #if 0 //;? (HCF_TYPE) & HCF_TYPE_AP |
| //;?should we restore this to allow smaller memory footprint |
| |
| /* DTIM Period */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_CNF_OWN_DTIM_PERIOD; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->DTIMPeriod ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* Multicast PM Buffering */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_CNF_MCAST_PM_BUF; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->multicastPMBuffering ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* Reject ANY - Closed System */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_CNF_REJECT_ANY; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->RejectAny ); |
| |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* Exclude Unencrypted */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_CNF_EXCL_UNENCRYPTED; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->ExcludeUnencrypted ); |
| |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* IntraBSS Relay */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_CNF_INTRA_BSS_RELAY; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->intraBSSRelay ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* RTS Threshold 0 */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_RTS_THRH0; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->RTSThreshold ); |
| |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* Tx Rate Control 0 */ |
| #ifdef WARP |
| lp->ltvRecord.len = 3; |
| lp->ltvRecord.typ = CFG_TX_RATE_CNTL0; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->TxRateControl[0] ); |
| lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE( lp->TxRateControl[1] ); |
| #else |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_TX_RATE_CNTL0; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->TxRateControl[0] ); |
| #endif // WARP |
| |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* Own Beacon Interval */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = 0xFC31; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->ownBeaconInterval ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* Co-Existence Behavior */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = 0xFCC7; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->coexistence ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| #ifdef USE_WDS |
| |
| /* RTS Threshold 1 */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_RTS_THRH1; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->wds_port[0].rtsThreshold ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* RTS Threshold 2 */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_RTS_THRH2; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->wds_port[1].rtsThreshold ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| |
| /* RTS Threshold 3 */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_RTS_THRH3; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->wds_port[2].rtsThreshold ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| |
| /* RTS Threshold 4 */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_RTS_THRH4; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->wds_port[3].rtsThreshold ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| |
| /* RTS Threshold 5 */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_RTS_THRH5; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->wds_port[4].rtsThreshold ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* RTS Threshold 6 */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_RTS_THRH6; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->wds_port[5].rtsThreshold ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| #if 0 |
| /* TX Rate Control 1 */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_TX_RATE_CNTL1; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->wds_port[0].txRateCntl ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* TX Rate Control 2 */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_TX_RATE_CNTL2; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->wds_port[1].txRateCntl ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* TX Rate Control 3 */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_TX_RATE_CNTL3; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->wds_port[2].txRateCntl ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* TX Rate Control 4 */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_TX_RATE_CNTL4; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->wds_port[3].txRateCntl ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* TX Rate Control 5 */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_TX_RATE_CNTL5; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->wds_port[4].txRateCntl ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* TX Rate Control 6 */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_TX_RATE_CNTL6; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->wds_port[5].txRateCntl ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| #endif |
| |
| /* WDS addresses. It's okay to blindly send these parameters, because |
| the port needs to be enabled, before anything is done with it. */ |
| |
| /* WDS Address 1 */ |
| lp->ltvRecord.len = 4; |
| lp->ltvRecord.typ = CFG_CNF_WDS_ADDR1; |
| |
| memcpy( &lp->ltvRecord.u.u8[0], lp->wds_port[0].wdsAddress, ETH_ALEN ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* WDS Address 2 */ |
| lp->ltvRecord.len = 4; |
| lp->ltvRecord.typ = CFG_CNF_WDS_ADDR2; |
| |
| memcpy( &lp->ltvRecord.u.u8[0], lp->wds_port[1].wdsAddress, ETH_ALEN ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* WDS Address 3 */ |
| lp->ltvRecord.len = 4; |
| lp->ltvRecord.typ = CFG_CNF_WDS_ADDR3; |
| |
| memcpy( &lp->ltvRecord.u.u8[0], lp->wds_port[2].wdsAddress, ETH_ALEN ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* WDS Address 4 */ |
| lp->ltvRecord.len = 4; |
| lp->ltvRecord.typ = CFG_CNF_WDS_ADDR4; |
| |
| memcpy( &lp->ltvRecord.u.u8[0], lp->wds_port[3].wdsAddress, ETH_ALEN ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* WDS Address 5 */ |
| lp->ltvRecord.len = 4; |
| lp->ltvRecord.typ = CFG_CNF_WDS_ADDR5; |
| |
| memcpy( &lp->ltvRecord.u.u8[0], lp->wds_port[4].wdsAddress, ETH_ALEN ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* WDS Address 6 */ |
| lp->ltvRecord.len = 4; |
| lp->ltvRecord.typ = CFG_CNF_WDS_ADDR6; |
| |
| memcpy( &lp->ltvRecord.u.u8[0], lp->wds_port[5].wdsAddress, ETH_ALEN ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| #endif /* USE_WDS */ |
| #endif /* (HCF_TYPE) & HCF_TYPE_AP */ |
| } |
| |
| /* Own MAC Address */ |
| //DBG_TRACE( DbgInfo, "MAC Address : %s\n", |
| // DbgHwAddr( lp->MACAddress )); |
| |
| if ( WVLAN_VALID_MAC_ADDRESS( lp->MACAddress )) { |
| /* Make the MAC address valid by: |
| Clearing the multicast bit |
| Setting the local MAC address bit |
| */ |
| //lp->MACAddress[0] &= ~0x03; //;?why is this commented out already in 720 |
| //lp->MACAddress[0] |= 0x02; |
| |
| lp->ltvRecord.len = 1 + ( ETH_ALEN / sizeof( hcf_16 )); |
| if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) { |
| //DBG_TRACE( DbgInfo, "CFG_NIC_MAC_ADDR\n" ); |
| lp->ltvRecord.typ = CFG_NIC_MAC_ADDR; |
| } else { |
| //DBG_TRACE( DbgInfo, "CFG_CNF_OWN_MAC_ADDR\n" ); |
| lp->ltvRecord.typ = CFG_CNF_OWN_MAC_ADDR; |
| } |
| /* MAC address is byte aligned, no endian conversion needed */ |
| memcpy( &( lp->ltvRecord.u.u8[0] ), lp->MACAddress, ETH_ALEN ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| //DBG_TRACE( DbgInfo, "CFG_XXX_MAC_ADDR result : 0x%04x\n", |
| // hcf_status ); |
| |
| /* Update the MAC address in the netdevice struct */ |
| memcpy( lp->dev->dev_addr, lp->MACAddress, ETH_ALEN ); //;?what is the purpose of this seemingly complex logic |
| } |
| /* Own SSID */ |
| if ((( len = ( strlen( lp->NetworkName ) + 1 ) & ~0x01 ) != 0 ) && |
| ( strcmp( lp->NetworkName, "ANY" ) != 0 ) && |
| ( strcmp( lp->NetworkName, "any" ) != 0 )) { |
| //DBG_TRACE( DbgInfo, "CFG_CNF_OWN_SSID : %s\n", |
| // lp->NetworkName ); |
| lp->ltvRecord.len = 2 + (len / sizeof(hcf_16)); |
| lp->ltvRecord.typ = CFG_CNF_OWN_SSID; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( strlen( lp->NetworkName )); |
| |
| memcpy( &( lp->ltvRecord.u.u8[2] ), lp->NetworkName, len ); |
| } else { |
| //DBG_TRACE( DbgInfo, "CFG_CNF_OWN_SSID : ANY\n" ); |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_CNF_OWN_SSID; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 ); |
| } |
| |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| //DBG_TRACE( DbgInfo, "CFG_CNF_OWN_SSID result : 0x%04x\n", |
| // hcf_status ); |
| /* enable/disable encryption */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_CNF_ENCRYPTION; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->EnableEncryption ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| /* Set the Authentication Key Management Suite */ |
| lp->ltvRecord.len = 2; |
| lp->ltvRecord.typ = CFG_SET_WPA_AUTH_KEY_MGMT_SUITE; |
| lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( lp->AuthKeyMgmtSuite ); |
| hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| /* WEP Keys */ |
| wl_set_wep_keys( lp ); |
| |
| /* Country Code */ |
| /* countryInfo, ltvCountryInfo, CFG_CNF_COUNTRY_INFO */ |
| |
| DBG_LEAVE( DbgInfo ); |
| return hcf_status; |
| } // wl_put_ltv |
| /*============================================================================*/ |
| |
| |
| /******************************************************************************* |
| * init_module() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Load the kernel module. |
| * |
| * PARAMETERS: |
| * |
| * N/A |
| * |
| * RETURNS: |
| * |
| * 0 on success |
| * an errno value otherwise |
| * |
| ******************************************************************************/ |
| static int __init wl_module_init( void ) |
| { |
| int result; |
| /*------------------------------------------------------------------------*/ |
| |
| DBG_FUNC( "wl_module_init" ); |
| |
| #if DBG |
| /* Convert "standard" PCMCIA parameter pc_debug to a reasonable DebugFlag value. |
| * NOTE: The values all fall through to the lower values. */ |
| DbgInfo->DebugFlag = 0; |
| DbgInfo->DebugFlag = DBG_TRACE_ON; //;?get this mess resolved one day |
| if ( pc_debug ) switch( pc_debug ) { |
| case 8: |
| DbgInfo->DebugFlag |= DBG_DS_ON; |
| case 7: |
| DbgInfo->DebugFlag |= DBG_RX_ON | DBG_TX_ON; |
| case 6: |
| DbgInfo->DebugFlag |= DBG_PARAM_ON; |
| case 5: |
| DbgInfo->DebugFlag |= DBG_TRACE_ON; |
| case 4: |
| DbgInfo->DebugFlag |= DBG_VERBOSE_ON; |
| case 1: |
| DbgInfo->DebugFlag |= DBG_DEFAULTS; |
| default: |
| break; |
| } |
| #endif /* DBG */ |
| |
| DBG_ENTER( DbgInfo ); |
| printk(KERN_INFO "%s\n", VERSION_INFO); |
| printk(KERN_INFO "*** Modified for kernel 2.6 by Henk de Groot <pe1dnn@amsat.org>\n"); |
| printk(KERN_INFO "*** Based on 7.18 version by Andrey Borzenkov <arvidjaar@mail.ru> $Revision: 39 $\n"); |
| |
| |
| // ;?#if (HCF_TYPE) & HCF_TYPE_AP |
| // DBG_PRINT( "Access Point Mode (AP) Support: YES\n" ); |
| // #else |
| // DBG_PRINT( "Access Point Mode (AP) Support: NO\n" ); |
| // #endif /* (HCF_TYPE) & HCF_TYPE_AP */ |
| |
| result = wl_adapter_init_module( ); |
| DBG_LEAVE( DbgInfo ); |
| return result; |
| } // init_module |
| /*============================================================================*/ |
| |
| |
| /******************************************************************************* |
| * cleanup_module() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Unload the kernel module. |
| * |
| * PARAMETERS: |
| * |
| * N/A |
| * |
| * RETURNS: |
| * |
| * N/A |
| * |
| ******************************************************************************/ |
| static void __exit wl_module_exit( void ) |
| { |
| DBG_FUNC( "wl_module_exit" ); |
| DBG_ENTER(DbgInfo); |
| |
| wl_adapter_cleanup_module( ); |
| #if 0 //SCULL_USE_PROC /* don't waste space if unused */ |
| remove_proc_entry( "wlags", NULL ); //;?why so a-symmetric compared to location of create_proc_read_entry |
| #endif |
| |
| DBG_LEAVE( DbgInfo ); |
| return; |
| } // cleanup_module |
| /*============================================================================*/ |
| |
| module_init(wl_module_init); |
| module_exit(wl_module_exit); |
| |
| /******************************************************************************* |
| * wl_isr() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * The Interrupt Service Routine for the driver. |
| * |
| * PARAMETERS: |
| * |
| * irq - the irq the interrupt came in on |
| * dev_id - a buffer containing information about the request |
| * regs - |
| * |
| * RETURNS: |
| * |
| * N/A |
| * |
| ******************************************************************************/ |
| irqreturn_t wl_isr( int irq, void *dev_id, struct pt_regs *regs ) |
| { |
| int events; |
| struct net_device *dev = (struct net_device *) dev_id; |
| struct wl_private *lp = NULL; |
| /*------------------------------------------------------------------------*/ |
| if (( dev == NULL ) || ( !netif_device_present( dev ))) { |
| return IRQ_NONE; |
| } |
| |
| /* Set the wl_private pointer (lp), now that we know that dev is non-null */ |
| lp = wl_priv(dev); |
| |
| #ifdef USE_RTS |
| if ( lp->useRTS == 1 ) { |
| DBG_PRINT( "EXITING ISR, IN RTS MODE...\n" ); |
| return; |
| } |
| #endif /* USE_RTS */ |
| |
| /* If we have interrupts pending, then put them on a system task |
| queue. Otherwise turn interrupts back on */ |
| events = hcf_action( &lp->hcfCtx, HCF_ACT_INT_OFF ); |
| |
| if ( events == HCF_INT_PENDING ) { |
| /* Schedule the ISR handler as a bottom-half task in the |
| tq_immediate queue */ |
| tasklet_schedule(&lp->task); |
| } else { |
| //DBG_PRINT( "NOT OUR INTERRUPT\n" ); |
| hcf_action( &lp->hcfCtx, HCF_ACT_INT_ON ); |
| } |
| |
| return IRQ_RETVAL(events == HCF_INT_PENDING); |
| } // wl_isr |
| /*============================================================================*/ |
| |
| |
| /******************************************************************************* |
| * wl_isr_handler() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * The ISR handler, scheduled to run in a deferred context by the ISR. This |
| * is where the ISR's work actually gets done. |
| * |
| * PARAMETERS: |
| * |
| * lp - a pointer to the device's private adapter structure |
| * |
| * RETURNS: |
| * |
| * N/A |
| * |
| ******************************************************************************/ |
| #define WVLAN_MAX_INT_SERVICES 50 |
| |
| void wl_isr_handler( unsigned long p ) |
| { |
| struct net_device *dev; |
| unsigned long flags; |
| bool_t stop = TRUE; |
| int count; |
| int result; |
| struct wl_private *lp = (struct wl_private *)p; |
| /*------------------------------------------------------------------------*/ |
| |
| if ( lp == NULL ) { |
| DBG_PRINT( "wl_isr_handler lp adapter pointer is NULL!!!\n" ); |
| } else { |
| wl_lock( lp, &flags ); |
| |
| dev = (struct net_device *)lp->dev; |
| if ( dev != NULL && netif_device_present( dev ) ) stop = FALSE; |
| for( count = 0; stop == FALSE && count < WVLAN_MAX_INT_SERVICES; count++ ) { |
| stop = TRUE; |
| result = hcf_service_nic( &lp->hcfCtx, |
| (wci_bufp)lp->lookAheadBuf, |
| sizeof( lp->lookAheadBuf )); |
| if ( result == HCF_ERR_MIC ) { |
| wl_wext_event_mic_failed( dev ); /* Send an event that MIC failed */ |
| //;?this seems wrong if HCF_ERR_MIC coincides with another event, stop gets FALSE |
| //so why not do it always ;? |
| } |
| |
| #ifndef USE_MBOX_SYNC |
| if ( lp->hcfCtx.IFB_MBInfoLen != 0 ) { /* anything in the mailbox */ |
| wl_mbx( lp ); |
| stop = FALSE; |
| } |
| #endif |
| /* Check for a Link status event */ |
| if ( ( lp->hcfCtx.IFB_LinkStat & CFG_LINK_STAT_FW ) != 0 ) { |
| wl_process_link_status( lp ); |
| stop = FALSE; |
| } |
| /* Check for probe response events */ |
| if ( lp->ProbeResp.infoType != 0 && |
| lp->ProbeResp.infoType != 0xFFFF ) { |
| wl_process_probe_response( lp ); |
| memset( &lp->ProbeResp, 0, sizeof( lp->ProbeResp )); |
| lp->ProbeResp.infoType = 0xFFFF; |
| stop = FALSE; |
| } |
| /* Check for updated record events */ |
| if ( lp->updatedRecord.len != 0xFFFF ) { |
| wl_process_updated_record( lp ); |
| lp->updatedRecord.len = 0xFFFF; |
| stop = FALSE; |
| } |
| /* Check for association status events */ |
| if ( lp->assoc_stat.len != 0xFFFF ) { |
| wl_process_assoc_status( lp ); |
| lp->assoc_stat.len = 0xFFFF; |
| stop = FALSE; |
| } |
| /* Check for security status events */ |
| if ( lp->sec_stat.len != 0xFFFF ) { |
| wl_process_security_status( lp ); |
| lp->sec_stat.len = 0xFFFF; |
| stop = FALSE; |
| } |
| |
| #ifdef ENABLE_DMA |
| if ( lp->use_dma ) { |
| /* Check for DMA Rx packets */ |
| if ( lp->hcfCtx.IFB_DmaPackets & HREG_EV_RDMAD ) { |
| wl_rx_dma( dev ); |
| stop = FALSE; |
| } |
| /* Return Tx DMA descriptors to host */ |
| if ( lp->hcfCtx.IFB_DmaPackets & HREG_EV_TDMAD ) { |
| wl_pci_dma_hcf_reclaim_tx( lp ); |
| stop = FALSE; |
| } |
| } |
| else |
| #endif // ENABLE_DMA |
| { |
| /* Check for Rx packets */ |
| if ( lp->hcfCtx.IFB_RxLen != 0 ) { |
| wl_rx( dev ); |
| stop = FALSE; |
| } |
| /* Make sure that queued frames get sent */ |
| if ( wl_send( lp )) { |
| stop = FALSE; |
| } |
| } |
| } |
| /* We're done, so turn interrupts which were turned off in wl_isr, back on */ |
| hcf_action( &lp->hcfCtx, HCF_ACT_INT_ON ); |
| wl_unlock( lp, &flags ); |
| } |
| return; |
| } // wl_isr_handler |
| /*============================================================================*/ |
| |
| |
| /******************************************************************************* |
| * wl_remove() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Notify the adapter that it has been removed. Since the adapter is gone, |
| * we should no longer try to talk to it. |
| * |
| * PARAMETERS: |
| * |
| * dev - a pointer to the device's net_device structure |
| * |
| * RETURNS: |
| * |
| * N/A |
| * |
| ******************************************************************************/ |
| void wl_remove( struct net_device *dev ) |
| { |
| struct wl_private *lp = wl_priv(dev); |
| unsigned long flags; |
| /*------------------------------------------------------------------------*/ |
| DBG_FUNC( "wl_remove" ); |
| DBG_ENTER( DbgInfo ); |
| |
| DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev ); |
| |
| wl_lock( lp, &flags ); |
| |
| /* stop handling interrupts */ |
| wl_act_int_off( lp ); |
| lp->is_handling_int = WL_NOT_HANDLING_INT; |
| |
| /* |
| * Disable the ports: just change state: since the |
| * card is gone it is useless to talk to it and at |
| * disconnect all state information is lost anyway. |
| */ |
| /* Reset portState */ |
| lp->portState = WVLAN_PORT_STATE_DISABLED; |
| |
| #if 0 //;? (HCF_TYPE) & HCF_TYPE_AP |
| #ifdef USE_WDS |
| //wl_disable_wds_ports( lp ); |
| #endif // USE_WDS |
| #endif /* (HCF_TYPE) & HCF_TYPE_AP */ |
| |
| /* Mark the device as unregistered */ |
| lp->is_registered = FALSE; |
| |
| /* Deregister the WDS ports as well */ |
| WL_WDS_NETDEV_DEREGISTER( lp ); |
| #ifdef USE_RTS |
| if ( lp->useRTS == 1 ) { |
| wl_unlock( lp, &flags ); |
| |
| DBG_LEAVE( DbgInfo ); |
| return; |
| } |
| #endif /* USE_RTS */ |
| |
| /* Inform the HCF that the card has been removed */ |
| hcf_connect( &lp->hcfCtx, HCF_DISCONNECT ); |
| |
| wl_unlock( lp, &flags ); |
| |
| DBG_LEAVE( DbgInfo ); |
| return; |
| } // wl_remove |
| /*============================================================================*/ |
| |
| |
| /******************************************************************************* |
| * wl_suspend() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Power-down and halt the adapter. |
| * |
| * PARAMETERS: |
| * |
| * dev - a pointer to the device's net_device structure |
| * |
| * RETURNS: |
| * |
| * N/A |
| * |
| ******************************************************************************/ |
| void wl_suspend( struct net_device *dev ) |
| { |
| struct wl_private *lp = wl_priv(dev); |
| unsigned long flags; |
| /*------------------------------------------------------------------------*/ |
| DBG_FUNC( "wl_suspend" ); |
| DBG_ENTER( DbgInfo ); |
| |
| DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev ); |
| |
| /* The adapter is suspended: |
| Stop the adapter |
| Power down |
| */ |
| wl_lock( lp, &flags ); |
| |
| /* Disable interrupt handling */ |
| wl_act_int_off( lp ); |
| |
| /* Disconnect */ |
| wl_disconnect( lp ); |
| |
| /* Disable */ |
| wl_disable( lp ); |
| |
| /* Disconnect from the adapter */ |
| hcf_connect( &lp->hcfCtx, HCF_DISCONNECT ); |
| |
| /* Reset portState to be sure (should have been done by wl_disable */ |
| lp->portState = WVLAN_PORT_STATE_DISABLED; |
| |
| wl_unlock( lp, &flags ); |
| |
| DBG_LEAVE( DbgInfo ); |
| return; |
| } // wl_suspend |
| /*============================================================================*/ |
| |
| |
| /******************************************************************************* |
| * wl_resume() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Resume a previously suspended adapter. |
| * |
| * PARAMETERS: |
| * |
| * dev - a pointer to the device's net_device structure |
| * |
| * RETURNS: |
| * |
| * N/A |
| * |
| ******************************************************************************/ |
| void wl_resume(struct net_device *dev) |
| { |
| struct wl_private *lp = wl_priv(dev); |
| unsigned long flags; |
| /*------------------------------------------------------------------------*/ |
| DBG_FUNC( "wl_resume" ); |
| DBG_ENTER( DbgInfo ); |
| |
| DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev ); |
| |
| wl_lock( lp, &flags ); |
| |
| /* Connect to the adapter */ |
| hcf_connect( &lp->hcfCtx, dev->base_addr ); |
| |
| /* Reset portState */ |
| lp->portState = WVLAN_PORT_STATE_DISABLED; |
| |
| /* Power might have been off, assume the card lost the firmware*/ |
| lp->firmware_present = WL_FRIMWARE_NOT_PRESENT; |
| |
| /* Reload the firmware and restart */ |
| wl_reset( dev ); |
| |
| /* Resume interrupt handling */ |
| wl_act_int_on( lp ); |
| |
| wl_unlock( lp, &flags ); |
| |
| DBG_LEAVE( DbgInfo ); |
| return; |
| } // wl_resume |
| /*============================================================================*/ |
| |
| |
| /******************************************************************************* |
| * wl_release() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * This function perfroms a check on the device and calls wl_remove() if |
| * necessary. This function can be used for all bus types, but exists mostly |
| * for the benefit of the Card Services driver, as there are times when |
| * wl_remove() does not get called. |
| * |
| * PARAMETERS: |
| * |
| * dev - a pointer to the device's net_device structure |
| * |
| * RETURNS: |
| * |
| * N/A |
| * |
| ******************************************************************************/ |
| void wl_release( struct net_device *dev ) |
| { |
| struct wl_private *lp = wl_priv(dev); |
| /*------------------------------------------------------------------------*/ |
| DBG_FUNC( "wl_release" ); |
| DBG_ENTER( DbgInfo ); |
| |
| DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev ); |
| /* If wl_remove() hasn't been called (i.e. when Card Services is shut |
| down with the card in the slot), then call it */ |
| if ( lp->is_registered == TRUE ) { |
| DBG_TRACE( DbgInfo, "Calling unregister_netdev(), as it wasn't called yet\n" ); |
| wl_remove( dev ); |
| |
| lp->is_registered = FALSE; |
| } |
| |
| DBG_LEAVE( DbgInfo ); |
| return; |
| } // wl_release |
| /*============================================================================*/ |
| |
| |
| /******************************************************************************* |
| * wl_get_irq_mask() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Accessor function to retrieve the irq_mask module parameter |
| * |
| * PARAMETERS: |
| * |
| * N/A |
| * |
| * RETURNS: |
| * |
| * The irq_mask module parameter |
| * |
| ******************************************************************************/ |
| p_u16 wl_get_irq_mask( void ) |
| { |
| return irq_mask; |
| } // wl_get_irq_mask |
| /*============================================================================*/ |
| |
| |
| /******************************************************************************* |
| * wl_get_irq_list() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Accessor function to retrieve the irq_list module parameter |
| * |
| * PARAMETERS: |
| * |
| * N/A |
| * |
| * RETURNS: |
| * |
| * The irq_list module parameter |
| * |
| ******************************************************************************/ |
| p_s8 * wl_get_irq_list( void ) |
| { |
| return irq_list; |
| } // wl_get_irq_list |
| /*============================================================================*/ |
| |
| |
| |
| /******************************************************************************* |
| * wl_enable() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Used to enable MAC ports |
| * |
| * PARAMETERS: |
| * |
| * lp - pointer to the device's private adapter structure |
| * |
| * RETURNS: |
| * |
| * N/A |
| * |
| ******************************************************************************/ |
| int wl_enable( struct wl_private *lp ) |
| { |
| int hcf_status = HCF_SUCCESS; |
| /*------------------------------------------------------------------------*/ |
| DBG_FUNC( "wl_enable" ); |
| DBG_ENTER( DbgInfo ); |
| |
| if ( lp->portState == WVLAN_PORT_STATE_ENABLED ) { |
| DBG_TRACE( DbgInfo, "No action: Card already enabled\n" ); |
| } else if ( lp->portState == WVLAN_PORT_STATE_CONNECTED ) { |
| //;?suspicuous logic, how can you be connected without being enabled so this is probably dead code |
| DBG_TRACE( DbgInfo, "No action: Card already connected\n" ); |
| } else { |
| hcf_status = hcf_cntl( &lp->hcfCtx, HCF_CNTL_ENABLE ); |
| if ( hcf_status == HCF_SUCCESS ) { |
| /* Set the status of the NIC to enabled */ |
| lp->portState = WVLAN_PORT_STATE_ENABLED; //;?bad mnemonic, NIC iso PORT |
| #ifdef ENABLE_DMA |
| if ( lp->use_dma ) { |
| wl_pci_dma_hcf_supply( lp ); //;?always succes? |
| } |
| #endif |
| } |
| } |
| if ( hcf_status != HCF_SUCCESS ) { //;?make this an assert |
| DBG_TRACE( DbgInfo, "failed: 0x%x\n", hcf_status ); |
| } |
| DBG_LEAVE( DbgInfo ); |
| return hcf_status; |
| } // wl_enable |
| /*============================================================================*/ |
| |
| |
| #ifdef USE_WDS |
| /******************************************************************************* |
| * wl_enable_wds_ports() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Used to enable the WDS MAC ports 1-6 |
| * |
| * PARAMETERS: |
| * |
| * lp - pointer to the device's private adapter structure |
| * |
| * RETURNS: |
| * |
| * N/A |
| * |
| ******************************************************************************/ |
| void wl_enable_wds_ports( struct wl_private * lp ) |
| { |
| |
| DBG_FUNC( "wl_enable_wds_ports" ); |
| DBG_ENTER( DbgInfo ); |
| if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ){ |
| DBG_ERROR( DbgInfo, "!!!!;? someone misunderstood something !!!!!\n" ); |
| } |
| DBG_LEAVE( DbgInfo ); |
| return; |
| } // wl_enable_wds_ports |
| #endif /* USE_WDS */ |
| /*============================================================================*/ |
| |
| |
| /******************************************************************************* |
| * wl_connect() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Used to connect a MAC port |
| * |
| * PARAMETERS: |
| * |
| * lp - pointer to the device's private adapter structure |
| * |
| * RETURNS: |
| * |
| * N/A |
| * |
| ******************************************************************************/ |
| int wl_connect( struct wl_private *lp ) |
| { |
| int hcf_status; |
| /*------------------------------------------------------------------------*/ |
| |
| DBG_FUNC( "wl_connect" ); |
| DBG_ENTER( DbgInfo ); |
| |
| if ( lp->portState != WVLAN_PORT_STATE_ENABLED ) { |
| DBG_TRACE( DbgInfo, "No action: Not in enabled state\n" ); |
| DBG_LEAVE( DbgInfo ); |
| return HCF_SUCCESS; |
| } |
| hcf_status = hcf_cntl( &lp->hcfCtx, HCF_CNTL_CONNECT ); |
| if ( hcf_status == HCF_SUCCESS ) { |
| lp->portState = WVLAN_PORT_STATE_CONNECTED; |
| } |
| DBG_LEAVE( DbgInfo ); |
| return hcf_status; |
| } // wl_connect |
| /*============================================================================*/ |
| |
| |
| /******************************************************************************* |
| * wl_disconnect() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Used to disconnect a MAC port |
| * |
| * PARAMETERS: |
| * |
| * lp - pointer to the device's private adapter structure |
| * |
| * RETURNS: |
| * |
| * N/A |
| * |
| ******************************************************************************/ |
| int wl_disconnect( struct wl_private *lp ) |
| { |
| int hcf_status; |
| /*------------------------------------------------------------------------*/ |
| |
| DBG_FUNC( "wl_disconnect" ); |
| DBG_ENTER( DbgInfo ); |
| |
| if ( lp->portState != WVLAN_PORT_STATE_CONNECTED ) { |
| DBG_TRACE( DbgInfo, "No action: Not in connected state\n" ); |
| DBG_LEAVE( DbgInfo ); |
| return HCF_SUCCESS; |
| } |
| hcf_status = hcf_cntl( &lp->hcfCtx, HCF_CNTL_DISCONNECT ); |
| if ( hcf_status == HCF_SUCCESS ) { |
| lp->portState = WVLAN_PORT_STATE_ENABLED; |
| } |
| DBG_LEAVE( DbgInfo ); |
| return hcf_status; |
| } // wl_disconnect |
| /*============================================================================*/ |
| |
| |
| /******************************************************************************* |
| * wl_disable() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Used to disable MAC ports |
| * |
| * PARAMETERS: |
| * |
| * lp - pointer to the device's private adapter structure |
| * port - the MAC port to disable |
| * |
| * RETURNS: |
| * |
| * N/A |
| * |
| ******************************************************************************/ |
| int wl_disable( struct wl_private *lp ) |
| { |
| int hcf_status = HCF_SUCCESS; |
| /*------------------------------------------------------------------------*/ |
| DBG_FUNC( "wl_disable" ); |
| DBG_ENTER( DbgInfo ); |
| |
| if ( lp->portState == WVLAN_PORT_STATE_DISABLED ) { |
| DBG_TRACE( DbgInfo, "No action: Port state is disabled\n" ); |
| } else { |
| hcf_status = hcf_cntl( &lp->hcfCtx, HCF_CNTL_DISABLE ); |
| if ( hcf_status == HCF_SUCCESS ) { |
| /* Set the status of the port to disabled */ //;?bad mnemonic use NIC iso PORT |
| lp->portState = WVLAN_PORT_STATE_DISABLED; |
| |
| #ifdef ENABLE_DMA |
| if ( lp->use_dma ) { |
| wl_pci_dma_hcf_reclaim( lp ); |
| } |
| #endif |
| } |
| } |
| if ( hcf_status != HCF_SUCCESS ) { |
| DBG_TRACE( DbgInfo, "failed: 0x%x\n", hcf_status ); |
| } |
| DBG_LEAVE( DbgInfo ); |
| return hcf_status; |
| } // wl_disable |
| /*============================================================================*/ |
| |
| |
| #ifdef USE_WDS |
| /******************************************************************************* |
| * wl_disable_wds_ports() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * Used to disable the WDS MAC ports 1-6 |
| * |
| * PARAMETERS: |
| * |
| * lp - pointer to the device's private adapter structure |
| * |
| * RETURNS: |
| * |
| * N/A |
| * |
| ******************************************************************************/ |
| void wl_disable_wds_ports( struct wl_private * lp ) |
| { |
| |
| DBG_FUNC( "wl_disable_wds_ports" ); |
| DBG_ENTER( DbgInfo ); |
| |
| if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ){ |
| DBG_ERROR( DbgInfo, "!!!!;? someone misunderstood something !!!!!\n" ); |
| } |
| // if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP ) { |
| // wl_disable( lp, HCF_PORT_1 ); |
| // wl_disable( lp, HCF_PORT_2 ); |
| // wl_disable( lp, HCF_PORT_3 ); |
| // wl_disable( lp, HCF_PORT_4 ); |
| // wl_disable( lp, HCF_PORT_5 ); |
| // wl_disable( lp, HCF_PORT_6 ); |
| // } |
| DBG_LEAVE( DbgInfo ); |
| return; |
| } // wl_disable_wds_ports |
| #endif // USE_WDS |
| /*============================================================================*/ |
| |
| |
| #ifndef USE_MBOX_SYNC |
| /******************************************************************************* |
| * wl_mbx() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * This function is used to read and process a mailbox message. |
| * |
| * |
| * PARAMETERS: |
| * |
| * lp - pointer to the device's private adapter structure |
| * |
| * RETURNS: |
| * |
| * an HCF status code |
| * |
| ******************************************************************************/ |
| int wl_mbx( struct wl_private *lp ) |
| { |
| int hcf_status = HCF_SUCCESS; |
| /*------------------------------------------------------------------------*/ |
| DBG_FUNC( "wl_mbx" ); |
| DBG_ENTER( DbgInfo ); |
| DBG_TRACE( DbgInfo, "Mailbox Info: IFB_MBInfoLen: %d\n", |
| lp->hcfCtx.IFB_MBInfoLen ); |
| |
| memset( &( lp->ltvRecord ), 0, sizeof( ltv_t )); |
| |
| lp->ltvRecord.len = MB_SIZE; |
| lp->ltvRecord.typ = CFG_MB_INFO; |
| hcf_status = hcf_get_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord )); |
| |
| if ( hcf_status != HCF_SUCCESS ) { |
| DBG_ERROR( DbgInfo, "hcf_get_info returned 0x%x\n", hcf_status ); |
| |
| DBG_LEAVE( DbgInfo ); |
| return hcf_status; |
| } |
| |
| if ( lp->ltvRecord.typ == CFG_MB_INFO ) { |
| DBG_LEAVE( DbgInfo ); |
| return hcf_status; |
| } |
| /* Endian translate the mailbox data, then process the message */ |
| wl_endian_translate_mailbox( &( lp->ltvRecord )); |
| wl_process_mailbox( lp ); |
| DBG_LEAVE( DbgInfo ); |
| return hcf_status; |
| } // wl_mbx |
| /*============================================================================*/ |
| |
| |
| /******************************************************************************* |
| * wl_endian_translate_mailbox() |
| ******************************************************************************* |
| * |
| * DESCRIPTION: |
| * |
| * This function will perform the tedious task of endian translating all |
| * fields withtin a mailbox message which need translating. |
| * |
| * PARAMETERS: |
| * |
| * ltv - pointer to the LTV to endian translate |
| * |
| * RETURNS: |
| * |
| * none |
| * |
| ******************************************************************************/ |
| void wl_endian_translate_mailbox( ltv_t *ltv ) |
| { |
| |
| DBG_FUNC( "wl_endian_translate_mailbox" ); |
| DBG_ENTER( DbgInfo ); |
| switch( ltv->typ ) { |
| case CFG_TALLIES: |
| break; |
| |
| case CFG_SCAN: |
| { |
| int num_aps; |
| SCAN_RS_STRCT *aps = (SCAN_RS_STRCT *)<v->u.u8[0]; |
| |
| num_aps = (hcf_16)(( (size_t)(ltv->len - 1 ) * 2 ) / |
| ( sizeof( SCAN_RS_STRCT ))); |
| |
| while( num_aps >= 1 ) { |
| num_aps--; |
| |
| aps[num_aps].channel_id = |
| CNV_LITTLE_TO_INT( aps[num_aps].channel_id ); |
| |
| aps[num_aps].noise_level = |
| CNV_LITTLE_TO_INT( aps[num_aps].noise_level ); |
| |
| aps[num_aps].signal_level = |
| CNV_LITTLE_TO_INT( aps[num_aps].signal_level ); |
| |
| aps[num_aps].beacon_interval_time = |
| CNV_LITTLE_TO_INT( aps[num_aps].beacon_interval_time ); |
| |
| aps[num_aps].capability = |
| CNV_LITTLE_TO_INT( aps[num_aps].capability ); |
| |
| aps[num_aps].ssid_len = |
| CNV_LITTLE_TO_INT( aps[num_aps].ssid_len ); |
| |
| aps[num_aps].ssid_val[aps[num_aps].ssid_len] = 0; |
| } |
| } |
| break; |
| |
| case CFG_ACS_SCAN: |
| { |
| PROBE_RESP *probe_resp = (PROBE_RESP *)ltv; |
| |
| probe_resp->frameControl = CNV_LITTLE_TO_INT( probe_resp->frameControl ); |
| probe_resp->durID = CNV_LITTLE_TO_INT( probe_resp->durID ); |
| probe_resp->sequence = CNV_LITTLE_TO_INT( probe_resp->sequence ); |
| probe_resp->dataLength = CNV_LITTLE_TO_INT( probe_resp->dataLength ); |
| #ifndef WARP |
| probe_resp->lenType = CNV_LITTLE_TO_INT( probe_resp->lenType ); |
| #endif // WARP |
| probe_resp->beaconInterval = CNV_LITTLE_TO_INT( probe_resp->beaconInterval ); |
| probe_resp->capability = CNV_LITTLE_TO_INT( probe_resp->capability ); |
| probe_resp->flags = CNV_LITTLE_TO_INT
|