1/** 2 * This file contains the initialization for FW and HW 3 */ 4#include <linux/firmware.h> 5 6#include "host.h" 7#include "defs.h" 8#include "decl.h" 9#include "dev.h" 10#include "wext.h" 11#include "if_usb.h" 12 13/** 14 * @brief This function checks the validity of Boot2/FW image. 15 * 16 * @param data pointer to image 17 * len image length 18 * @return 0 or -1 19 */ 20static int check_fwfile_format(u8 *data, u32 totlen) 21{ 22 u32 bincmd, exit; 23 u32 blksize, offset, len; 24 int ret; 25 26 ret = 1; 27 exit = len = 0; 28 29 do { 30 struct fwheader *fwh = (void *)data; 31 32 bincmd = le32_to_cpu(fwh->dnldcmd); 33 blksize = le32_to_cpu(fwh->datalength); 34 switch (bincmd) { 35 case FW_HAS_DATA_TO_RECV: 36 offset = sizeof(struct fwheader) + blksize; 37 data += offset; 38 len += offset; 39 if (len >= totlen) 40 exit = 1; 41 break; 42 case FW_HAS_LAST_BLOCK: 43 exit = 1; 44 ret = 0; 45 break; 46 default: 47 exit = 1; 48 break; 49 } 50 } while (!exit); 51 52 if (ret) 53 lbs_pr_err("firmware file format check FAIL\n"); 54 else 55 lbs_deb_fw("firmware file format check PASS\n"); 56 57 return ret; 58} 59 60/** 61 * @brief This function downloads firmware image, gets 62 * HW spec from firmware and set basic parameters to 63 * firmware. 64 * 65 * @param priv A pointer to wlan_private structure 66 * @return 0 or -1 67 */ 68static int wlan_setup_station_hw(wlan_private * priv, char *fw_name) 69{ 70 int ret = -1; 71 wlan_adapter *adapter = priv->adapter; 72 73 lbs_deb_enter(LBS_DEB_FW); 74 75 if ((ret = request_firmware(&priv->firmware, fw_name, 76 priv->hotplug_device)) < 0) { 77 lbs_pr_err("request_firmware() failed with %#x\n", ret); 78 lbs_pr_err("firmware %s not found\n", fw_name); 79 goto done; 80 } 81 82 if (check_fwfile_format(priv->firmware->data, priv->firmware->size)) { 83 release_firmware(priv->firmware); 84 goto done; 85 } 86 87 ret = priv->hw_prog_firmware(priv); 88 89 release_firmware(priv->firmware); 90 91 if (ret) { 92 lbs_deb_fw("bootloader in invalid state\n"); 93 ret = -1; 94 goto done; 95 } 96 97 /* 98 * Read MAC address from HW 99 */ 100 memset(adapter->current_addr, 0xff, ETH_ALEN); 101 102 ret = libertas_prepare_and_send_command(priv, cmd_get_hw_spec, 103 0, cmd_option_waitforrsp, 0, NULL); 104 105 if (ret) { 106 ret = -1; 107 goto done; 108 } 109 110 libertas_set_mac_packet_filter(priv); 111 112 /* Get the supported Data rates */ 113 ret = libertas_prepare_and_send_command(priv, cmd_802_11_data_rate, 114 cmd_act_get_tx_rate, 115 cmd_option_waitforrsp, 0, NULL); 116 117 if (ret) { 118 ret = -1; 119 goto done; 120 } 121 122 ret = 0; 123done: 124 lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); 125 return ret; 126} 127 128static int wlan_allocate_adapter(wlan_private * priv) 129{ 130 size_t bufsize; 131 wlan_adapter *adapter = priv->adapter; 132 133 /* Allocate buffer to store the BSSID list */ 134 bufsize = MAX_NETWORK_COUNT * sizeof(struct bss_descriptor); 135 adapter->networks = kzalloc(bufsize, GFP_KERNEL); 136 if (!adapter->networks) { 137 lbs_pr_err("Out of memory allocating beacons\n"); 138 libertas_free_adapter(priv); 139 return -ENOMEM; 140 } 141 142 /* Allocate the command buffers */ 143 libertas_allocate_cmd_buffer(priv); 144 145 memset(&adapter->libertas_ps_confirm_sleep, 0, sizeof(struct PS_CMD_ConfirmSleep)); 146 adapter->libertas_ps_confirm_sleep.seqnum = cpu_to_le16(++adapter->seqnum); 147 adapter->libertas_ps_confirm_sleep.command = 148 cpu_to_le16(cmd_802_11_ps_mode); 149 adapter->libertas_ps_confirm_sleep.size = 150 cpu_to_le16(sizeof(struct PS_CMD_ConfirmSleep)); 151 adapter->libertas_ps_confirm_sleep.result = 0; 152 adapter->libertas_ps_confirm_sleep.action = 153 cpu_to_le16(cmd_subcmd_sleep_confirmed); 154 155 return 0; 156} 157 158static void wlan_init_adapter(wlan_private * priv) 159{ 160 wlan_adapter *adapter = priv->adapter; 161 int i; 162 163 adapter->scanprobes = 0; 164 165 adapter->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR; 166 adapter->data_avg_factor = DEFAULT_DATA_AVG_FACTOR; 167 168 /* ATIM params */ 169 adapter->atimwindow = 0; 170 171 adapter->connect_status = libertas_disconnected; 172 memset(adapter->current_addr, 0xff, ETH_ALEN); 173 174 /* scan type */ 175 adapter->scantype = cmd_scan_type_active; 176 177 /* scan mode */ 178 adapter->scanmode = cmd_bss_type_any; 179 180 /* 802.11 specific */ 181 adapter->secinfo.wep_enabled = 0; 182 for (i = 0; i < sizeof(adapter->wep_keys) / sizeof(adapter->wep_keys[0]); 183 i++) 184 memset(&adapter->wep_keys[i], 0, sizeof(struct WLAN_802_11_KEY)); 185 adapter->wep_tx_keyidx = 0; 186 adapter->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; 187 adapter->mode = IW_MODE_INFRA; 188 189 adapter->pending_assoc_req = NULL; 190 adapter->in_progress_assoc_req = NULL; 191 192 /* Initialize scan result lists */ 193 INIT_LIST_HEAD(&adapter->network_free_list); 194 INIT_LIST_HEAD(&adapter->network_list); 195 for (i = 0; i < MAX_NETWORK_COUNT; i++) { 196 list_add_tail(&adapter->networks[i].list, 197 &adapter->network_free_list); 198 } 199 200 mutex_init(&adapter->lock); 201 202 adapter->prescan = 1; 203 204 memset(&adapter->curbssparams, 0, sizeof(adapter->curbssparams)); 205 adapter->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL; 206 207 /* PnP and power profile */ 208 adapter->surpriseremoved = 0; 209 210 adapter->currentpacketfilter = 211 cmd_act_mac_rx_on | cmd_act_mac_tx_on; 212 213 adapter->radioon = RADIO_ON; 214 adapter->txantenna = RF_ANTENNA_2; 215 adapter->rxantenna = RF_ANTENNA_AUTO; 216 217 adapter->is_datarate_auto = 1; 218 adapter->beaconperiod = MRVDRV_BEACON_INTERVAL; 219 220 // set default value of capinfo. 221#define SHORT_PREAMBLE_ALLOWED 1 222 memset(&adapter->capinfo, 0, sizeof(adapter->capinfo)); 223 adapter->capinfo.shortpreamble = SHORT_PREAMBLE_ALLOWED; 224 225 adapter->psmode = wlan802_11powermodecam; 226 adapter->multipledtim = MRVDRV_DEFAULT_MULTIPLE_DTIM; 227 228 adapter->listeninterval = MRVDRV_DEFAULT_LISTEN_INTERVAL; 229 230 adapter->psstate = PS_STATE_FULL_POWER; 231 adapter->needtowakeup = 0; 232 adapter->locallisteninterval = 0; /* default value in firmware will be used */ 233 234 adapter->datarate = 0; // Initially indicate the rate as auto 235 236 adapter->adhoc_grate_enabled = 0; 237 238 adapter->intcounter = 0; 239 240 adapter->currenttxskb = NULL; 241 adapter->pkttxctrl = 0; 242 243 memset(&adapter->tx_queue_ps, 0, NR_TX_QUEUE*sizeof(struct sk_buff*)); 244 adapter->tx_queue_idx = 0; 245 spin_lock_init(&adapter->txqueue_lock); 246 247 return; 248} 249 250static void command_timer_fn(unsigned long data); 251 252int libertas_init_fw(wlan_private * priv, char *fw_name) 253{ 254 int ret = -1; 255 wlan_adapter *adapter = priv->adapter; 256 257 lbs_deb_enter(LBS_DEB_FW); 258 259 /* Allocate adapter structure */ 260 if ((ret = wlan_allocate_adapter(priv)) != 0) 261 goto done; 262 263 /* init adapter structure */ 264 wlan_init_adapter(priv); 265 266 /* init timer etc. */ 267 setup_timer(&adapter->command_timer, command_timer_fn, 268 (unsigned long)priv); 269 270 /* download fimrware etc. */ 271 if ((ret = wlan_setup_station_hw(priv, fw_name)) != 0) { 272 del_timer_sync(&adapter->command_timer); 273 goto done; 274 } 275 276 /* init 802.11d */ 277 libertas_init_11d(priv); 278 279 ret = 0; 280done: 281 lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); 282 return ret; 283} 284 285void libertas_free_adapter(wlan_private * priv) 286{ 287 wlan_adapter *adapter = priv->adapter; 288 289 if (!adapter) { 290 lbs_deb_fw("why double free adapter?\n"); 291 return; 292 } 293 294 lbs_deb_fw("free command buffer\n"); 295 libertas_free_cmd_buffer(priv); 296 297 lbs_deb_fw("free command_timer\n"); 298 del_timer(&adapter->command_timer); 299 300 lbs_deb_fw("free scan results table\n"); 301 kfree(adapter->networks); 302 adapter->networks = NULL; 303 304 /* Free the adapter object itself */ 305 lbs_deb_fw("free adapter\n"); 306 kfree(adapter); 307 priv->adapter = NULL; 308} 309 310/** 311 * This function handles the timeout of command sending. 312 * It will re-send the same command again. 313 */ 314static void command_timer_fn(unsigned long data) 315{ 316 wlan_private *priv = (wlan_private *)data; 317 wlan_adapter *adapter = priv->adapter; 318 struct cmd_ctrl_node *ptempnode; 319 struct cmd_ds_command *cmd; 320 unsigned long flags; 321 322 ptempnode = adapter->cur_cmd; 323 if (ptempnode == NULL) { 324 lbs_deb_fw("ptempnode empty\n"); 325 return; 326 } 327 328 cmd = (struct cmd_ds_command *)ptempnode->bufvirtualaddr; 329 if (!cmd) { 330 lbs_deb_fw("cmd is NULL\n"); 331 return; 332 } 333 334 lbs_deb_fw("command_timer_fn fired, cmd %x\n", cmd->command); 335 336 if (!adapter->fw_ready) 337 return; 338 339 spin_lock_irqsave(&adapter->driver_lock, flags); 340 adapter->cur_cmd = NULL; 341 spin_unlock_irqrestore(&adapter->driver_lock, flags); 342 343 lbs_deb_fw("re-sending same command because of timeout\n"); 344 libertas_queue_cmd(adapter, ptempnode, 0); 345 346 wake_up_interruptible(&priv->mainthread.waitq); 347 348 return; 349} 350