blob: bf672f51f16310f29f53fddd186fcf79c0576657 [file] [log] [blame]
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001/**
2 * This file contains the handling of command
3 * responses as well as events generated by firmware.
4 */
5#include <linux/delay.h>
6#include <linux/if_arp.h>
7#include <linux/netdevice.h>
8
9#include <net/iw_handler.h>
10
11#include "host.h"
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020012#include "decl.h"
13#include "defs.h"
14#include "dev.h"
15#include "join.h"
16#include "wext.h"
17
18/**
19 * @brief This function handles disconnect event. it
20 * reports disconnect to upper layer, clean tx/rx packets,
21 * reset link state etc.
22 *
23 * @param priv A pointer to wlan_private structure
24 * @return n/a
25 */
26void libertas_mac_event_disconnected(wlan_private * priv)
27{
28 wlan_adapter *adapter = priv->adapter;
29 union iwreq_data wrqu;
30
Dan Williams0aef64d2007-08-02 11:31:18 -040031 if (adapter->connect_status != LIBERTAS_CONNECTED)
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020032 return;
33
Holger Schuriga6c87002007-08-02 11:54:10 -040034 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020035
36 memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
37 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
38
39 /*
40 * Cisco AP sends EAP failure and de-auth in less than 0.5 ms.
41 * It causes problem in the Supplicant
42 */
43
44 msleep_interruptible(1000);
Holger Schurig634b8f42007-05-25 13:05:16 -040045 wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020046
47 /* Free Tx and Rx packets */
48 kfree_skb(priv->adapter->currenttxskb);
49 priv->adapter->currenttxskb = NULL;
50
51 /* report disconnect to upper layer */
Holger Schurig634b8f42007-05-25 13:05:16 -040052 netif_stop_queue(priv->dev);
53 netif_carrier_off(priv->dev);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020054
55 /* reset SNR/NF/RSSI values */
56 memset(adapter->SNR, 0x00, sizeof(adapter->SNR));
57 memset(adapter->NF, 0x00, sizeof(adapter->NF));
58 memset(adapter->RSSI, 0x00, sizeof(adapter->RSSI));
59 memset(adapter->rawSNR, 0x00, sizeof(adapter->rawSNR));
60 memset(adapter->rawNF, 0x00, sizeof(adapter->rawNF));
61 adapter->nextSNRNF = 0;
62 adapter->numSNRNF = 0;
63 adapter->rxpd_rate = 0;
Holger Schuriga6c87002007-08-02 11:54:10 -040064 lbs_deb_cmd("current SSID '%s', length %u\n",
Dan Williamsd8efea22007-05-28 23:54:55 -040065 escape_essid(adapter->curbssparams.ssid,
66 adapter->curbssparams.ssid_len),
67 adapter->curbssparams.ssid_len);
Holger Schuriga6c87002007-08-02 11:54:10 -040068 lbs_deb_cmd("previous SSID '%s', length %u\n",
Dan Williamsd8efea22007-05-28 23:54:55 -040069 escape_essid(adapter->prev_ssid, adapter->prev_ssid_len),
70 adapter->prev_ssid_len);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020071
Dan Williams0aef64d2007-08-02 11:31:18 -040072 adapter->connect_status = LIBERTAS_DISCONNECTED;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020073
Dan Williamse76850d2007-05-25 17:09:41 -040074 /* Save previous SSID and BSSID for possible reassociation */
Dan Williamsd8efea22007-05-28 23:54:55 -040075 memcpy(&adapter->prev_ssid, &adapter->curbssparams.ssid,
76 IW_ESSID_MAX_SIZE);
77 adapter->prev_ssid_len = adapter->curbssparams.ssid_len;
78 memcpy(adapter->prev_bssid, adapter->curbssparams.bssid, ETH_ALEN);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020079
Dan Williamse76850d2007-05-25 17:09:41 -040080 /* Clear out associated SSID and BSSID since connection is
81 * no longer valid.
82 */
83 memset(&adapter->curbssparams.bssid, 0, ETH_ALEN);
Dan Williamsd8efea22007-05-28 23:54:55 -040084 memset(&adapter->curbssparams.ssid, 0, IW_ESSID_MAX_SIZE);
85 adapter->curbssparams.ssid_len = 0;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020086
87 if (adapter->psstate != PS_STATE_FULL_POWER) {
88 /* make firmware to exit PS mode */
Holger Schuriga6c87002007-08-02 11:54:10 -040089 lbs_deb_cmd("disconnected, so exit PS mode\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020090 libertas_ps_wakeup(priv, 0);
91 }
Holger Schuriga6c87002007-08-02 11:54:10 -040092 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020093}
94
95/**
96 * @brief This function handles MIC failure event.
97 *
98 * @param priv A pointer to wlan_private structure
99 * @para event the event id
100 * @return n/a
101 */
102static void handle_mic_failureevent(wlan_private * priv, u32 event)
103{
104 char buf[50];
105
Holger Schuriga6c87002007-08-02 11:54:10 -0400106 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200107 memset(buf, 0, sizeof(buf));
108
109 sprintf(buf, "%s", "MLME-MICHAELMICFAILURE.indication ");
110
111 if (event == MACREG_INT_CODE_MIC_ERR_UNICAST) {
112 strcat(buf, "unicast ");
113 } else {
114 strcat(buf, "multicast ");
115 }
116
117 libertas_send_iwevcustom_event(priv, buf);
Holger Schuriga6c87002007-08-02 11:54:10 -0400118 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200119}
120
121static int wlan_ret_reg_access(wlan_private * priv,
122 u16 type, struct cmd_ds_command *resp)
123{
Holger Schurig9012b282007-05-25 11:27:16 -0400124 int ret = 0;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200125 wlan_adapter *adapter = priv->adapter;
126
Holger Schurig9012b282007-05-25 11:27:16 -0400127 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200128
129 switch (type) {
Holger Schurig6b63cd02007-08-02 11:53:36 -0400130 case CMD_RET(CMD_MAC_REG_ACCESS):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200131 {
David Woodhouse981f1872007-05-25 23:36:54 -0400132 struct cmd_ds_mac_reg_access *reg = &resp->params.macreg;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200133
David Woodhouse981f1872007-05-25 23:36:54 -0400134 adapter->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
135 adapter->offsetvalue.value = le32_to_cpu(reg->value);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200136 break;
137 }
138
Holger Schurig6b63cd02007-08-02 11:53:36 -0400139 case CMD_RET(CMD_BBP_REG_ACCESS):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200140 {
David Woodhouse981f1872007-05-25 23:36:54 -0400141 struct cmd_ds_bbp_reg_access *reg = &resp->params.bbpreg;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200142
David Woodhouse981f1872007-05-25 23:36:54 -0400143 adapter->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200144 adapter->offsetvalue.value = reg->value;
145 break;
146 }
147
Holger Schurig6b63cd02007-08-02 11:53:36 -0400148 case CMD_RET(CMD_RF_REG_ACCESS):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200149 {
David Woodhouse981f1872007-05-25 23:36:54 -0400150 struct cmd_ds_rf_reg_access *reg = &resp->params.rfreg;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200151
David Woodhouse981f1872007-05-25 23:36:54 -0400152 adapter->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200153 adapter->offsetvalue.value = reg->value;
154 break;
155 }
156
157 default:
Holger Schurig9012b282007-05-25 11:27:16 -0400158 ret = -1;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200159 }
160
Holger Schurig9012b282007-05-25 11:27:16 -0400161 lbs_deb_enter_args(LBS_DEB_CMD, "ret %d", ret);
162 return ret;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200163}
164
165static int wlan_ret_get_hw_spec(wlan_private * priv,
166 struct cmd_ds_command *resp)
167{
168 u32 i;
169 struct cmd_ds_get_hw_spec *hwspec = &resp->params.hwspec;
170 wlan_adapter *adapter = priv->adapter;
171 int ret = 0;
172
Holger Schurig9012b282007-05-25 11:27:16 -0400173 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200174
175 adapter->fwcapinfo = le32_to_cpu(hwspec->fwcapinfo);
176
David Woodhousee5b3d472007-05-25 23:40:21 -0400177 memcpy(adapter->fwreleasenumber, hwspec->fwreleasenumber, 4);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200178
Holger Schuriga6c87002007-08-02 11:54:10 -0400179 lbs_deb_cmd("GET_HW_SPEC: firmware release %u.%u.%up%u\n",
David Woodhousee5b3d472007-05-25 23:40:21 -0400180 adapter->fwreleasenumber[2], adapter->fwreleasenumber[1],
181 adapter->fwreleasenumber[0], adapter->fwreleasenumber[3]);
Holger Schuriga6c87002007-08-02 11:54:10 -0400182 lbs_deb_cmd("GET_HW_SPEC: MAC addr " MAC_FMT "\n",
Holger Schurig0a6d0552007-08-02 11:50:35 -0400183 MAC_ARG(hwspec->permanentaddr));
Holger Schuriga6c87002007-08-02 11:54:10 -0400184 lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n",
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200185 hwspec->hwifversion, hwspec->version);
186
187 adapter->regioncode = le16_to_cpu(hwspec->regioncode);
188
189 for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
190 /* use the region code to search for the index */
191 if (adapter->regioncode == libertas_region_code_to_index[i]) {
192 adapter->regiontableindex = (u16) i;
193 break;
194 }
195 }
196
197 /* if it's unidentified region code, use the default (USA) */
198 if (i >= MRVDRV_MAX_REGION_CODE) {
199 adapter->regioncode = 0x10;
200 adapter->regiontableindex = 0;
David Woodhouse981f1872007-05-25 23:36:54 -0400201 lbs_pr_info("unidentified region code; using the default (USA)\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200202 }
203
David Woodhouse981f1872007-05-25 23:36:54 -0400204 if (adapter->current_addr[0] == 0xff)
205 memmove(adapter->current_addr, hwspec->permanentaddr, ETH_ALEN);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200206
Holger Schurig634b8f42007-05-25 13:05:16 -0400207 memcpy(priv->dev->dev_addr, adapter->current_addr, ETH_ALEN);
Holger Schurig78523da2007-05-25 11:49:19 -0400208 if (priv->mesh_dev)
David Woodhouse981f1872007-05-25 23:36:54 -0400209 memcpy(priv->mesh_dev->dev_addr, adapter->current_addr, ETH_ALEN);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200210
211 if (libertas_set_regiontable(priv, adapter->regioncode, 0)) {
212 ret = -1;
213 goto done;
214 }
215
216 if (libertas_set_universaltable(priv, 0)) {
217 ret = -1;
218 goto done;
219 }
220
Holger Schurig9012b282007-05-25 11:27:16 -0400221done:
222 lbs_deb_enter_args(LBS_DEB_CMD, "ret %d", ret);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200223 return ret;
224}
225
226static int wlan_ret_802_11_sleep_params(wlan_private * priv,
227 struct cmd_ds_command *resp)
228{
229 struct cmd_ds_802_11_sleep_params *sp = &resp->params.sleep_params;
230 wlan_adapter *adapter = priv->adapter;
231
Holger Schurig9012b282007-05-25 11:27:16 -0400232 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200233
Holger Schuriga6c87002007-08-02 11:54:10 -0400234 lbs_deb_cmd("error 0x%x, offset 0x%x, stabletime 0x%x, calcontrol 0x%x "
235 "extsleepclk 0x%x\n", le16_to_cpu(sp->error),
David Woodhouse981f1872007-05-25 23:36:54 -0400236 le16_to_cpu(sp->offset), le16_to_cpu(sp->stabletime),
237 sp->calcontrol, sp->externalsleepclk);
238
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200239 adapter->sp.sp_error = le16_to_cpu(sp->error);
240 adapter->sp.sp_offset = le16_to_cpu(sp->offset);
241 adapter->sp.sp_stabletime = le16_to_cpu(sp->stabletime);
David Woodhouse981f1872007-05-25 23:36:54 -0400242 adapter->sp.sp_calcontrol = sp->calcontrol;
243 adapter->sp.sp_extsleepclk = sp->externalsleepclk;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200244 adapter->sp.sp_reserved = le16_to_cpu(sp->reserved);
245
Holger Schurig9012b282007-05-25 11:27:16 -0400246 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200247 return 0;
248}
249
250static int wlan_ret_802_11_stat(wlan_private * priv,
251 struct cmd_ds_command *resp)
252{
Holger Schuriga6c87002007-08-02 11:54:10 -0400253 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200254/* currently adapter->wlan802_11Stat is unused
255
256 struct cmd_ds_802_11_get_stat *p11Stat = &resp->params.gstat;
257 wlan_adapter *adapter = priv->adapter;
258
259 // TODO Convert it to Big endian befor copy
260 memcpy(&adapter->wlan802_11Stat,
261 p11Stat, sizeof(struct cmd_ds_802_11_get_stat));
262*/
Holger Schuriga6c87002007-08-02 11:54:10 -0400263 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200264 return 0;
265}
266
267static int wlan_ret_802_11_snmp_mib(wlan_private * priv,
268 struct cmd_ds_command *resp)
269{
270 struct cmd_ds_802_11_snmp_mib *smib = &resp->params.smib;
271 u16 oid = le16_to_cpu(smib->oid);
272 u16 querytype = le16_to_cpu(smib->querytype);
273
Holger Schurig9012b282007-05-25 11:27:16 -0400274 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200275
Holger Schuriga6c87002007-08-02 11:54:10 -0400276 lbs_deb_cmd("SNMP_RESP: oid 0x%x, querytype 0x%x\n", oid,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200277 querytype);
Holger Schuriga6c87002007-08-02 11:54:10 -0400278 lbs_deb_cmd("SNMP_RESP: Buf size %d\n", le16_to_cpu(smib->bufsize));
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200279
Dan Williams0aef64d2007-08-02 11:31:18 -0400280 if (querytype == CMD_ACT_GET) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200281 switch (oid) {
Dan Williams0aef64d2007-08-02 11:31:18 -0400282 case FRAGTHRESH_I:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200283 priv->adapter->fragthsd =
David Woodhouse981f1872007-05-25 23:36:54 -0400284 le16_to_cpu(*((__le16 *)(smib->value)));
Holger Schuriga6c87002007-08-02 11:54:10 -0400285 lbs_deb_cmd("SNMP_RESP: frag threshold %u\n",
David Woodhouse981f1872007-05-25 23:36:54 -0400286 priv->adapter->fragthsd);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200287 break;
Dan Williams0aef64d2007-08-02 11:31:18 -0400288 case RTSTHRESH_I:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200289 priv->adapter->rtsthsd =
David Woodhouse981f1872007-05-25 23:36:54 -0400290 le16_to_cpu(*((__le16 *)(smib->value)));
Holger Schuriga6c87002007-08-02 11:54:10 -0400291 lbs_deb_cmd("SNMP_RESP: rts threshold %u\n",
David Woodhouse981f1872007-05-25 23:36:54 -0400292 priv->adapter->rtsthsd);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200293 break;
Dan Williams0aef64d2007-08-02 11:31:18 -0400294 case SHORT_RETRYLIM_I:
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200295 priv->adapter->txretrycount =
David Woodhouse981f1872007-05-25 23:36:54 -0400296 le16_to_cpu(*((__le16 *)(smib->value)));
Holger Schuriga6c87002007-08-02 11:54:10 -0400297 lbs_deb_cmd("SNMP_RESP: tx retry count %u\n",
David Woodhouse981f1872007-05-25 23:36:54 -0400298 priv->adapter->rtsthsd);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200299 break;
300 default:
301 break;
302 }
303 }
304
Holger Schurig9012b282007-05-25 11:27:16 -0400305 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200306 return 0;
307}
308
309static int wlan_ret_802_11_key_material(wlan_private * priv,
310 struct cmd_ds_command *resp)
311{
312 struct cmd_ds_802_11_key_material *pkeymaterial =
313 &resp->params.keymaterial;
314 wlan_adapter *adapter = priv->adapter;
315 u16 action = le16_to_cpu(pkeymaterial->action);
316
Holger Schurig9012b282007-05-25 11:27:16 -0400317 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200318
319 /* Copy the returned key to driver private data */
Dan Williams0aef64d2007-08-02 11:31:18 -0400320 if (action == CMD_ACT_GET) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200321 u8 * buf_ptr = (u8 *) &pkeymaterial->keyParamSet;
322 u8 * resp_end = (u8 *) (resp + le16_to_cpu(resp->size));
323
324 while (buf_ptr < resp_end) {
325 struct MrvlIEtype_keyParamSet * pkeyparamset =
326 (struct MrvlIEtype_keyParamSet *) buf_ptr;
Dan Williams1443b652007-08-02 10:45:55 -0400327 struct enc_key * pkey;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200328 u16 param_set_len = le16_to_cpu(pkeyparamset->length);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200329 u16 key_len = le16_to_cpu(pkeyparamset->keylen);
Dan Williams1443b652007-08-02 10:45:55 -0400330 u16 key_flags = le16_to_cpu(pkeyparamset->keyinfo);
331 u16 key_type = le16_to_cpu(pkeyparamset->keytypeid);
332 u8 * end;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200333
334 end = (u8 *) pkeyparamset + sizeof (pkeyparamset->type)
335 + sizeof (pkeyparamset->length)
336 + param_set_len;
337 /* Make sure we don't access past the end of the IEs */
338 if (end > resp_end)
339 break;
340
Dan Williams1443b652007-08-02 10:45:55 -0400341 if (key_flags & KEY_INFO_WPA_UNICAST)
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200342 pkey = &adapter->wpa_unicast_key;
Dan Williams1443b652007-08-02 10:45:55 -0400343 else if (key_flags & KEY_INFO_WPA_MCAST)
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200344 pkey = &adapter->wpa_mcast_key;
345 else
346 break;
347
348 /* Copy returned key into driver */
Dan Williams1443b652007-08-02 10:45:55 -0400349 memset(pkey, 0, sizeof(struct enc_key));
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200350 if (key_len > sizeof(pkey->key))
351 break;
Dan Williams1443b652007-08-02 10:45:55 -0400352 pkey->type = key_type;
353 pkey->flags = key_flags;
354 pkey->len = key_len;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200355 memcpy(pkey->key, pkeyparamset->key, pkey->len);
356
357 buf_ptr = end + 1;
358 }
359 }
360
Holger Schurig9012b282007-05-25 11:27:16 -0400361 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200362 return 0;
363}
364
365static int wlan_ret_802_11_mac_address(wlan_private * priv,
366 struct cmd_ds_command *resp)
367{
368 struct cmd_ds_802_11_mac_address *macadd = &resp->params.macadd;
369 wlan_adapter *adapter = priv->adapter;
370
Holger Schurig9012b282007-05-25 11:27:16 -0400371 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200372
373 memcpy(adapter->current_addr, macadd->macadd, ETH_ALEN);
374
Holger Schurig9012b282007-05-25 11:27:16 -0400375 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200376 return 0;
377}
378
379static int wlan_ret_802_11_rf_tx_power(wlan_private * priv,
380 struct cmd_ds_command *resp)
381{
382 struct cmd_ds_802_11_rf_tx_power *rtp = &resp->params.txp;
383 wlan_adapter *adapter = priv->adapter;
384
Holger Schurig9012b282007-05-25 11:27:16 -0400385 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200386
387 adapter->txpowerlevel = le16_to_cpu(rtp->currentlevel);
388
Holger Schuriga6c87002007-08-02 11:54:10 -0400389 lbs_deb_cmd("TX power currently %d\n", adapter->txpowerlevel);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200390
Holger Schuriga6c87002007-08-02 11:54:10 -0400391 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200392 return 0;
393}
394
395static int wlan_ret_802_11_rf_antenna(wlan_private * priv,
396 struct cmd_ds_command *resp)
397{
398 struct cmd_ds_802_11_rf_antenna *pAntenna = &resp->params.rant;
399 wlan_adapter *adapter = priv->adapter;
400 u16 action = le16_to_cpu(pAntenna->action);
401
Holger Schuriga6c87002007-08-02 11:54:10 -0400402 lbs_deb_enter(LBS_DEB_CMD);
Dan Williamsffcae952007-08-02 11:35:46 -0400403 if (action == CMD_ACT_GET_RX)
David Woodhouse981f1872007-05-25 23:36:54 -0400404 adapter->rxantennamode = le16_to_cpu(pAntenna->antennamode);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200405
Dan Williamsffcae952007-08-02 11:35:46 -0400406 if (action == CMD_ACT_GET_TX)
David Woodhouse981f1872007-05-25 23:36:54 -0400407 adapter->txantennamode = le16_to_cpu(pAntenna->antennamode);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200408
Holger Schuriga6c87002007-08-02 11:54:10 -0400409 lbs_deb_cmd("RF_ANT_RESP: action 0x%x, mode 0x%04x\n",
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200410 action, le16_to_cpu(pAntenna->antennamode));
411
Holger Schuriga6c87002007-08-02 11:54:10 -0400412 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200413 return 0;
414}
415
416static int wlan_ret_802_11_rate_adapt_rateset(wlan_private * priv,
417 struct cmd_ds_command *resp)
418{
David Woodhouse981f1872007-05-25 23:36:54 -0400419 struct cmd_ds_802_11_rate_adapt_rateset *rates = &resp->params.rateset;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200420 wlan_adapter *adapter = priv->adapter;
421
Holger Schurig9012b282007-05-25 11:27:16 -0400422 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200423
Dan Williams0aef64d2007-08-02 11:31:18 -0400424 if (rates->action == CMD_ACT_GET) {
David Woodhouse981f1872007-05-25 23:36:54 -0400425 adapter->enablehwauto = le16_to_cpu(rates->enablehwauto);
426 adapter->ratebitmap = le16_to_cpu(rates->bitmap);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200427 }
428
Holger Schuriga6c87002007-08-02 11:54:10 -0400429 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200430 return 0;
431}
432
433static int wlan_ret_802_11_data_rate(wlan_private * priv,
434 struct cmd_ds_command *resp)
435{
436 struct cmd_ds_802_11_data_rate *pdatarate = &resp->params.drate;
437 wlan_adapter *adapter = priv->adapter;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200438
Holger Schurig9012b282007-05-25 11:27:16 -0400439 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200440
Holger Schuriga6c87002007-08-02 11:54:10 -0400441 lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) pdatarate,
Dan Williams8c512762007-08-02 11:40:45 -0400442 sizeof(struct cmd_ds_802_11_data_rate));
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200443
Dan Williams8c512762007-08-02 11:40:45 -0400444 /* FIXME: get actual rates FW can do if this command actually returns
445 * all data rates supported.
446 */
447 adapter->cur_rate = libertas_fw_index_to_data_rate(pdatarate->rates[0]);
Holger Schuriga6c87002007-08-02 11:54:10 -0400448 lbs_deb_cmd("DATA_RATE: current rate 0x%02x\n", adapter->cur_rate);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200449
Dan Williams8c512762007-08-02 11:40:45 -0400450 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200451 return 0;
452}
453
454static int wlan_ret_802_11_rf_channel(wlan_private * priv,
455 struct cmd_ds_command *resp)
456{
David Woodhouse981f1872007-05-25 23:36:54 -0400457 struct cmd_ds_802_11_rf_channel *rfchannel = &resp->params.rfchannel;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200458 wlan_adapter *adapter = priv->adapter;
459 u16 action = le16_to_cpu(rfchannel->action);
460 u16 newchannel = le16_to_cpu(rfchannel->currentchannel);
461
Holger Schurig9012b282007-05-25 11:27:16 -0400462 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200463
Dan Williams0aef64d2007-08-02 11:31:18 -0400464 if (action == CMD_OPT_802_11_RF_CHANNEL_GET
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200465 && adapter->curbssparams.channel != newchannel) {
Holger Schuriga6c87002007-08-02 11:54:10 -0400466 lbs_deb_cmd("channel switch from %d to %d\n",
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200467 adapter->curbssparams.channel, newchannel);
468
469 /* Update the channel again */
470 adapter->curbssparams.channel = newchannel;
471 }
472
Holger Schurig9012b282007-05-25 11:27:16 -0400473 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200474 return 0;
475}
476
477static int wlan_ret_802_11_rssi(wlan_private * priv,
478 struct cmd_ds_command *resp)
479{
480 struct cmd_ds_802_11_rssi_rsp *rssirsp = &resp->params.rssirsp;
481 wlan_adapter *adapter = priv->adapter;
482
Holger Schuriga6c87002007-08-02 11:54:10 -0400483 lbs_deb_enter(LBS_DEB_CMD);
484
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200485 /* store the non average value */
486 adapter->SNR[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->SNR);
David Woodhouse981f1872007-05-25 23:36:54 -0400487 adapter->NF[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->noisefloor);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200488
489 adapter->SNR[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgSNR);
David Woodhouse981f1872007-05-25 23:36:54 -0400490 adapter->NF[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgnoisefloor);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200491
492 adapter->RSSI[TYPE_BEACON][TYPE_NOAVG] =
493 CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_NOAVG],
494 adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
495
496 adapter->RSSI[TYPE_BEACON][TYPE_AVG] =
497 CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE,
498 adapter->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE);
499
Holger Schuriga6c87002007-08-02 11:54:10 -0400500 lbs_deb_cmd("RSSI: beacon %d, avg %d\n",
501 adapter->RSSI[TYPE_BEACON][TYPE_NOAVG],
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200502 adapter->RSSI[TYPE_BEACON][TYPE_AVG]);
503
Holger Schuriga6c87002007-08-02 11:54:10 -0400504 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200505 return 0;
506}
507
508static int wlan_ret_802_11_eeprom_access(wlan_private * priv,
509 struct cmd_ds_command *resp)
510{
511 wlan_adapter *adapter = priv->adapter;
512 struct wlan_ioctl_regrdwr *pbuf;
513 pbuf = (struct wlan_ioctl_regrdwr *) adapter->prdeeprom;
514
Holger Schuriga6c87002007-08-02 11:54:10 -0400515 lbs_deb_enter_args(LBS_DEB_CMD, "len %d",
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200516 le16_to_cpu(resp->params.rdeeprom.bytecount));
517 if (pbuf->NOB < le16_to_cpu(resp->params.rdeeprom.bytecount)) {
518 pbuf->NOB = 0;
Holger Schuriga6c87002007-08-02 11:54:10 -0400519 lbs_deb_cmd("EEPROM read length too big\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200520 return -1;
521 }
522 pbuf->NOB = le16_to_cpu(resp->params.rdeeprom.bytecount);
523 if (pbuf->NOB > 0) {
524
525 memcpy(&pbuf->value, (u8 *) & resp->params.rdeeprom.value,
526 le16_to_cpu(resp->params.rdeeprom.bytecount));
Holger Schuriga6c87002007-08-02 11:54:10 -0400527 lbs_deb_hex(LBS_DEB_CMD, "EEPROM", (char *)&pbuf->value,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200528 le16_to_cpu(resp->params.rdeeprom.bytecount));
529 }
Holger Schuriga6c87002007-08-02 11:54:10 -0400530 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200531 return 0;
532}
533
534static int wlan_ret_get_log(wlan_private * priv,
535 struct cmd_ds_command *resp)
536{
David Woodhouse981f1872007-05-25 23:36:54 -0400537 struct cmd_ds_802_11_get_log *logmessage = &resp->params.glog;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200538 wlan_adapter *adapter = priv->adapter;
539
Holger Schurig9012b282007-05-25 11:27:16 -0400540 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200541
David Woodhouse981f1872007-05-25 23:36:54 -0400542 /* Stored little-endian */
543 memcpy(&adapter->logmsg, logmessage, sizeof(struct cmd_ds_802_11_get_log));
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200544
Holger Schuriga6c87002007-08-02 11:54:10 -0400545 lbs_deb_leave(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200546 return 0;
547}
548
Dan Williams18c96c342007-06-18 12:01:12 -0400549static int libertas_ret_802_11_enable_rsn(wlan_private * priv,
550 struct cmd_ds_command *resp)
551{
552 struct cmd_ds_802_11_enable_rsn *enable_rsn = &resp->params.enbrsn;
553 wlan_adapter *adapter = priv->adapter;
554 u32 * pdata_buf = adapter->cur_cmd->pdata_buf;
555
556 lbs_deb_enter(LBS_DEB_CMD);
557
Dan Williams0aef64d2007-08-02 11:31:18 -0400558 if (enable_rsn->action == cpu_to_le16(CMD_ACT_GET)) {
Dan Williams18c96c342007-06-18 12:01:12 -0400559 if (pdata_buf)
560 *pdata_buf = (u32) le16_to_cpu(enable_rsn->enable);
561 }
562
Holger Schuriga6c87002007-08-02 11:54:10 -0400563 lbs_deb_leave(LBS_DEB_CMD);
Dan Williams18c96c342007-06-18 12:01:12 -0400564 return 0;
565}
566
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200567static inline int handle_cmd_response(u16 respcmd,
568 struct cmd_ds_command *resp,
569 wlan_private *priv)
570{
571 int ret = 0;
572 unsigned long flags;
573 wlan_adapter *adapter = priv->adapter;
574
Holger Schuriga6c87002007-08-02 11:54:10 -0400575 lbs_deb_enter(LBS_DEB_HOST);
576
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200577 switch (respcmd) {
Holger Schurig6b63cd02007-08-02 11:53:36 -0400578 case CMD_RET(CMD_MAC_REG_ACCESS):
579 case CMD_RET(CMD_BBP_REG_ACCESS):
580 case CMD_RET(CMD_RF_REG_ACCESS):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200581 ret = wlan_ret_reg_access(priv, respcmd, resp);
582 break;
583
Holger Schurig6b63cd02007-08-02 11:53:36 -0400584 case CMD_RET(CMD_GET_HW_SPEC):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200585 ret = wlan_ret_get_hw_spec(priv, resp);
586 break;
587
Holger Schurig6b63cd02007-08-02 11:53:36 -0400588 case CMD_RET(CMD_802_11_SCAN):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200589 ret = libertas_ret_80211_scan(priv, resp);
590 break;
591
Holger Schurig6b63cd02007-08-02 11:53:36 -0400592 case CMD_RET(CMD_802_11_GET_LOG):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200593 ret = wlan_ret_get_log(priv, resp);
594 break;
595
Dan Williams0aef64d2007-08-02 11:31:18 -0400596 case CMD_RET_802_11_ASSOCIATE:
Holger Schurig6b63cd02007-08-02 11:53:36 -0400597 case CMD_RET(CMD_802_11_ASSOCIATE):
598 case CMD_RET(CMD_802_11_REASSOCIATE):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200599 ret = libertas_ret_80211_associate(priv, resp);
600 break;
601
Holger Schurig6b63cd02007-08-02 11:53:36 -0400602 case CMD_RET(CMD_802_11_DISASSOCIATE):
603 case CMD_RET(CMD_802_11_DEAUTHENTICATE):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200604 ret = libertas_ret_80211_disassociate(priv, resp);
605 break;
606
Holger Schurig6b63cd02007-08-02 11:53:36 -0400607 case CMD_RET(CMD_802_11_AD_HOC_START):
608 case CMD_RET(CMD_802_11_AD_HOC_JOIN):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200609 ret = libertas_ret_80211_ad_hoc_start(priv, resp);
610 break;
611
Holger Schurig6b63cd02007-08-02 11:53:36 -0400612 case CMD_RET(CMD_802_11_GET_STAT):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200613 ret = wlan_ret_802_11_stat(priv, resp);
614 break;
615
Holger Schurig6b63cd02007-08-02 11:53:36 -0400616 case CMD_RET(CMD_802_11_SNMP_MIB):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200617 ret = wlan_ret_802_11_snmp_mib(priv, resp);
618 break;
619
Holger Schurig6b63cd02007-08-02 11:53:36 -0400620 case CMD_RET(CMD_802_11_RF_TX_POWER):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200621 ret = wlan_ret_802_11_rf_tx_power(priv, resp);
622 break;
623
Holger Schurig6b63cd02007-08-02 11:53:36 -0400624 case CMD_RET(CMD_802_11_SET_AFC):
625 case CMD_RET(CMD_802_11_GET_AFC):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200626 spin_lock_irqsave(&adapter->driver_lock, flags);
David Woodhouse981f1872007-05-25 23:36:54 -0400627 memmove(adapter->cur_cmd->pdata_buf, &resp->params.afc,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200628 sizeof(struct cmd_ds_802_11_afc));
629 spin_unlock_irqrestore(&adapter->driver_lock, flags);
630
631 break;
Holger Schurig6b63cd02007-08-02 11:53:36 -0400632 case CMD_RET(CMD_802_11_RF_ANTENNA):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200633 ret = wlan_ret_802_11_rf_antenna(priv, resp);
634 break;
635
Holger Schurig6b63cd02007-08-02 11:53:36 -0400636 case CMD_RET(CMD_MAC_MULTICAST_ADR):
637 case CMD_RET(CMD_MAC_CONTROL):
638 case CMD_RET(CMD_802_11_SET_WEP):
639 case CMD_RET(CMD_802_11_RESET):
640 case CMD_RET(CMD_802_11_AUTHENTICATE):
641 case CMD_RET(CMD_802_11_RADIO_CONTROL):
642 case CMD_RET(CMD_802_11_BEACON_STOP):
Dan Williams18c96c342007-06-18 12:01:12 -0400643 break;
644
Holger Schurig6b63cd02007-08-02 11:53:36 -0400645 case CMD_RET(CMD_802_11_ENABLE_RSN):
Dan Williams18c96c342007-06-18 12:01:12 -0400646 ret = libertas_ret_802_11_enable_rsn(priv, resp);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200647 break;
648
Holger Schurig6b63cd02007-08-02 11:53:36 -0400649 case CMD_RET(CMD_802_11_DATA_RATE):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200650 ret = wlan_ret_802_11_data_rate(priv, resp);
651 break;
Holger Schurig6b63cd02007-08-02 11:53:36 -0400652 case CMD_RET(CMD_802_11_RATE_ADAPT_RATESET):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200653 ret = wlan_ret_802_11_rate_adapt_rateset(priv, resp);
654 break;
Holger Schurig6b63cd02007-08-02 11:53:36 -0400655 case CMD_RET(CMD_802_11_RF_CHANNEL):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200656 ret = wlan_ret_802_11_rf_channel(priv, resp);
657 break;
658
Holger Schurig6b63cd02007-08-02 11:53:36 -0400659 case CMD_RET(CMD_802_11_RSSI):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200660 ret = wlan_ret_802_11_rssi(priv, resp);
661 break;
662
Holger Schurig6b63cd02007-08-02 11:53:36 -0400663 case CMD_RET(CMD_802_11_MAC_ADDRESS):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200664 ret = wlan_ret_802_11_mac_address(priv, resp);
665 break;
666
Holger Schurig6b63cd02007-08-02 11:53:36 -0400667 case CMD_RET(CMD_802_11_AD_HOC_STOP):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200668 ret = libertas_ret_80211_ad_hoc_stop(priv, resp);
669 break;
670
Holger Schurig6b63cd02007-08-02 11:53:36 -0400671 case CMD_RET(CMD_802_11_KEY_MATERIAL):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200672 ret = wlan_ret_802_11_key_material(priv, resp);
673 break;
674
Holger Schurig6b63cd02007-08-02 11:53:36 -0400675 case CMD_RET(CMD_802_11_EEPROM_ACCESS):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200676 ret = wlan_ret_802_11_eeprom_access(priv, resp);
677 break;
678
Holger Schurig6b63cd02007-08-02 11:53:36 -0400679 case CMD_RET(CMD_802_11D_DOMAIN_INFO):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200680 ret = libertas_ret_802_11d_domain_info(priv, resp);
681 break;
682
Holger Schurig6b63cd02007-08-02 11:53:36 -0400683 case CMD_RET(CMD_802_11_SLEEP_PARAMS):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200684 ret = wlan_ret_802_11_sleep_params(priv, resp);
685 break;
Holger Schurig6b63cd02007-08-02 11:53:36 -0400686 case CMD_RET(CMD_802_11_INACTIVITY_TIMEOUT):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200687 spin_lock_irqsave(&adapter->driver_lock, flags);
688 *((u16 *) adapter->cur_cmd->pdata_buf) =
689 le16_to_cpu(resp->params.inactivity_timeout.timeout);
690 spin_unlock_irqrestore(&adapter->driver_lock, flags);
691 break;
692
Holger Schurig6b63cd02007-08-02 11:53:36 -0400693 case CMD_RET(CMD_802_11_TPC_CFG):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200694 spin_lock_irqsave(&adapter->driver_lock, flags);
David Woodhouse981f1872007-05-25 23:36:54 -0400695 memmove(adapter->cur_cmd->pdata_buf, &resp->params.tpccfg,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200696 sizeof(struct cmd_ds_802_11_tpc_cfg));
697 spin_unlock_irqrestore(&adapter->driver_lock, flags);
698 break;
Holger Schurig6b63cd02007-08-02 11:53:36 -0400699 case CMD_RET(CMD_802_11_LED_GPIO_CTRL):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200700 spin_lock_irqsave(&adapter->driver_lock, flags);
David Woodhouse981f1872007-05-25 23:36:54 -0400701 memmove(adapter->cur_cmd->pdata_buf, &resp->params.ledgpio,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200702 sizeof(struct cmd_ds_802_11_led_ctrl));
703 spin_unlock_irqrestore(&adapter->driver_lock, flags);
704 break;
Holger Schurig6b63cd02007-08-02 11:53:36 -0400705 case CMD_RET(CMD_802_11_PWR_CFG):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200706 spin_lock_irqsave(&adapter->driver_lock, flags);
David Woodhouse981f1872007-05-25 23:36:54 -0400707 memmove(adapter->cur_cmd->pdata_buf, &resp->params.pwrcfg,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200708 sizeof(struct cmd_ds_802_11_pwr_cfg));
709 spin_unlock_irqrestore(&adapter->driver_lock, flags);
710
711 break;
712
Holger Schurig6b63cd02007-08-02 11:53:36 -0400713 case CMD_RET(CMD_GET_TSF):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200714 spin_lock_irqsave(&adapter->driver_lock, flags);
715 memcpy(priv->adapter->cur_cmd->pdata_buf,
716 &resp->params.gettsf.tsfvalue, sizeof(u64));
717 spin_unlock_irqrestore(&adapter->driver_lock, flags);
718 break;
Holger Schurig6b63cd02007-08-02 11:53:36 -0400719 case CMD_RET(CMD_BT_ACCESS):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200720 spin_lock_irqsave(&adapter->driver_lock, flags);
721 if (adapter->cur_cmd->pdata_buf)
722 memcpy(adapter->cur_cmd->pdata_buf,
723 &resp->params.bt.addr1, 2 * ETH_ALEN);
724 spin_unlock_irqrestore(&adapter->driver_lock, flags);
725 break;
Holger Schurig6b63cd02007-08-02 11:53:36 -0400726 case CMD_RET(CMD_FWT_ACCESS):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200727 spin_lock_irqsave(&adapter->driver_lock, flags);
728 if (adapter->cur_cmd->pdata_buf)
David Woodhouse981f1872007-05-25 23:36:54 -0400729 memcpy(adapter->cur_cmd->pdata_buf, &resp->params.fwt,
730 sizeof(resp->params.fwt));
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200731 spin_unlock_irqrestore(&adapter->driver_lock, flags);
732 break;
Holger Schurig6b63cd02007-08-02 11:53:36 -0400733 case CMD_RET(CMD_MESH_ACCESS):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200734 if (adapter->cur_cmd->pdata_buf)
David Woodhouse981f1872007-05-25 23:36:54 -0400735 memcpy(adapter->cur_cmd->pdata_buf, &resp->params.mesh,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200736 sizeof(resp->params.mesh));
737 break;
Holger Schurig6b63cd02007-08-02 11:53:36 -0400738 case CMD_RET(CMD_802_11_TX_RATE_QUERY):
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200739 priv->adapter->txrate = resp->params.txrate.txrate;
740 break;
741 default:
Holger Schuriga6c87002007-08-02 11:54:10 -0400742 lbs_deb_host("CMD_RESP: unknown cmd response 0x%04x\n",
David Woodhouse981f1872007-05-25 23:36:54 -0400743 resp->command);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200744 break;
745 }
Holger Schuriga6c87002007-08-02 11:54:10 -0400746 lbs_deb_leave(LBS_DEB_HOST);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200747 return ret;
748}
749
750int libertas_process_rx_command(wlan_private * priv)
751{
752 u16 respcmd;
753 struct cmd_ds_command *resp;
754 wlan_adapter *adapter = priv->adapter;
755 int ret = 0;
756 ulong flags;
757 u16 result;
758
Holger Schuriga6c87002007-08-02 11:54:10 -0400759 lbs_deb_enter(LBS_DEB_HOST);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200760
761 /* Now we got response from FW, cancel the command timer */
762 del_timer(&adapter->command_timer);
763
764 mutex_lock(&adapter->lock);
765 spin_lock_irqsave(&adapter->driver_lock, flags);
766
767 if (!adapter->cur_cmd) {
Holger Schuriga6c87002007-08-02 11:54:10 -0400768 lbs_deb_host("CMD_RESP: cur_cmd is NULL\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200769 ret = -1;
770 spin_unlock_irqrestore(&adapter->driver_lock, flags);
771 goto done;
772 }
773 resp = (struct cmd_ds_command *)(adapter->cur_cmd->bufvirtualaddr);
774
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200775 respcmd = le16_to_cpu(resp->command);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200776 result = le16_to_cpu(resp->result);
777
Holger Schuriga6c87002007-08-02 11:54:10 -0400778 lbs_deb_host("CMD_RESP: response 0x%04x, size %d, jiffies %lu\n",
779 respcmd, priv->upld_len, jiffies);
780 lbs_deb_hex(LBS_DEB_HOST, "CMD_RESP", adapter->cur_cmd->bufvirtualaddr,
781 priv->upld_len);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200782
783 if (!(respcmd & 0x8000)) {
Holger Schuriga6c87002007-08-02 11:54:10 -0400784 lbs_deb_host("invalid response!\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200785 adapter->cur_cmd_retcode = -1;
786 __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
787 adapter->nr_cmd_pending--;
788 adapter->cur_cmd = NULL;
789 spin_unlock_irqrestore(&adapter->driver_lock, flags);
790 ret = -1;
791 goto done;
792 }
793
794 /* Store the response code to cur_cmd_retcode. */
David Woodhouse981f1872007-05-25 23:36:54 -0400795 adapter->cur_cmd_retcode = result;;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200796
Holger Schurig6b63cd02007-08-02 11:53:36 -0400797 if (respcmd == CMD_RET(CMD_802_11_PS_MODE)) {
David Woodhouse981f1872007-05-25 23:36:54 -0400798 struct cmd_ds_802_11_ps_mode *psmode = &resp->params.psmode;
799 u16 action = le16_to_cpu(psmode->action);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200800
Holger Schuriga6c87002007-08-02 11:54:10 -0400801 lbs_deb_host(
802 "CMD_RESP: PS_MODE cmd reply result 0x%x, action 0x%x\n",
David Woodhouse981f1872007-05-25 23:36:54 -0400803 result, action);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200804
805 if (result) {
Holger Schuriga6c87002007-08-02 11:54:10 -0400806 lbs_deb_host("CMD_RESP: PS command failed with 0x%x\n",
David Woodhouse981f1872007-05-25 23:36:54 -0400807 result);
808 /*
809 * We should not re-try enter-ps command in
810 * ad-hoc mode. It takes place in
811 * libertas_execute_next_command().
812 */
813 if (adapter->mode == IW_MODE_ADHOC &&
Dan Williams0aef64d2007-08-02 11:31:18 -0400814 action == CMD_SUBCMD_ENTER_PS)
815 adapter->psmode = WLAN802_11POWERMODECAM;
816 } else if (action == CMD_SUBCMD_ENTER_PS) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200817 adapter->needtowakeup = 0;
818 adapter->psstate = PS_STATE_AWAKE;
819
Holger Schuriga6c87002007-08-02 11:54:10 -0400820 lbs_deb_host("CMD_RESP: ENTER_PS command response\n");
Dan Williams0aef64d2007-08-02 11:31:18 -0400821 if (adapter->connect_status != LIBERTAS_CONNECTED) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200822 /*
823 * When Deauth Event received before Enter_PS command
824 * response, We need to wake up the firmware.
825 */
Holger Schuriga6c87002007-08-02 11:54:10 -0400826 lbs_deb_host(
827 "disconnected, invoking libertas_ps_wakeup\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200828
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200829 spin_unlock_irqrestore(&adapter->driver_lock, flags);
Dan Williams6cfb0082007-05-25 17:33:28 -0400830 mutex_unlock(&adapter->lock);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200831 libertas_ps_wakeup(priv, 0);
832 mutex_lock(&adapter->lock);
833 spin_lock_irqsave(&adapter->driver_lock, flags);
834 }
Dan Williams0aef64d2007-08-02 11:31:18 -0400835 } else if (action == CMD_SUBCMD_EXIT_PS) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200836 adapter->needtowakeup = 0;
837 adapter->psstate = PS_STATE_FULL_POWER;
Holger Schuriga6c87002007-08-02 11:54:10 -0400838 lbs_deb_host("CMD_RESP: EXIT_PS command response\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200839 } else {
Holger Schuriga6c87002007-08-02 11:54:10 -0400840 lbs_deb_host("CMD_RESP: PS action 0x%X\n", action);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200841 }
842
843 __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
844 adapter->nr_cmd_pending--;
845 adapter->cur_cmd = NULL;
846 spin_unlock_irqrestore(&adapter->driver_lock, flags);
847
848 ret = 0;
849 goto done;
850 }
851
852 if (adapter->cur_cmd->cmdflags & CMD_F_HOSTCMD) {
853 /* Copy the response back to response buffer */
854 memcpy(adapter->cur_cmd->pdata_buf, resp, resp->size);
855
856 adapter->cur_cmd->cmdflags &= ~CMD_F_HOSTCMD;
857 }
858
859 /* If the command is not successful, cleanup and return failure */
860 if ((result != 0 || !(respcmd & 0x8000))) {
Holger Schuriga6c87002007-08-02 11:54:10 -0400861 lbs_deb_host("CMD_RESP: error 0x%04x in command reply 0x%04x\n",
862 result, respcmd);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200863 /*
864 * Handling errors here
865 */
866 switch (respcmd) {
Holger Schurig6b63cd02007-08-02 11:53:36 -0400867 case CMD_RET(CMD_GET_HW_SPEC):
868 case CMD_RET(CMD_802_11_RESET):
Holger Schuriga6c87002007-08-02 11:54:10 -0400869 lbs_deb_host("CMD_RESP: reset failed\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200870 break;
871
872 }
873
874 __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
875 adapter->nr_cmd_pending--;
876 adapter->cur_cmd = NULL;
877 spin_unlock_irqrestore(&adapter->driver_lock, flags);
878
879 ret = -1;
880 goto done;
881 }
882
883 spin_unlock_irqrestore(&adapter->driver_lock, flags);
884
885 ret = handle_cmd_response(respcmd, resp, priv);
886
887 spin_lock_irqsave(&adapter->driver_lock, flags);
888 if (adapter->cur_cmd) {
889 /* Clean up and Put current command back to cmdfreeq */
890 __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
891 adapter->nr_cmd_pending--;
892 WARN_ON(adapter->nr_cmd_pending > 128);
893 adapter->cur_cmd = NULL;
894 }
895 spin_unlock_irqrestore(&adapter->driver_lock, flags);
896
897done:
898 mutex_unlock(&adapter->lock);
Holger Schuriga6c87002007-08-02 11:54:10 -0400899 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200900 return ret;
901}
902
903int libertas_process_event(wlan_private * priv)
904{
905 int ret = 0;
906 wlan_adapter *adapter = priv->adapter;
907 u32 eventcause;
908
909 spin_lock_irq(&adapter->driver_lock);
910 eventcause = adapter->eventcause;
911 spin_unlock_irq(&adapter->driver_lock);
912
Holger Schurig9012b282007-05-25 11:27:16 -0400913 lbs_deb_enter(LBS_DEB_CMD);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200914
Holger Schuriga6c87002007-08-02 11:54:10 -0400915 lbs_deb_cmd("event cause 0x%x\n", eventcause);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200916
917 switch (eventcause >> SBI_EVENT_CAUSE_SHIFT) {
918 case MACREG_INT_CODE_LINK_SENSED:
Holger Schurig9012b282007-05-25 11:27:16 -0400919 lbs_deb_cmd("EVENT: MACREG_INT_CODE_LINK_SENSED\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200920 break;
921
922 case MACREG_INT_CODE_DEAUTHENTICATED:
Holger Schuriga6c87002007-08-02 11:54:10 -0400923 lbs_deb_cmd("EVENT: deauthenticated\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200924 libertas_mac_event_disconnected(priv);
925 break;
926
927 case MACREG_INT_CODE_DISASSOCIATED:
Holger Schuriga6c87002007-08-02 11:54:10 -0400928 lbs_deb_cmd("EVENT: disassociated\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200929 libertas_mac_event_disconnected(priv);
930 break;
931
932 case MACREG_INT_CODE_LINK_LOSE_NO_SCAN:
Holger Schuriga6c87002007-08-02 11:54:10 -0400933 lbs_deb_cmd("EVENT: link lost\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200934 libertas_mac_event_disconnected(priv);
935 break;
936
937 case MACREG_INT_CODE_PS_SLEEP:
Holger Schuriga6c87002007-08-02 11:54:10 -0400938 lbs_deb_cmd("EVENT: sleep\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200939
940 /* handle unexpected PS SLEEP event */
941 if (adapter->psstate == PS_STATE_FULL_POWER) {
Holger Schurig9012b282007-05-25 11:27:16 -0400942 lbs_deb_cmd(
Holger Schuriga6c87002007-08-02 11:54:10 -0400943 "EVENT: in FULL POWER mode, ignoreing PS_SLEEP\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200944 break;
945 }
946 adapter->psstate = PS_STATE_PRE_SLEEP;
947
948 libertas_ps_confirm_sleep(priv, (u16) adapter->psmode);
949
950 break;
951
952 case MACREG_INT_CODE_PS_AWAKE:
Holger Schuriga6c87002007-08-02 11:54:10 -0400953 lbs_deb_cmd("EVENT: awake\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200954
955 /* handle unexpected PS AWAKE event */
956 if (adapter->psstate == PS_STATE_FULL_POWER) {
Holger Schurig9012b282007-05-25 11:27:16 -0400957 lbs_deb_cmd(
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200958 "EVENT: In FULL POWER mode - ignore PS AWAKE\n");
959 break;
960 }
961
962 adapter->psstate = PS_STATE_AWAKE;
963
964 if (adapter->needtowakeup) {
965 /*
966 * wait for the command processing to finish
967 * before resuming sending
968 * adapter->needtowakeup will be set to FALSE
969 * in libertas_ps_wakeup()
970 */
Holger Schuriga6c87002007-08-02 11:54:10 -0400971 lbs_deb_cmd("waking up ...\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200972 libertas_ps_wakeup(priv, 0);
973 }
974 break;
975
976 case MACREG_INT_CODE_MIC_ERR_UNICAST:
Holger Schurig9012b282007-05-25 11:27:16 -0400977 lbs_deb_cmd("EVENT: UNICAST MIC ERROR\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200978 handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_UNICAST);
979 break;
980
981 case MACREG_INT_CODE_MIC_ERR_MULTICAST:
Holger Schurig9012b282007-05-25 11:27:16 -0400982 lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200983 handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_MULTICAST);
984 break;
985 case MACREG_INT_CODE_MIB_CHANGED:
986 case MACREG_INT_CODE_INIT_DONE:
987 break;
988
989 case MACREG_INT_CODE_ADHOC_BCN_LOST:
Holger Schuriga6c87002007-08-02 11:54:10 -0400990 lbs_deb_cmd("EVENT: ADHOC beacon lost\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200991 break;
992
993 case MACREG_INT_CODE_RSSI_LOW:
Holger Schuriga6c87002007-08-02 11:54:10 -0400994 lbs_pr_alert("EVENT: rssi low\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200995 break;
996 case MACREG_INT_CODE_SNR_LOW:
Holger Schuriga6c87002007-08-02 11:54:10 -0400997 lbs_pr_alert("EVENT: snr low\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200998 break;
999 case MACREG_INT_CODE_MAX_FAIL:
Holger Schuriga6c87002007-08-02 11:54:10 -04001000 lbs_pr_alert("EVENT: max fail\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001001 break;
1002 case MACREG_INT_CODE_RSSI_HIGH:
Holger Schuriga6c87002007-08-02 11:54:10 -04001003 lbs_pr_alert("EVENT: rssi high\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001004 break;
1005 case MACREG_INT_CODE_SNR_HIGH:
Holger Schuriga6c87002007-08-02 11:54:10 -04001006 lbs_pr_alert("EVENT: snr high\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001007 break;
1008
Luis Carlos Cobo Rus7d8d28b2007-05-25 23:12:19 -04001009 case MACREG_INT_CODE_MESH_AUTO_STARTED:
Luis Carlos Cobo9cdc6d22007-08-02 11:55:22 -04001010 lbs_pr_info("EVENT: MESH_AUTO_STARTED\n");
1011 adapter->connect_status = LIBERTAS_CONNECTED;
Luis Carlos Cobo Rus7d8d28b2007-05-25 23:12:19 -04001012 if (priv->mesh_open == 1) {
Luis Carlos Cobo9cdc6d22007-08-02 11:55:22 -04001013 netif_wake_queue(priv->mesh_dev);
1014 netif_carrier_on(priv->mesh_dev);
Luis Carlos Cobo Rus7d8d28b2007-05-25 23:12:19 -04001015 }
Luis Carlos Cobo9cdc6d22007-08-02 11:55:22 -04001016 adapter->mode = IW_MODE_ADHOC;
Luis Carlos Cobo Rusb8bedef2007-05-30 12:14:34 -04001017 schedule_work(&priv->sync_channel);
Luis Carlos Cobo Rus7d8d28b2007-05-25 23:12:19 -04001018 break;
1019
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001020 default:
Holger Schuriga6c87002007-08-02 11:54:10 -04001021 lbs_pr_alert("EVENT: unknown event id 0x%04x\n",
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001022 eventcause >> SBI_EVENT_CAUSE_SHIFT);
1023 break;
1024 }
1025
1026 spin_lock_irq(&adapter->driver_lock);
1027 adapter->eventcause = 0;
1028 spin_unlock_irq(&adapter->driver_lock);
Holger Schurig9012b282007-05-25 11:27:16 -04001029
1030 lbs_deb_enter_args(LBS_DEB_CMD, "ret %d", ret);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001031 return ret;
1032}