add rga2 drivers for 64bit platform
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / esp8089 / esp_driver / esp_ctrl.c
1 /*
2  * Copyright (c) 2009 - 2014 Espressif System.
3  * 
4  * SIP ctrl packet parse and pack
5  */
6
7 #include <net/mac80211.h>
8 #include <net/cfg80211.h>
9 #include <linux/skbuff.h>
10 #include <linux/bitops.h>
11 #include <linux/firmware.h>
12
13 #include "esp_pub.h"
14 #include "esp_sip.h"
15 #include "esp_ctrl.h"
16 #include "esp_sif.h"
17 #include "esp_debug.h"
18 #include "esp_wmac.h"
19 #include "esp_utils.h"
20 #include "esp_wl.h"
21 #include "esp_file.h"
22 #include "esp_path.h"
23 #ifdef TEST_MODE
24 #include "testmode.h"
25 #endif /* TEST_MODE */
26 #include "esp_version.h"
27
28 extern struct completion *gl_bootup_cplx; 
29
30 static void esp_tx_ba_session_op(struct esp_sip *sip, struct esp_node *node, trc_ampdu_state_t state, u8 tid )
31 {
32         struct esp_tx_tid *txtid;
33
34         txtid = &node->tid[tid];
35         if (state == TRC_TX_AMPDU_STOPPED) {
36                 if (txtid->state == ESP_TID_STATE_OPERATIONAL) {
37                         esp_dbg(ESP_DBG_TXAMPDU, "%s tid %d TXAMPDU GOT STOP EVT\n", __func__, tid);
38
39                         spin_lock_bh(&sip->epub->tx_ampdu_lock);
40                         txtid->state = ESP_TID_STATE_WAIT_STOP;
41                         spin_unlock_bh(&sip->epub->tx_ampdu_lock);
42 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
43                         ieee80211_stop_tx_ba_session(sip->epub->hw, node->addr, (u16)tid, WLAN_BACK_INITIATOR);
44 #elif (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32))
45                         ieee80211_stop_tx_ba_session(sip->epub->hw, node->sta->addr, (u16)tid, WLAN_BACK_INITIATOR);
46 #elif (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
47                         ieee80211_stop_tx_ba_session(node->sta, (u16)tid, WLAN_BACK_INITIATOR);
48 #else
49                         ieee80211_stop_tx_ba_session(node->sta, (u16)tid);
50 #endif /* KERNEL_VERSION 2.6.39 */
51                 } else {
52                         esp_dbg(ESP_DBG_TXAMPDU, "%s tid %d TXAMPDU GOT STOP EVT IN WRONG STATE %d\n", __func__, tid, txtid->state);
53                 }
54         } else if (state == TRC_TX_AMPDU_OPERATIONAL) {
55                 if (txtid->state == ESP_TID_STATE_STOP) {
56                         esp_dbg(ESP_DBG_TXAMPDU, "%s tid %d TXAMPDU GOT OPERATIONAL\n", __func__, tid);
57
58                         spin_lock_bh(&sip->epub->tx_ampdu_lock);
59                         txtid->state = ESP_TID_STATE_TRIGGER;
60                         spin_unlock_bh(&sip->epub->tx_ampdu_lock);
61 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
62                         ieee80211_start_tx_ba_session(sip->epub->hw, node->addr, tid);
63 #elif (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32))
64                         ieee80211_start_tx_ba_session(sip->epub->hw, node->sta->addr, tid);
65 #elif (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 37))
66                         ieee80211_start_tx_ba_session(node->sta, (u16)tid);
67 #else
68                         ieee80211_start_tx_ba_session(node->sta, (u16)tid, 0);
69 #endif /* KERNEL_VERSION 2.6.39 */
70
71                 } else if(txtid->state == ESP_TID_STATE_OPERATIONAL) {
72 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
73                         sip_send_ampdu_action(sip->epub, SIP_AMPDU_TX_OPERATIONAL, node->addr, tid, node->ifidx, 0);
74 #else
75                         sip_send_ampdu_action(sip->epub, SIP_AMPDU_TX_OPERATIONAL, node->sta->addr, tid, node->ifidx, 0);
76 #endif
77                 } else {
78                         esp_dbg(ESP_DBG_TXAMPDU, "%s tid %d TXAMPDU GOT OPERATIONAL EVT IN WRONG STATE %d\n", __func__, tid, txtid->state);
79                 }
80         }
81 }
82
83 int sip_parse_event_debug(struct esp_pub *epub, const u8 *src, u8 *dst)
84 {
85         struct sip_evt_debug* debug_evt =  (struct sip_evt_debug *)(src + SIP_CTRL_HDR_LEN);
86
87         switch (debug_evt->results[0]) {
88                 case RDRSSI: {
89                         u32 mask = debug_evt->results[1];
90                         u8 *p = (u8 *)&debug_evt->results[2];
91                         u8 index;
92                         struct esp_node *enode;
93
94                         while (mask != 0) {
95                                 index = ffs(mask) - 1;
96                                 if (index >= ESP_PUB_MAX_STA)
97                                         break;
98                                 enode = esp_get_node_by_index(epub, index);
99                                 if (enode == NULL) {
100                                         esp_dbg(ESP_DBG_ERROR, "trc mask dismatch");
101                                 } else {
102                                         dst += sprintf(dst, "%02x:%02x:%02x:%02x:%02x:%02x 0x%x 0x%x\n", 
103 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
104                                                 enode->sta->addr[0], enode->sta->addr[1], enode->sta->addr[2],
105                                                 enode->sta->addr[3], enode->sta->addr[4], enode->sta->addr[5],
106 #else
107                                                 enode->addr[0], enode->addr[1], enode->addr[2],
108                                                 enode->addr[3], enode->addr[4], enode->addr[5],
109 #endif
110                                                 *p, *(p+1));
111                                                 p += 2;
112                                 }
113                                 mask &= ~(1<<index);
114                         };
115                         dst += sprintf(dst, "%c", '\0');
116                                         break;
117                 }
118                 default: {
119                         int i;
120                         for(i = 1; i < debug_evt->len; i++)
121                                 dst += sprintf(dst, "0x%x%s", debug_evt->results[i], i == debug_evt->len -1 ? "":" " );
122                         break;
123                 }
124         }
125
126         return 0;
127 }
128
129 int sip_parse_events(struct esp_sip *sip, u8 *buf)
130 {
131         struct sip_hdr *hdr = (struct sip_hdr *)buf;
132
133         switch (hdr->c_evtid) {
134         case SIP_EVT_TARGET_ON: {
135                 /* use rx work queue to send... */
136                 if (atomic_read(&sip->state) == SIP_PREPARE_BOOT || atomic_read(&sip->state) == SIP_BOOT) {
137                         atomic_set(&sip->state, SIP_SEND_INIT);
138                         queue_work(sip->epub->esp_wkq, &sip->rx_process_work);
139                 } else {
140                         esp_dbg(ESP_DBG_ERROR, "%s boot during wrong state %d\n", __func__, atomic_read(&sip->state));
141                 }
142                 break;
143         }
144
145         case SIP_EVT_BOOTUP: {
146                 struct sip_evt_bootup2 *bootup_evt = (struct sip_evt_bootup2 *)(buf + SIP_CTRL_HDR_LEN);
147                 if (sip->rawbuf)
148                         kfree(sip->rawbuf);
149                 
150                 sip_post_init(sip, bootup_evt);
151                 
152                 if (gl_bootup_cplx)     
153                         complete(gl_bootup_cplx);
154                 
155                 break;
156         }
157         case SIP_EVT_RESETTING:{
158                 sip->epub->wait_reset = 1;                       
159                 if (gl_bootup_cplx)     
160                         complete(gl_bootup_cplx);
161                 break;
162         }
163         case SIP_EVT_SLEEP:{
164                 //atomic_set(&sip->epub->ps.state, ESP_PM_ON);
165                 break;
166         }
167         case SIP_EVT_TXIDLE:{
168                 //struct sip_evt_txidle *txidle = (struct sip_evt_txidle *)(buf + SIP_CTRL_HDR_LEN);
169                 //sip_txdone_clear(sip, txidle->last_seq);
170                 break;
171         }
172 #ifndef FAST_TX_STATUS
173         case SIP_EVT_TX_STATUS: {
174                 struct sip_evt_tx_report *report = (struct sip_evt_tx_report *)(buf + SIP_CTRL_HDR_LEN);
175                 sip_txdoneq_process(sip, report);
176
177                 break;
178         }
179 #endif /* FAST_TX_STATUS */
180
181         case SIP_EVT_SCAN_RESULT: {
182                 struct sip_evt_scan_report *report = (struct sip_evt_scan_report *)(buf + SIP_CTRL_HDR_LEN);
183                 if (atomic_read(&sip->epub->wl.off)) {
184                         esp_dbg(ESP_DBG_ERROR, "%s scan result while wlan off\n", __func__);
185                         return 0;
186                 }
187                 sip_scandone_process(sip, report);
188
189                 break;
190         }
191
192         case SIP_EVT_ROC: {
193                 struct sip_evt_roc* report = (struct sip_evt_roc *)(buf + SIP_CTRL_HDR_LEN);
194                 esp_rocdone_process(sip->epub->hw, report);
195                 break;
196         }
197
198
199 #ifdef ESP_RX_COPYBACK_TEST
200
201         case SIP_EVT_COPYBACK: {
202                 u32 len = hdr->len - SIP_CTRL_HDR_LEN;
203
204                 esp_dbg(ESP_DBG_TRACE, "%s copyback len %d   seq %u\n", __func__, len, hdr->seq);
205
206                 memcpy(copyback_buf + copyback_offset, pkt->buf + SIP_CTRL_HDR_LEN, len);
207                 copyback_offset += len;
208
209                 //show_buf(pkt->buf, 256);
210
211                 //how about totlen % 256 == 0??
212                 if (hdr->hdr.len < 256) {
213                         kfree(copyback_buf);
214                 }
215         }
216         break;
217 #endif /* ESP_RX_COPYBACK_TEST */
218         case SIP_EVT_CREDIT_RPT:
219                 break;
220
221 #ifdef TEST_MODE
222         case SIP_EVT_WAKEUP: {
223                 u8 check_str[12];
224                 struct sip_evt_wakeup* wakeup_evt=  (struct sip_evt_wakeup *)(buf + SIP_CTRL_HDR_LEN);
225                 sprintf((char *)&check_str, "%d", wakeup_evt->check_data);
226                 esp_test_cmd_event(TEST_CMD_WAKEUP, (char *)&check_str);
227                 break;
228         }
229
230         case SIP_EVT_DEBUG: {
231                 u8 check_str[640];
232                 sip_parse_event_debug(sip->epub, buf, check_str);
233                 esp_dbg(ESP_DBG_TRACE, "%s", check_str);
234                 esp_test_cmd_event(TEST_CMD_DEBUG, (char *)&check_str);
235                 break;
236         }
237
238         case SIP_EVT_LOOPBACK: {
239                 u8 check_str[12];
240                 struct sip_evt_loopback *loopback_evt = (struct sip_evt_loopback *)(buf + SIP_CTRL_HDR_LEN);
241                 esp_dbg(ESP_DBG_LOG, "%s loopback len %d seq %u\n", __func__,hdr->len, hdr->seq);
242
243                 if(loopback_evt->pack_id!=get_loopback_id()) {
244                         sprintf((char *)&check_str, "seq id error %d, expect %d", loopback_evt->pack_id, get_loopback_id());
245                         esp_test_cmd_event(TEST_CMD_LOOPBACK, (char *)&check_str);
246                 }
247
248                 if((loopback_evt->pack_id+1) <get_loopback_num()) {
249                         inc_loopback_id();
250                         sip_send_loopback_mblk(sip, loopback_evt->txlen, loopback_evt->rxlen, get_loopback_id());
251                 } else {
252                         sprintf((char *)&check_str, "test over!");
253                         esp_test_cmd_event(TEST_CMD_LOOPBACK, (char *)&check_str);
254                 }
255                 break;
256         }
257 #endif  /*TEST_MODE*/
258
259         case SIP_EVT_SNPRINTF_TO_HOST: {
260                 u8 *p = (buf + sizeof(struct sip_hdr) + sizeof(u16));
261                 u16 *len = (u16 *)(buf + sizeof(struct sip_hdr));
262                 char test_res_str[560];
263                 sprintf(test_res_str, "esp_host:%llx\nesp_target: %.*s", DRIVER_VER, *len, p);
264                 
265                 esp_dbg(ESP_SHOW, "%s\n", test_res_str);
266                 if(*len && sip->epub->sdio_state == ESP_SDIO_STATE_FIRST_INIT){
267                         char filename[256];
268                         if (mod_eagle_path_get() == NULL)
269                                 sprintf(filename, "%s/%s", FWPATH, "test_results");
270                         else
271                                 sprintf(filename, "%s/%s", mod_eagle_path_get(), "test_results");
272                         esp_readwrite_file(filename, NULL, test_res_str, strlen(test_res_str));
273                 }
274                 break;
275         }
276         case SIP_EVT_TRC_AMPDU: {
277                 struct sip_evt_trc_ampdu *ep = (struct sip_evt_trc_ampdu*)(buf + SIP_CTRL_HDR_LEN);
278                 struct esp_node *node = NULL;
279                 int i = 0;
280
281                 if (atomic_read(&sip->epub->wl.off)) {
282                         esp_dbg(ESP_DBG_ERROR, "%s scan result while wlan off\n", __func__);
283                         return 0;
284                 }
285                 
286                 node = esp_get_node_by_addr(sip->epub, ep->addr);
287                 if(node == NULL)
288                         break;
289                 for (i = 0; i < 8; i++) {
290                         if (ep->tid & (1<<i)) {
291                                 esp_tx_ba_session_op(sip, node, ep->state, i);
292                         }
293                 }
294                 break;
295         }
296
297         case SIP_EVT_EP: {
298                 char *ep = (char *)(buf + SIP_CTRL_HDR_LEN);
299                 static int counter = 0;
300
301                 esp_dbg(ESP_ATE, "%s EVT_EP \n\n", __func__);
302                 if (counter++ < 2) {
303                         esp_dbg(ESP_ATE, "ATE: %s \n", ep);
304                 }
305
306                 esp_test_ate_done_cb(ep);
307
308                 break;
309         }
310         case SIP_EVT_INIT_EP: {
311                 char *ep = (char *)(buf + SIP_CTRL_HDR_LEN);
312                 esp_dbg(ESP_ATE, "Phy Init: %s \n", ep);
313                 break;
314         }
315
316         case SIP_EVT_NOISEFLOOR:{
317                 struct sip_evt_noisefloor *ep = (struct sip_evt_noisefloor *)(buf + SIP_CTRL_HDR_LEN);                                        
318                 atomic_set(&sip->noise_floor, ep->noise_floor);
319                 break;
320         }
321         default:
322                 break;
323         }
324
325         return 0;
326 }
327
328 #ifdef HAS_INIT_DATA
329 #include "esp_init_data.h"
330 #else
331 #define ESP_INIT_NAME "esp_init_data.bin"
332 #endif /* HAS_INIT_DATA */
333
334 void sip_send_chip_init(struct esp_sip *sip)
335 {
336         size_t size = 0;
337 #ifndef HAS_INIT_DATA
338         const struct firmware *fw_entry;
339         u8 * esp_init_data = NULL;
340         int ret = 0;
341
342         ret = esp_request_firmware(&fw_entry, ESP_INIT_NAME, sip->epub->dev);
343         
344         if (ret) {
345                 esp_dbg(ESP_DBG_ERROR, "%s =============ERROR! NO INIT DATA!!=================\n", __func__);
346                 return;
347         }
348         esp_init_data = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
349
350         size = fw_entry->size;
351
352         esp_release_firmware(fw_entry);
353
354         if (esp_init_data == NULL) {
355                 esp_dbg(ESP_DBG_ERROR, "%s =============ERROR! NO MEMORY!!=================\n", __func__);
356                 return;
357         }
358 #else
359         size = sizeof(esp_init_data);
360
361 #endif /* !HAS_INIT_DATA */
362
363         fix_init_data(esp_init_data, size);
364
365         atomic_sub(1, &sip->tx_credits);
366         
367         sip_send_cmd(sip, SIP_CMD_INIT, size, (void *)esp_init_data);
368
369 #ifndef HAS_INIT_DATA
370         kfree(esp_init_data);
371 #endif /* !HAS_INIT_DATA */
372 }
373
374 int sip_send_config(struct esp_pub *epub, struct ieee80211_conf * conf)
375 {
376         struct sk_buff *skb = NULL;
377         struct sip_cmd_config *configcmd;
378
379         skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_config) + sizeof(struct sip_hdr), SIP_CMD_CONFIG);
380         if (!skb)
381                 return -EINVAL;
382 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
383         esp_dbg(ESP_DBG_TRACE, "%s config center freq %d\n", __func__, conf->chandef.chan->center_freq);
384 #else
385         esp_dbg(ESP_DBG_TRACE, "%s config center freq %d\n", __func__, conf->channel->center_freq);
386 #endif
387         configcmd = (struct sip_cmd_config *)(skb->data + sizeof(struct sip_hdr));
388 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
389         configcmd->center_freq= conf->chandef.chan->center_freq;
390 #else
391         configcmd->center_freq= conf->channel->center_freq;
392 #endif
393                 configcmd->duration= 0;
394         return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL);
395 }
396
397 int  sip_send_bss_info_update(struct esp_pub *epub, struct esp_vif *evif, u8 *bssid, int assoc)
398 {
399         struct sk_buff *skb = NULL;
400         struct sip_cmd_bss_info_update*bsscmd;
401
402         skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_bss_info_update) + sizeof(struct sip_hdr), SIP_CMD_BSS_INFO_UPDATE);
403         if (!skb)
404                 return -EINVAL;
405
406         bsscmd = (struct sip_cmd_bss_info_update *)(skb->data + sizeof(struct sip_hdr));
407         if (assoc == 2) { //hack for softAP mode
408                         bsscmd->beacon_int = evif->beacon_interval;
409                 } else if (assoc == 1) {
410                         set_bit(ESP_WL_FLAG_CONNECT, &epub->wl.flags);
411         } else {
412                         clear_bit(ESP_WL_FLAG_CONNECT, &epub->wl.flags);
413         }
414                 bsscmd->bssid_no = evif->index;
415                 bsscmd->isassoc= assoc;
416                 bsscmd->beacon_int = evif->beacon_interval;
417         memcpy(bsscmd->bssid, bssid, ETH_ALEN);
418         return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL);
419 }
420
421 int  sip_send_wmm_params(struct esp_pub *epub, u8 aci, const struct ieee80211_tx_queue_params *params)
422 {
423         struct sk_buff *skb = NULL;
424         struct sip_cmd_set_wmm_params* bsscmd;
425         skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_set_wmm_params) + sizeof(struct sip_hdr), SIP_CMD_SET_WMM_PARAM);
426         if (!skb)
427                 return -EINVAL;
428
429         bsscmd = (struct sip_cmd_set_wmm_params *)(skb->data + sizeof(struct sip_hdr));
430         bsscmd->aci= aci;
431         bsscmd->aifs=params->aifs;
432         bsscmd->txop_us=params->txop*32;
433
434         bsscmd->ecw_min = 32 - __builtin_clz(params->cw_min);
435         bsscmd->ecw_max= 32 -__builtin_clz(params->cw_max);
436
437         return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL);
438 }
439
440 int sip_send_ampdu_action(struct esp_pub *epub, u8 action_num, const u8 * addr, u16 tid, u16 ssn, u8 buf_size)
441 {
442         int index = 0;
443         struct sk_buff *skb = NULL;
444         struct sip_cmd_ampdu_action * action;
445         if(action_num == SIP_AMPDU_RX_START){
446                 index = esp_get_empty_rxampdu(epub, addr, tid);
447         } else if(action_num == SIP_AMPDU_RX_STOP){
448                 index = esp_get_exist_rxampdu(epub, addr, tid);
449         }
450         if(index < 0)
451                 return -EACCES;
452         skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_ampdu_action) + sizeof(struct sip_hdr), SIP_CMD_AMPDU_ACTION);
453         if(!skb)
454                 return -EINVAL;
455
456         action = (struct sip_cmd_ampdu_action *)(skb->data + sizeof(struct sip_hdr));
457         action->action = action_num;
458         //for TX, it means interface index
459         action->index = ssn;
460
461         switch(action_num) {
462         case SIP_AMPDU_RX_START:
463                 action->ssn = ssn;
464         case SIP_AMPDU_RX_STOP:
465                 action->index = index;
466         case SIP_AMPDU_TX_OPERATIONAL:
467         case SIP_AMPDU_TX_STOP:
468                 action->win_size = buf_size;
469                 action->tid = tid;
470                 memcpy(action->addr, addr, ETH_ALEN);
471                 break;
472         }
473
474         return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL);
475 }
476
477 #ifdef HW_SCAN
478 /*send cmd to target, if aborted is true, inform target stop scan, report scan complete imediately
479   return 1: complete over, 0: success, still have next scan, -1: hardware failure
480   */
481 int sip_send_scan(struct esp_pub *epub)
482 {
483         struct cfg80211_scan_request *scan_req = epub->wl.scan_req;
484         struct sk_buff *skb = NULL;
485         struct sip_cmd_scan *scancmd;
486         u8 *ptr = NULL;
487         int i;
488         u8 append_len, ssid_len;
489
490         ESSERT(scan_req != NULL);
491         ssid_len = scan_req->n_ssids == 0 ? 0:
492                 (scan_req->n_ssids == 1 ? scan_req->ssids->ssid_len: scan_req->ssids->ssid_len + (scan_req->ssids + 1)->ssid_len);
493         append_len = ssid_len + scan_req->n_channels + scan_req->ie_len;
494
495         skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_scan) + sizeof(struct sip_hdr) + append_len, SIP_CMD_SCAN);
496
497         if (!skb)
498                 return -EINVAL;
499
500         ptr = skb->data;
501         scancmd = (struct sip_cmd_scan *)(ptr + sizeof(struct sip_hdr));
502         ptr += sizeof(struct sip_hdr);
503
504         scancmd->aborted= false;
505
506         if (scancmd->aborted==false) {
507                 ptr += sizeof(struct sip_cmd_scan);
508                 if (scan_req->n_ssids <=0 || (scan_req->n_ssids == 1&& ssid_len == 0)) {
509                         scancmd->ssid_len = 0;
510                 } else { 
511                         scancmd->ssid_len = ssid_len;
512                         if(scan_req->ssids->ssid_len == ssid_len)
513                                 memcpy(ptr, scan_req->ssids->ssid, scancmd->ssid_len);
514                         else
515                                 memcpy(ptr, (scan_req->ssids + 1)->ssid, scancmd->ssid_len);
516                 }
517
518                 ptr += scancmd->ssid_len;
519                 scancmd->n_channels=scan_req->n_channels;
520                 for (i=0; i<scan_req->n_channels; i++)
521                         ptr[i] = scan_req->channels[i]->hw_value;
522                 
523                 ptr += scancmd->n_channels;
524                 if (scan_req->ie_len && scan_req->ie != NULL) {
525                         scancmd->ie_len=scan_req->ie_len;
526                         memcpy(ptr, scan_req->ie, scan_req->ie_len);
527                 } else {
528                         scancmd->ie_len = 0;
529                 }
530                 //add a flag that support two ssids,
531                 if(scan_req->n_ssids > 1)
532                         scancmd->ssid_len |= 0x80;
533
534         }
535         
536         return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL);
537 }
538 #endif
539
540 int sip_send_suspend_config(struct esp_pub *epub, u8 suspend)
541 {
542         struct sip_cmd_suspend *cmd = NULL;
543         struct sk_buff *skb = NULL;
544
545         skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_suspend) + sizeof(struct sip_hdr), SIP_CMD_SUSPEND);
546
547         if (!skb)
548                 return -EINVAL;
549
550         cmd = (struct sip_cmd_suspend *)(skb->data + sizeof(struct sip_hdr));
551         cmd->suspend = suspend;
552         return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL);
553 }
554
555 int sip_send_ps_config(struct esp_pub *epub, struct esp_ps *ps)
556 {
557         struct sip_cmd_ps *pscmd = NULL;
558         struct sk_buff *skb = NULL;
559         struct sip_hdr *shdr = NULL;
560
561         skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_ps) + sizeof(struct sip_hdr), SIP_CMD_PS);
562
563         if (!skb)
564                 return -EINVAL;
565
566
567         shdr = (struct sip_hdr *)skb->data;
568         pscmd = (struct sip_cmd_ps *)(skb->data + sizeof(struct sip_hdr));
569
570         pscmd->dtim_period = ps->dtim_period;
571         pscmd->max_sleep_period = ps->max_sleep_period;
572
573         return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL);
574 }
575
576 void sip_scandone_process(struct esp_sip *sip, struct sip_evt_scan_report *scan_report)
577 {
578         struct esp_pub *epub = sip->epub;
579
580         esp_dbg(ESP_DBG_TRACE, "eagle hw scan report\n");
581
582         if (epub->wl.scan_req) {
583                 hw_scan_done(epub, scan_report->aborted);
584                 epub->wl.scan_req = NULL;
585         }
586 }
587
588 int sip_send_setkey(struct esp_pub *epub, u8 bssid_no, u8 *peer_addr, struct ieee80211_key_conf *key, u8 isvalid)
589 {
590         struct sip_cmd_setkey *setkeycmd;
591         struct sk_buff *skb = NULL;
592
593         skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_setkey) + sizeof(struct sip_hdr), SIP_CMD_SETKEY);
594
595         if (!skb)
596                 return -EINVAL;
597
598         setkeycmd = (struct sip_cmd_setkey *)(skb->data + sizeof(struct sip_hdr));
599
600         if (peer_addr) {
601                 memcpy(setkeycmd->addr, peer_addr, ETH_ALEN);
602         } else {
603                 memset(setkeycmd->addr, 0, ETH_ALEN);
604         }
605
606                 setkeycmd->bssid_no = bssid_no;
607         setkeycmd->hw_key_idx= key->hw_key_idx;
608
609         if (isvalid) {
610 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
611                 setkeycmd->alg= key->alg;
612 #else
613                 setkeycmd->alg= esp_cipher2alg(key->cipher);
614 #endif /* NEW_KERNEL */
615                 setkeycmd->keyidx = key->keyidx;
616                 setkeycmd->keylen = key->keylen;
617 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
618                 if (key->alg == ALG_TKIP) {
619 #else
620                 if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
621 #endif /* NEW_KERNEL */
622                         memcpy(setkeycmd->key, key->key, 16);
623                         memcpy(setkeycmd->key+16,key->key+24,8);
624                         memcpy(setkeycmd->key+24,key->key+16,8);
625                 } else {
626                         memcpy(setkeycmd->key, key->key, key->keylen);
627                 }
628
629                 setkeycmd->flags=1;
630         } else {
631                 setkeycmd->flags=0;
632         }
633         return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL);
634 }
635
636 #ifdef FPGA_LOOPBACK
637 #define LOOPBACK_PKT_LEN 200
638 int sip_send_loopback_cmd_mblk(struct esp_sip *sip)
639 {
640         int cnt, ret;
641
642         for (cnt = 0; cnt < 4; cnt++) {
643                 if (0!=(ret=sip_send_loopback_mblk(sip, LOOPBACK_PKT_LEN, LOOPBACK_PKT_LEN, 0)))
644                         return ret;
645         }
646         return 0;
647 }
648 #endif /* FPGA_LOOPBACK */
649
650 int sip_send_loopback_mblk(struct esp_sip *sip, int txpacket_len, int rxpacket_len, int packet_id)
651 {
652         struct sk_buff *skb = NULL;
653         struct sip_cmd_loopback *cmd;
654         u8 *ptr = NULL;
655         int i, ret;
656
657         //send 100 loopback pkt
658         if(txpacket_len)
659                 skb = sip_alloc_ctrl_skbuf(sip, sizeof(struct sip_cmd_loopback) + sizeof(struct sip_hdr) +  txpacket_len, SIP_CMD_LOOPBACK);
660         else
661                 skb = sip_alloc_ctrl_skbuf(sip, sizeof(struct sip_cmd_loopback) + sizeof(struct sip_hdr), SIP_CMD_LOOPBACK);
662
663         if (!skb)
664                 return -ENOMEM;
665
666         ptr = skb->data;
667         cmd = (struct sip_cmd_loopback *)(ptr + sizeof(struct sip_hdr));
668         ptr += sizeof(struct sip_hdr);
669         cmd->txlen = txpacket_len;
670         cmd->rxlen = rxpacket_len;
671         cmd->pack_id = packet_id;
672
673         if (txpacket_len) {
674                 ptr += sizeof(struct sip_cmd_loopback);
675                 /* fill up pkt payload */
676                 for (i = 0; i < txpacket_len; i++) {
677                         ptr[i] = i;
678                 }
679         }
680
681         ret = sip_cmd_enqueue(sip, skb, ENQUEUE_PRIOR_TAIL);
682         if (ret <0)
683                 return ret;
684
685         return 0;
686 }
687
688 //remain_on_channel 
689 int sip_send_roc(struct esp_pub *epub, u16 center_freq, u16 duration)
690 {
691         struct sk_buff *skb = NULL;
692         struct sip_cmd_config *configcmd;
693
694         skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_config) + sizeof(struct sip_hdr), SIP_CMD_CONFIG);
695         if (!skb)
696                 return -EINVAL;
697
698         configcmd = (struct sip_cmd_config *)(skb->data + sizeof(struct sip_hdr));
699         configcmd->center_freq= center_freq;
700         configcmd->duration= duration;
701         return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL);
702 }
703
704 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
705 int sip_send_set_sta(struct esp_pub *epub, u8 ifidx, u8 set, struct ieee80211_sta *sta, struct ieee80211_vif *vif, u8 index)
706 #else
707 int sip_send_set_sta(struct esp_pub *epub, u8 ifidx, u8 set, struct esp_node *node, struct ieee80211_vif *vif, u8 index)
708 #endif
709 {
710         struct sk_buff *skb = NULL;
711         struct sip_cmd_setsta *setstacmd;
712 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
713         struct ieee80211_ht_info ht_info = node->ht_info;
714 #endif
715         skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_setsta) + sizeof(struct sip_hdr), SIP_CMD_SETSTA);
716         if (!skb)
717         return -EINVAL;
718
719         setstacmd = (struct sip_cmd_setsta *)(skb->data + sizeof(struct sip_hdr));
720         setstacmd->ifidx = ifidx;
721         setstacmd->index = index;
722         setstacmd->set = set;
723 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
724         if(sta->aid == 0)
725                 setstacmd->aid = vif->bss_conf.aid;
726         else
727                 setstacmd->aid = sta->aid;
728         memcpy(setstacmd->mac, sta->addr, ETH_ALEN);
729         if(set){
730                 if(sta->ht_cap.ht_supported){
731                         if(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20)
732                                 setstacmd->phymode = ESP_IEEE80211_T_HT20_S;
733                         else
734                                 setstacmd->phymode = ESP_IEEE80211_T_HT20_L;
735                         setstacmd->ampdu_factor = sta->ht_cap.ampdu_factor;
736                         setstacmd->ampdu_density = sta->ht_cap.ampdu_density;
737                 } else {
738                         if(sta->supp_rates[IEEE80211_BAND_2GHZ] & (~(u32)CONF_HW_BIT_RATE_11B_MASK)){
739                                 setstacmd->phymode = ESP_IEEE80211_T_OFDM;
740                         } else {
741                                 setstacmd->phymode = ESP_IEEE80211_T_CCK;
742                         }
743                 }
744         }
745 #else
746     setstacmd->aid = node->aid;
747     memcpy(setstacmd->mac, node->addr, ETH_ALEN);
748     if(set){
749         if(ht_info.ht_supported){
750             if(ht_info.cap & IEEE80211_HT_CAP_SGI_20)
751                 setstacmd->phymode = ESP_IEEE80211_T_HT20_S;
752             else
753                 setstacmd->phymode = ESP_IEEE80211_T_HT20_L;
754             setstacmd->ampdu_factor = ht_info.ampdu_factor;
755             setstacmd->ampdu_density = ht_info.ampdu_density;
756         } else {
757             //note supp_rates is u64[] in 2.6.27
758             if(node->supp_rates[IEEE80211_BAND_2GHZ] & (~(u64)CONF_HW_BIT_RATE_11B_MASK)){
759                 setstacmd->phymode = ESP_IEEE80211_T_OFDM;
760             } else {
761                 setstacmd->phymode = ESP_IEEE80211_T_CCK;
762             }   
763         }   
764     }   
765 #endif
766         return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL);
767 }
768
769 int sip_send_recalc_credit(struct esp_pub *epub)
770 {
771         struct sk_buff *skb = NULL;
772
773         skb = sip_alloc_ctrl_skbuf(epub->sip, 0 + sizeof(struct sip_hdr), SIP_CMD_RECALC_CREDIT);
774         if (!skb)
775                 return -ENOMEM;
776         
777         return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_HEAD);
778 }
779
780 int sip_cmd(struct esp_pub *epub, enum sip_cmd_id cmd_id, u8 *cmd_buf, u8 cmd_len)
781 {
782         struct sk_buff *skb = NULL;
783
784         skb = sip_alloc_ctrl_skbuf(epub->sip, cmd_len + sizeof(struct sip_hdr), cmd_id);
785         if (!skb)
786                 return -ENOMEM;
787
788         memcpy(skb->data + sizeof(struct sip_hdr), cmd_buf, cmd_len);
789
790         return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL);
791 }