• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500-V1.0.1.40_1.0.68/src/linux/linux-2.6/drivers/net/wireless/libertas/
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