Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6
[pandora-kernel.git] / drivers / staging / otus / 80211core / cmmap.c
1 /*
2  * Copyright (c) 2007-2008 Atheros Communications Inc.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 /*                                                                      */
17 /*  Module Name : mm.c                                                  */
18 /*                                                                      */
19 /*  Abstract                                                            */
20 /*      This module contains common functions for handle AP             */
21 /*      management frame.                                               */
22 /*                                                                      */
23 /*  NOTES                                                               */
24 /*      None                                                            */
25 /*                                                                      */
26 /************************************************************************/
27 #include "cprecomp.h"
28 #include "ratectrl.h"
29
30 extern const u8_t zcUpToAc[];
31
32 void zfMmApTimeTick(zdev_t* dev)
33 {
34     u32_t now;
35     zmw_get_wlan_dev(dev);
36
37     //zm_debug_msg1("wd->wlanMode : ", wd->wlanMode);
38     if (wd->wlanMode == ZM_MODE_AP)
39     {
40         /* => every 1.28 seconds */
41         /* AP : aging STA that does not active for wd->ap.staAgingTime    */
42         now = wd->tick & 0x7f;
43         if (now == 0x0)
44         {
45             zfApAgingSta(dev);
46         }
47         else if (now == 0x1f)
48         {
49             zfQueueAge(dev, wd->ap.uapsdQ, wd->tick, 10000);
50         }
51         /* AP : check (wd->ap.protectedObss) and (wd->ap.bStaAssociated)  */
52         /*      to enable NonErp and Protection mode                      */
53         else if (now == 0x3f)
54         {
55             //zfApProtctionMonitor(dev);
56         }
57     }
58 }
59
60 /************************************************************************/
61 /*                                                                      */
62 /*    FUNCTION DESCRIPTION                  zfApInitStaTbl              */
63 /*      Init AP's station table.                                        */
64 /*                                                                      */
65 /*    INPUTS                                                            */
66 /*      dev : device pointer                                            */
67 /*                                                                      */
68 /*    OUTPUTS                                                           */
69 /*      None                                                            */
70 /*                                                                      */
71 /*    AUTHOR                                                            */
72 /*      Stephen Chen        ZyDAS Technology Corporation    2005.10     */
73 /*                                                                      */
74 /************************************************************************/
75 void zfApInitStaTbl(zdev_t* dev)
76 {
77     u16_t i;
78
79     zmw_get_wlan_dev(dev);
80
81     for (i=0; i<ZM_MAX_STA_SUPPORT; i++)
82     {
83         wd->ap.staTable[i].valid = 0;
84         wd->ap.staTable[i].state = 0;
85         wd->ap.staTable[i].addr[0] = 0;
86         wd->ap.staTable[i].addr[1] = 0;
87         wd->ap.staTable[i].addr[2] = 0;
88         wd->ap.staTable[i].time = 0;
89         wd->ap.staTable[i].vap = 0;
90         wd->ap.staTable[i].encryMode = ZM_NO_WEP;
91     }
92     return;
93 }
94
95
96 /************************************************************************/
97 /*                                                                      */
98 /*    FUNCTION DESCRIPTION                  zfApFindSta                 */
99 /*      Find a STA in station table.                                    */
100 /*                                                                      */
101 /*    INPUTS                                                            */
102 /*      dev : device pointer                                            */
103 /*      addr : Target STA address                                       */
104 /*                                                                      */
105 /*    OUTPUTS                                                           */
106 /*      0xffff : fail                                                   */
107 /*      other : STA table index                                         */
108 /*                                                                      */
109 /*    AUTHOR                                                            */
110 /*      Stephen Chen        ZyDAS Technology Corporation    2005.10     */
111 /*                                                                      */
112 /************************************************************************/
113 u16_t zfApFindSta(zdev_t* dev, u16_t* addr)
114 {
115     u16_t i;
116
117     zmw_get_wlan_dev(dev);
118
119     for (i=0; i<ZM_MAX_STA_SUPPORT; i++)
120     {
121         if (wd->ap.staTable[i].valid == 1)
122         {
123             if ((wd->ap.staTable[i].addr[0] == addr[0])
124                     && (wd->ap.staTable[i].addr[1] == addr[1])
125                     && (wd->ap.staTable[i].addr[2] == addr[2]))
126             {
127                 return i;
128             }
129         }
130     }
131     return 0xffff;
132 }
133
134 u16_t zfApGetSTAInfo(zdev_t* dev, u16_t* addr, u16_t* state, u8_t* vap)
135 {
136     u16_t id;
137
138     zmw_get_wlan_dev(dev);
139
140     zmw_declare_for_critical_section();
141
142     zmw_enter_critical_section(dev);
143
144     id = zfApFindSta(dev, addr);
145     if (id != 0xffff)
146     {
147         *vap = wd->ap.staTable[id].vap;
148         *state = wd->ap.staTable[id++].state;
149     }
150
151     zmw_leave_critical_section(dev);
152
153     return id;
154 }
155
156
157 void zfApGetStaQosType(zdev_t* dev, u16_t* addr, u8_t* qosType)
158 {
159     u16_t id;
160
161     zmw_get_wlan_dev(dev);
162
163     zmw_declare_for_critical_section();
164
165     zmw_enter_critical_section(dev);
166
167     id = zfApFindSta(dev, addr);
168     if (id != 0xffff)
169     {
170         *qosType = wd->ap.staTable[id].qosType;
171     }
172     else
173     {
174         *qosType = 0;
175     }
176
177     zmw_leave_critical_section(dev);
178
179     return;
180 }
181
182 void zfApGetStaTxRateAndQosType(zdev_t* dev, u16_t* addr, u32_t* phyCtrl,
183                                 u8_t* qosType, u16_t* rcProbingFlag)
184 {
185     u16_t id;
186     u8_t rate;
187
188     zmw_get_wlan_dev(dev);
189
190     zmw_declare_for_critical_section();
191
192     zmw_enter_critical_section(dev);
193
194     id = zfApFindSta(dev, addr);
195     if (id != 0xffff)
196     {
197         rate = (u8_t)zfRateCtrlGetTxRate(dev, &wd->ap.staTable[id].rcCell, rcProbingFlag);
198 #ifdef ZM_AP_DEBUG
199         //rate = 15;
200 #endif
201         *phyCtrl = zcRateToPhyCtrl[rate];
202         *qosType = wd->ap.staTable[id].qosType;
203     }
204     else
205     {
206         if (wd->frequency < 3000)
207         {
208             /* CCK 1M */
209             //header[2] = 0x0f00;          //PHY control L
210             //header[3] = 0x0000;          //PHY control H
211             *phyCtrl = 0x00000F00;
212         }
213         else
214         {
215             /* CCK 6M */
216             //header[2] = 0x0f01;          //PHY control L
217             //header[3] = 0x000B;          //PHY control H
218             *phyCtrl = 0x000B0F01;
219         }
220         *qosType = 0;
221     }
222
223     zmw_leave_critical_section(dev);
224
225     zm_msg2_mm(ZM_LV_3, "PhyCtrl=", *phyCtrl);
226     return;
227 }
228
229 void zfApGetStaEncryType(zdev_t* dev, u16_t* addr, u8_t* encryType)
230 {
231     //struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev);
232     u16_t id;
233
234     zmw_get_wlan_dev(dev);
235
236     zmw_declare_for_critical_section();
237
238     zmw_enter_critical_section(dev);
239
240     id = zfApFindSta(dev, addr);
241     if (id != 0xffff)
242     {
243         *encryType = wd->ap.staTable[id].encryMode;
244     }
245     else
246     {
247         *encryType = ZM_NO_WEP;
248     }
249
250     zmw_leave_critical_section(dev);
251
252     zm_msg2_mm(ZM_LV_3, "encyrType=", *encryType);
253     return;
254 }
255
256 void zfApGetStaWpaIv(zdev_t* dev, u16_t* addr, u16_t* iv16, u32_t* iv32)
257 {
258     //struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev);
259     u16_t id;
260
261     zmw_get_wlan_dev(dev);
262
263     zmw_declare_for_critical_section();
264
265     zmw_enter_critical_section(dev);
266
267     id = zfApFindSta(dev, addr);
268     if (id != 0xffff)
269     {
270         *iv16 = wd->ap.staTable[id].iv16;
271         *iv32 = wd->ap.staTable[id].iv32;
272     }
273     else
274     {
275         *iv16 = 0;
276         *iv32 = 0;
277     }
278
279     zmw_leave_critical_section(dev);
280
281     zm_msg2_mm(ZM_LV_3, "iv16=", *iv16);
282     zm_msg2_mm(ZM_LV_3, "iv32=", *iv32);
283     return;
284 }
285
286 void zfApSetStaWpaIv(zdev_t* dev, u16_t* addr, u16_t iv16, u32_t iv32)
287 {
288     //struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev);
289     u16_t id;
290
291     zmw_get_wlan_dev(dev);
292
293     zmw_declare_for_critical_section();
294
295     zmw_enter_critical_section(dev);
296
297     id = zfApFindSta(dev, addr);
298     if (id != 0xffff)
299     {
300         wd->ap.staTable[id].iv16 = iv16;
301         wd->ap.staTable[id].iv32 = iv32;
302     }
303
304     zmw_leave_critical_section(dev);
305
306     zm_msg2_mm(ZM_LV_3, "iv16=", iv16);
307     zm_msg2_mm(ZM_LV_3, "iv32=", iv32);
308     return;
309 }
310
311 void zfApClearStaKey(zdev_t* dev, u16_t* addr)
312 {
313     //struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev);
314     u16_t bcAddr[3] = { 0xffff, 0xffff, 0xffff };
315     u16_t id;
316
317     zmw_get_wlan_dev(dev);
318
319     if (zfMemoryIsEqual((u8_t*)bcAddr, (u8_t*)addr, sizeof(bcAddr)) == TRUE)
320     {
321         /* Turn off group key information */
322     //    zfClearKey(dev, 0);
323     }
324     else
325     {
326         zmw_declare_for_critical_section();
327
328         zmw_enter_critical_section(dev);
329
330         id = zfApFindSta(dev, addr);
331         if (id != 0xffff)
332         {
333             /* Turn off STA's key information */
334             zfHpRemoveKey(dev, id+1);
335
336             /* Update STA's Encryption Type */
337             wd->ap.staTable[id].encryMode = ZM_NO_WEP;
338         }
339         else
340         {
341             zm_msg0_mm(ZM_LV_3, "Can't find STA address\n");
342         }
343         zmw_leave_critical_section(dev);
344     }
345 }
346
347 #ifdef ZM_ENABLE_CENC
348 void zfApGetStaCencIvAndKeyIdx(zdev_t* dev, u16_t* addr, u32_t *iv, u8_t *keyIdx)
349 {
350     //struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev);
351     u16_t id;
352     zmw_get_wlan_dev(dev);
353     zmw_declare_for_critical_section();
354
355
356     zmw_enter_critical_section(dev);
357
358     id = zfApFindSta(dev, addr);
359     if (id != 0xffff)
360     {
361         *iv++ = wd->ap.staTable[id].txiv[0];
362         *iv++ = wd->ap.staTable[id].txiv[1];
363         *iv++ = wd->ap.staTable[id].txiv[2];
364         *iv = wd->ap.staTable[id].txiv[3];
365         *keyIdx = wd->ap.staTable[id].cencKeyIdx;
366     }
367     else
368     {
369         *iv++ = 0x5c365c37;
370         *iv++ = 0x5c365c36;
371         *iv++ = 0x5c365c36;
372         *iv = 0x5c365c36;
373         *keyIdx = 0;
374     }
375
376     zmw_leave_critical_section(dev);
377     return;
378 }
379
380 void zfApSetStaCencIv(zdev_t* dev, u16_t* addr, u32_t *iv)
381 {
382     //struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev);
383     u16_t id;
384     zmw_get_wlan_dev(dev);
385     zmw_declare_for_critical_section();
386
387
388     zmw_enter_critical_section(dev);
389
390     id = zfApFindSta(dev, addr);
391     if (id != 0xffff)
392     {
393         wd->ap.staTable[id].txiv[0] = *iv++;
394         wd->ap.staTable[id].txiv[1] = *iv++;
395         wd->ap.staTable[id].txiv[2] = *iv++;
396         wd->ap.staTable[id].txiv[3] = *iv;
397     }
398
399     zmw_leave_critical_section(dev);
400
401     return;
402 }
403 #endif //ZM_ENABLE_CENC
404
405
406 /************************************************************************/
407 /*                                                                      */
408 /*    FUNCTION DESCRIPTION                  zfApFlushBufferedPsFrame    */
409 /*      Free buffered PS frames.                                        */
410 /*                                                                      */
411 /*    INPUTS                                                            */
412 /*      dev : device pointer                                            */
413 /*                                                                      */
414 /*    OUTPUTS                                                           */
415 /*      None                                                            */
416 /*                                                                      */
417 /*    AUTHOR                                                            */
418 /*      Stephen Chen        Atheros Communications, INC.    2007.1      */
419 /*                                                                      */
420 /************************************************************************/
421 void zfApFlushBufferedPsFrame(zdev_t* dev)
422 {
423     u16_t emptyFlag;
424     u16_t freeCount;
425     u16_t vap;
426     zbuf_t* psBuf = NULL;
427     zmw_get_wlan_dev(dev);
428     zmw_declare_for_critical_section();
429
430     freeCount = 0;
431     emptyFlag = 0;
432     while (1)
433     {
434         psBuf = NULL;
435         zmw_enter_critical_section(dev);
436         if (wd->ap.uniHead != wd->ap.uniTail)
437         {
438             psBuf = wd->ap.uniArray[wd->ap.uniHead];
439             wd->ap.uniHead = (wd->ap.uniHead + 1) & (ZM_UNI_ARRAY_SIZE - 1);
440         }
441         else
442         {
443             emptyFlag = 1;
444         }
445         zmw_leave_critical_section(dev);
446
447         if (psBuf != NULL)
448         {
449             zfwBufFree(dev, psBuf, ZM_ERR_FLUSH_PS_QUEUE);
450         }
451         zm_assert(freeCount++ < (ZM_UNI_ARRAY_SIZE*2));
452
453         if (emptyFlag != 0)
454         {
455             break;
456         }
457     }
458
459     for (vap=0; vap<ZM_MAX_AP_SUPPORT; vap++)
460     {
461         freeCount = 0;
462         emptyFlag = 0;
463         while (1)
464         {
465             psBuf = NULL;
466             zmw_enter_critical_section(dev);
467             if (wd->ap.bcmcHead[vap] != wd->ap.bcmcTail[vap])
468             {
469                 psBuf = wd->ap.bcmcArray[vap][wd->ap.bcmcHead[vap]];
470                 wd->ap.bcmcHead[vap] = (wd->ap.bcmcHead[vap] + 1)
471                         & (ZM_BCMC_ARRAY_SIZE - 1);
472             }
473             else
474             {
475                 emptyFlag = 1;
476             }
477             zmw_leave_critical_section(dev);
478
479             if (psBuf != NULL)
480             {
481                 zfwBufFree(dev, psBuf, ZM_ERR_FLUSH_PS_QUEUE);
482             }
483             zm_assert(freeCount++ < (ZM_BCMC_ARRAY_SIZE*2));
484
485             if (emptyFlag != 0)
486             {
487                 break;
488             }
489         }
490     }
491     return;
492 }
493
494
495 u16_t zfApBufferPsFrame(zdev_t* dev, zbuf_t* buf, u16_t port)
496 {
497     u16_t id;
498     u16_t addr[3];
499     u16_t vap = 0;
500     u8_t up;
501     u16_t fragOff;
502     u8_t ac;
503     u16_t ret;
504
505     zmw_get_wlan_dev(dev);
506
507     zmw_declare_for_critical_section();
508
509     if (port < ZM_MAX_AP_SUPPORT)
510     {
511         vap = port;
512     }
513
514     addr[0] = zmw_rx_buf_readh(dev, buf, 0);
515     addr[1] = zmw_rx_buf_readh(dev, buf, 2);
516     addr[2] = zmw_rx_buf_readh(dev, buf, 4);
517
518     if ((addr[0] & 0x1) == 0x1)
519     {
520         if (wd->ap.staPowerSaving > 0)
521         {
522             zmw_enter_critical_section(dev);
523
524             /* Buffer this BC or MC frame */
525             if (((wd->ap.bcmcTail[vap]+1)&(ZM_BCMC_ARRAY_SIZE-1))
526                     != wd->ap.bcmcHead[vap])
527             {
528                 wd->ap.bcmcArray[vap][wd->ap.bcmcTail[vap]++] = buf;
529                 wd->ap.bcmcTail[vap] &= (ZM_BCMC_ARRAY_SIZE-1);
530                 zmw_leave_critical_section(dev);
531
532                 zm_msg0_tx(ZM_LV_0, "Buffer BCMC");
533             }
534             else
535             {
536                 /* bcmcArray full */
537                 zmw_leave_critical_section(dev);
538
539                 zm_msg0_tx(ZM_LV_0, "BCMC buffer full");
540
541                 /* free buffer according to buffer type */
542                 zfwBufFree(dev, buf, ZM_ERR_BCMC_PS_BUFFER_UNAVAILABLE);
543             }
544             return 1;
545         }
546     }
547     else
548     {
549         zmw_enter_critical_section(dev);
550
551         id = zfApFindSta(dev, addr);
552         if (id != 0xffff)
553         {
554             if (wd->ap.staTable[id].psMode == 1)
555             {
556
557                 zfTxGetIpTosAndFrag(dev, buf, &up, &fragOff);
558                 ac = zcUpToAc[up&0x7] & 0x3;
559
560                 if ((wd->ap.staTable[id].qosType == 1) &&
561                         ((wd->ap.staTable[id].qosInfo & (0x8>>ac)) != 0))
562                 {
563                     ret = zfQueuePutNcs(dev, wd->ap.uapsdQ, buf, wd->tick);
564                     zmw_leave_critical_section(dev);
565                     if (ret != ZM_SUCCESS)
566                     {
567                         zfwBufFree(dev, buf, ZM_ERR_AP_UAPSD_QUEUE_FULL);
568                     }
569                 }
570                 else
571                 {
572                 /* Buffer this unicast frame */
573                 if (((wd->ap.uniTail+1)&(ZM_UNI_ARRAY_SIZE-1))
574                         != wd->ap.uniHead)
575                 {
576                     wd->ap.uniArray[wd->ap.uniTail++] = buf;
577                     wd->ap.uniTail &= (ZM_UNI_ARRAY_SIZE-1);
578                     zmw_leave_critical_section(dev);
579                     zm_msg0_tx(ZM_LV_0, "Buffer UNI");
580
581                 }
582                 else
583                 {
584                     /* uniArray full */
585                     zmw_leave_critical_section(dev);
586                     zm_msg0_tx(ZM_LV_0, "UNI buffer full");
587                     /* free buffer according to buffer type */
588                     zfwBufFree(dev, buf, ZM_ERR_UNI_PS_BUFFER_UNAVAILABLE);
589                 }
590                 }
591                 return 1;
592             } /* if (wd->ap.staTable[id++].psMode == 1) */
593         } /* if ((id = zfApFindSta(dev, addr)) != 0xffff) */
594         zmw_leave_critical_section(dev);
595     }
596
597     return 0;
598 }
599
600 u16_t zfApGetSTAInfoAndUpdatePs(zdev_t* dev, u16_t* addr, u16_t* state,
601                                 u8_t* vap, u16_t psMode, u8_t* uapsdTrig)
602 {
603     u16_t id;
604     u8_t uapsdStaAwake = 0;
605
606     zmw_get_wlan_dev(dev);
607
608     zmw_declare_for_critical_section();
609
610     zmw_enter_critical_section(dev);
611
612 #ifdef ZM_AP_DEBUG
613     //psMode=0;
614 #endif
615
616     id = zfApFindSta(dev, addr);
617     if (id != 0xffff)
618     {
619         if (psMode != 0)
620         {
621             zm_msg0_mm(ZM_LV_0, "psMode = 1");
622             if (wd->ap.staTable[id].psMode == 0)
623             {
624                 wd->ap.staPowerSaving++;
625             }
626             else
627             {
628                 if (wd->ap.staTable[id].qosType == 1)
629                 {
630                     zm_msg0_mm(ZM_LV_0, "UAPSD trigger");
631                     *uapsdTrig = wd->ap.staTable[id].qosInfo;
632                 }
633             }
634         }
635         else
636         {
637             if (wd->ap.staTable[id].psMode != 0)
638             {
639                 wd->ap.staPowerSaving--;
640                 if ((wd->ap.staTable[id].qosType == 1) && ((wd->ap.staTable[id].qosInfo&0xf)!=0))
641                 {
642                     uapsdStaAwake = 1;
643                 }
644             }
645         }
646
647         wd->ap.staTable[id].psMode = (u8_t) psMode;
648         wd->ap.staTable[id].time = wd->tick;
649         *vap = wd->ap.staTable[id].vap;
650         *state = wd->ap.staTable[id++].state;
651     }
652
653     zmw_leave_critical_section(dev);
654
655     if (uapsdStaAwake == 1)
656     {
657         zbuf_t* psBuf;
658         u8_t mb;
659
660         while (1)
661         {
662             psBuf = zfQueueGetWithMac(dev, wd->ap.uapsdQ, (u8_t*)addr, &mb);
663             if (psBuf != NULL)
664             {
665                 zfTxSendEth(dev, psBuf, 0, ZM_EXTERNAL_ALLOC_BUF, 0);
666             }
667             else
668             {
669                 break;
670             }
671         }
672     }
673
674     return id;
675 }
676
677 /************************************************************************/
678 /*                                                                      */
679 /*    FUNCTION DESCRIPTION                  zfApGetNewSta               */
680 /*      Get a new STA from station table.                               */
681 /*                                                                      */
682 /*    INPUTS                                                            */
683 /*      dev : device pointer                                            */
684 /*                                                                      */
685 /*    OUTPUTS                                                           */
686 /*      0xffff : fail                                                   */
687 /*      other : STA table index                                         */
688 /*                                                                      */
689 /*    AUTHOR                                                            */
690 /*      Stephen Chen        ZyDAS Technology Corporation    2005.10     */
691 /*                                                                      */
692 /************************************************************************/
693 u16_t zfApGetNewSta(zdev_t* dev)
694 {
695     u16_t i;
696
697     zmw_get_wlan_dev(dev);
698
699     for (i=0; i<ZM_MAX_STA_SUPPORT; i++)
700     {
701         if (wd->ap.staTable[i].valid == 0)
702         {
703             zm_msg2_mm(ZM_LV_0, "zfApGetNewSta=", i);
704             return i;
705         }
706     }
707     return 0xffff;
708 }
709
710
711 /************************************************************************/
712 /*                                                                      */
713 /*    FUNCTION DESCRIPTION                  zfApAddSta                  */
714 /*      Add a STA to station table.                                     */
715 /*                                                                      */
716 /*    INPUTS                                                            */
717 /*      dev : device pointer                                            */
718 /*      addr : STA MAC address                                          */
719 /*      state : STA state                                               */
720 /*      apId : Virtual AP ID                                            */
721 /*      type : 0=>11b, 1=>11g                                           */
722 /*                                                                      */
723 /*    OUTPUTS                                                           */
724 /*      0xffff : fail                                                   */
725 /*      Other : index                                                   */
726 /*                                                                      */
727 /*    AUTHOR                                                            */
728 /*      Stephen Chen        ZyDAS Technology Corporation    2005.10     */
729 /*                                                                      */
730 /************************************************************************/
731 u16_t zfApAddSta(zdev_t* dev, u16_t* addr, u16_t state, u16_t apId, u8_t type,
732                  u8_t qosType, u8_t qosInfo)
733 {
734     u16_t index;
735     u16_t i;
736
737     zmw_get_wlan_dev(dev);
738
739     zmw_declare_for_critical_section();
740
741     zm_msg1_mm(ZM_LV_0, "STA type=", type);
742
743     zmw_enter_critical_section(dev);
744
745     index = zfApFindSta(dev, addr);
746     if (index != 0xffff)
747     {
748         zm_msg0_mm(ZM_LV_2, "found");
749         /* Update STA state */
750         if ((state == ZM_STATE_AUTH) || (state == ZM_STATE_PREAUTH))
751         {
752             wd->ap.staTable[index].state = state;
753             wd->ap.staTable[index].time = wd->tick;
754             wd->ap.staTable[index].vap = (u8_t)apId;
755         }
756         else if (state == ZM_STATE_ASOC)
757         {
758             if ((wd->ap.staTable[index].state == ZM_STATE_AUTH))
759                     //&& (wd->ap.staTable[index].vap == apId))
760             {
761                 wd->ap.staTable[index].state = state;
762                 wd->ap.staTable[index].time = wd->tick;
763                 wd->ap.staTable[index].qosType = qosType;
764                 wd->ap.staTable[index].vap = (u8_t)apId;
765                 wd->ap.staTable[index].staType = type;
766                 wd->ap.staTable[index].qosInfo = qosInfo;
767
768                 if (wd->frequency < 3000)
769                 {
770                     /* Init 11b/g */
771                     zfRateCtrlInitCell(dev, &wd->ap.staTable[index].rcCell, type, 1, 1);
772                 }
773                 else
774                 {
775                     /* Init 11a */
776                     zfRateCtrlInitCell(dev, &wd->ap.staTable[index].rcCell, type, 0, 1);
777                 }
778
779                 if (wd->zfcbApConnectNotify != NULL)
780                 {
781                     wd->zfcbApConnectNotify(dev, (u8_t*)addr, apId);
782                 }
783             }
784             else
785             {
786                 index = 0xffff;
787             }
788         }
789     }
790     else
791     {
792         zm_msg0_mm(ZM_LV_2, "Not found");
793         if ((state == ZM_STATE_AUTH) || (state == ZM_STATE_PREAUTH))
794         {
795             /* Get a new STA and update state */
796             index = zfApGetNewSta(dev);
797             zm_msg2_mm(ZM_LV_1, "new STA index=", index);
798
799             if (index != 0xffff)
800             {
801                 for (i=0; i<3; i++)
802                 {
803                     wd->ap.staTable[index].addr[i] = addr[i];
804                 }
805                 wd->ap.staTable[index].state = state;
806                 wd->ap.staTable[index].valid = 1;
807                 wd->ap.staTable[index].time = wd->tick;
808                 wd->ap.staTable[index].vap = (u8_t)apId;
809                 wd->ap.staTable[index].encryMode = ZM_NO_WEP;
810             }
811         }
812     }
813
814     zmw_leave_critical_section(dev);
815
816     return index;
817 }
818
819
820 /************************************************************************/
821 /*                                                                      */
822 /*    FUNCTION DESCRIPTION                  zfApAgingSta                */
823 /*      Aging STA in station table.                                     */
824 /*                                                                      */
825 /*    INPUTS                                                            */
826 /*      dev : device pointer                                            */
827 /*                                                                      */
828 /*    OUTPUTS                                                           */
829 /*      number of 11b STA in STA table                                  */
830 /*                                                                      */
831 /*    AUTHOR                                                            */
832 /*      Stephen Chen        ZyDAS Technology Corporation    2005.10     */
833 /*                                                                      */
834 /************************************************************************/
835 void zfApAgingSta(zdev_t* dev)
836 {
837     u16_t i;
838     u32_t deltaMs;
839     u16_t addr[3];
840     u16_t txFlag;
841     u16_t psStaCount = 0;
842
843     zmw_get_wlan_dev(dev);
844
845     zmw_declare_for_critical_section();
846
847     wd->ap.gStaAssociated = wd->ap.bStaAssociated = 0;
848
849     for (i=0; i<ZM_MAX_STA_SUPPORT; i++)
850     {
851         txFlag = 0;
852         zmw_enter_critical_section(dev);
853         if (wd->ap.staTable[i].valid == 1)
854         {
855             addr[0] = wd->ap.staTable[i].addr[0];
856             addr[1] = wd->ap.staTable[i].addr[1];
857             addr[2] = wd->ap.staTable[i].addr[2];
858             /* millisecond */
859             deltaMs = (u32_t)((u32_t)wd->tick-(u32_t)wd->ap.staTable[i].time)
860                       * ZM_MS_PER_TICK;
861
862             /* preauth */
863             if ((wd->ap.staTable[i].state == ZM_STATE_PREAUTH)
864                     && (deltaMs > ZM_PREAUTH_TIMEOUT_MS))
865             {
866                 /* Aging STA */
867                 wd->ap.staTable[i].valid = 0;
868                 wd->ap.authSharing = 0;
869                 txFlag = 1;
870             }
871
872             /* auth */
873             if ((wd->ap.staTable[i].state == ZM_STATE_AUTH)
874                     && (deltaMs > ZM_AUTH_TIMEOUT_MS))
875             {
876                 /* Aging STA */
877                 wd->ap.staTable[i].valid = 0;
878                 txFlag = 1;
879             }
880
881             /* asoc */
882             if (wd->ap.staTable[i].state == ZM_STATE_ASOC)
883             {
884                 if (wd->ap.staTable[i].psMode != 0)
885                 {
886                     psStaCount++;
887                 }
888
889                 if (deltaMs > ((u32_t)wd->ap.staAgingTimeSec<<10))
890                 {
891                     /* Aging STA */
892                     zm_msg1_mm(ZM_LV_0, "Age STA index=", i);
893                     wd->ap.staTable[i].valid = 0;
894                     txFlag = 1;
895                 }
896                 else if (deltaMs > ((u32_t)wd->ap.staProbingTimeSec<<10))
897                 {
898                     if (wd->ap.staTable[i].psMode == 0)
899                     {
900                         /* Probing non-PS STA */
901                         zm_msg1_mm(ZM_LV_0, "Probing STA index=", i);
902                         wd->ap.staTable[i].time +=
903                                 (wd->ap.staProbingTimeSec * ZM_TICK_PER_SECOND);
904                         txFlag = 2;
905                     }
906                 }
907             }
908
909
910         }
911         zmw_leave_critical_section(dev);
912
913         if (txFlag == 1)
914         {
915             /* Send deauthentication management frame */
916             zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, addr, 4, 0, 0);
917         }
918         else if (txFlag == 2)
919         {
920             zfSendMmFrame(dev, ZM_WLAN_DATA_FRAME, addr, 0, 0, 0);
921         }
922
923     }
924
925     wd->ap.staPowerSaving = psStaCount;
926
927     return;
928 }
929
930 void zfApProtctionMonitor(zdev_t* dev)
931 {
932     zmw_get_wlan_dev(dev);
933
934     /* 11b STA associated => nonErp, Protect */
935     if (wd->ap.bStaAssociated > 0)
936     {
937         /* Enable NonErp bit in information element */
938         wd->erpElement = ZM_WLAN_NON_ERP_PRESENT_BIT
939                          | ZM_WLAN_USE_PROTECTION_BIT;
940
941         /* Enable protection mode */
942         zfApSetProtectionMode(dev, 1);
943
944     }
945     /* 11b STA not associated, protection OBSS present => Protect */
946     else if (wd->ap.protectedObss > 2) //Threshold
947     {
948         if (wd->disableSelfCts == 0)
949         {
950             /* Disable NonErp bit in information element */
951             wd->erpElement = ZM_WLAN_USE_PROTECTION_BIT;
952
953             /* Enable protection mode */
954             zfApSetProtectionMode(dev, 1);
955         }
956     }
957     else
958     {
959         /* Disable NonErp bit in information element */
960         wd->erpElement = 0;
961
962         /* Disable protection mode */
963         zfApSetProtectionMode(dev, 0);
964     }
965     wd->ap.protectedObss = 0;
966 }
967
968
969 void zfApProcessBeacon(zdev_t* dev, zbuf_t* buf)
970 {
971     u16_t offset;
972     u8_t ch;
973
974     zmw_get_wlan_dev(dev);
975
976     zm_msg0_mm(ZM_LV_3, "Rx beacon");
977
978     /* update Non-ERP flag(wd->ap.nonErpObss) */
979     offset = zfFindElement(dev, buf, ZM_WLAN_EID_ERP);
980     if (offset == 0xffff)
981     {
982         /* 11b OBSS */
983         wd->ap.protectedObss++;
984         return;
985     }
986
987     ch = zmw_rx_buf_readb(dev, buf, offset+2);
988     if ((ch & ZM_WLAN_USE_PROTECTION_BIT) == ZM_WLAN_USE_PROTECTION_BIT)
989     {
990         /* Protected OBSS */
991         wd->ap.protectedObss = 1;
992     }
993
994     return;
995 }
996
997
998 /************************************************************************/
999 /*                                                                      */
1000 /*    FUNCTION DESCRIPTION                  zfProcessAuth               */
1001 /*      Process authenticate management frame.                          */
1002 /*                                                                      */
1003 /*    INPUTS                                                            */
1004 /*      dev : device pointer                                            */
1005 /*      buf : auth frame buffer                                         */
1006 /*                                                                      */
1007 /*    OUTPUTS                                                           */
1008 /*      none                                                            */
1009 /*                                                                      */
1010 /*    AUTHOR                                                            */
1011 /*      Stephen Chen        ZyDAS Technology Corporation    2005.10     */
1012 /*                                                                      */
1013 /************************************************************************/
1014 /* Note : AP allows one authenticating STA at a time, does not          */
1015 /*        support multiple authentication process. Make sure            */
1016 /*        authentication state machine will not be blocked due          */
1017 /*        to incompleted authentication handshake.                      */
1018 void zfApProcessAuth(zdev_t* dev, zbuf_t* buf, u16_t* src, u16_t apId)
1019 {
1020     u16_t algo, seq, status;
1021     u8_t authSharing;
1022     u16_t ret;
1023     u16_t i;
1024     u8_t challengePassed = 0;
1025     u8_t frameCtrl;
1026     u32_t retAlgoSeq;
1027     u32_t retStatus;
1028     zmw_get_wlan_dev(dev);
1029     zmw_declare_for_critical_section();
1030
1031
1032     frameCtrl = zmw_rx_buf_readb(dev, buf, 1);
1033     /* AP : Auth share 3 */
1034     /* shift for WEP IV */
1035     if ((frameCtrl & 0x40) != 0)
1036     {
1037         algo = zmw_rx_buf_readh(dev, buf, 28);
1038         seq = zmw_rx_buf_readh(dev, buf, 30);
1039         status = zmw_rx_buf_readh(dev, buf, 32);
1040     }
1041     else
1042     {
1043         algo = zmw_rx_buf_readh(dev, buf, 24);
1044         seq = zmw_rx_buf_readh(dev, buf, 26);
1045         status = zmw_rx_buf_readh(dev, buf, 28);
1046     }
1047
1048     zm_msg2_mm(ZM_LV_0, "Rx Auth, seq=", seq);
1049
1050     /* Set default to authentication algorithm not support */
1051     retAlgoSeq = 0x20000 | algo;
1052     retStatus = 13; /* authentication algorithm not support */
1053
1054     /* AP : Auth open 1 */
1055     if (algo == 0)
1056     {
1057         if (wd->ap.authAlgo[apId] == 0)
1058         {
1059             retAlgoSeq = 0x20000;
1060             if (seq == 1)
1061             {
1062                 /* AP : update STA to auth */
1063                 ret = zfApAddSta(dev, src, ZM_STATE_AUTH, apId, 0, 0, 0);
1064                 if (ret != 0xffff)
1065                 {
1066                     /* AP : call zfwAuthNotify() for host to judge */
1067                     //zfwAuthNotify(dev, src);
1068
1069                     /* AP : response Auth seq=2, success */
1070                     retStatus = 0;
1071
1072                 }
1073                 else
1074                 {
1075                     /* AP : response Auth seq=2, unspecific error */
1076                     retStatus = 1;
1077                 }
1078             }
1079             else
1080             {
1081                 /* AP : response Auth seq=2, sequence number out of expected */
1082                 retStatus = 14;
1083             }
1084         }
1085     }
1086     /* AP : Auth share 1 */
1087     else if (algo == 1)
1088     {
1089         if (wd->ap.authAlgo[apId] == 1)
1090         {
1091             if (seq == 1)
1092             {
1093                 retAlgoSeq = 0x20001;
1094
1095                 /* critical section */
1096                 zmw_enter_critical_section(dev);
1097                 if (wd->ap.authSharing == 1)
1098                 {
1099                     authSharing = 1;
1100                 }
1101                 else
1102                 {
1103                     authSharing = 0;
1104                     wd->ap.authSharing = 1;
1105                 }
1106                 /* end of critical section */
1107                 zmw_leave_critical_section(dev);
1108
1109                 if (authSharing == 1)
1110                 {
1111                     /* AP : response Auth seq=2, status = fail */
1112                     retStatus = 1;
1113                 }
1114                 else
1115                 {
1116                     /* AP : update STA to preauth */
1117                     zfApAddSta(dev, src, ZM_STATE_PREAUTH, apId, 0, 0, 0);
1118
1119                     /* AP : call zfwAuthNotify() for host to judge */
1120                     //zfwAuthNotify(dev, src);
1121
1122                     /* AP : response Auth seq=2 */
1123                     retStatus = 0;
1124                 }
1125             }
1126             else if (seq == 3)
1127             {
1128                 retAlgoSeq = 0x40001;
1129
1130                 if (wd->ap.authSharing == 1)
1131                 {
1132                     /* check challenge text */
1133                     if (zmw_buf_readh(dev, buf, 30+4) == 0x8010)
1134                     {
1135                         for (i=0; i<128; i++)
1136                         {
1137                             if (wd->ap.challengeText[i]
1138                                         != zmw_buf_readb(dev, buf, 32+i+4))
1139                             {
1140                                 break;
1141                             }
1142                         }
1143                         if (i == 128)
1144                         {
1145                             challengePassed = 1;
1146                         }
1147                     }
1148
1149                     if (challengePassed == 1)
1150                     {
1151                         /* AP : update STA to auth */
1152                         zfApAddSta(dev, src, ZM_STATE_AUTH, apId, 0, 0, 0);
1153
1154                         /* AP : response Auth seq=2 */
1155                         retStatus = 0;
1156                     }
1157                     else
1158                     {
1159                         /* AP : response Auth seq=2, challenge failure */
1160                         retStatus = 15;
1161
1162                         /* TODO : delete STA */
1163                     }
1164
1165                     wd->ap.authSharing = 0;
1166                 }
1167             }
1168             else
1169             {
1170                 retAlgoSeq = 0x40001;
1171                 retStatus = 14;
1172             }
1173         }
1174     }
1175
1176     zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_AUTH, src, retAlgoSeq,
1177             retStatus, apId);
1178     return;
1179 }
1180
1181 void zfApProcessAsocReq(zdev_t* dev, zbuf_t* buf, u16_t* src, u16_t apId)
1182 {
1183     u16_t aid = 0xffff;
1184     u8_t frameType;
1185     u16_t offset;
1186     u8_t staType = 0;
1187     u8_t qosType = 0;
1188     u8_t qosInfo = 0;
1189     u8_t tmp;
1190     u16_t i, j, k;
1191     u16_t encMode = 0;
1192
1193     zmw_get_wlan_dev(dev);
1194     /* AP : check SSID */
1195     offset = zfFindElement(dev, buf, ZM_WLAN_EID_SSID);
1196     if (offset != 0xffff)
1197     {
1198         k = 0;
1199         for (j = 0; j < wd->ap.vapNumber; j++)
1200         {
1201             tmp = zmw_buf_readb(dev, buf, offset+1);
1202             if (tmp
1203                         != wd->ap.ssidLen[j])
1204             {
1205                 k++;
1206             }
1207         }
1208         if (k == wd->ap.vapNumber)
1209         {
1210             goto zlDeauth;
1211         }
1212
1213         k = 0;
1214         for (j = 0; j < wd->ap.vapNumber; j++)
1215         {
1216             for (i=0; i<wd->ap.ssidLen[j]; i++)
1217             {
1218                 tmp = zmw_buf_readb(dev, buf, offset+2+i);
1219                 if (tmp
1220                         != wd->ap.ssid[j][i])
1221                 {
1222                     break;
1223                 }
1224             }
1225             if (i == wd->ap.ssidLen[j])
1226             {
1227                 apId = j;
1228             }
1229             else
1230             {
1231                 k++;
1232             }
1233         }
1234         if (k == wd->ap.vapNumber)
1235         {
1236             goto zlDeauth;
1237         }
1238     }
1239
1240     /* TODO : check capability */
1241
1242     /* AP : check support rate */
1243     offset = zfFindElement(dev, buf, ZM_WLAN_EID_EXTENDED_RATE);
1244     if (offset != 0xffff)
1245     {
1246         /* 11g STA */
1247         staType = 1;
1248     }
1249     //CWYang(+)
1250     offset = zfFindElement(dev, buf, ZM_WLAN_EID_HT_CAPABILITY);
1251     if (offset != 0xffff)
1252     {
1253         /* 11n STA */
1254         staType = 2;
1255     }
1256
1257     /* TODO : do not allow 11b STA to associated in Pure G mode */
1258     if (wd->ap.wlanType[apId] == ZM_WLAN_TYPE_PURE_G && staType == 0)
1259     {
1260         zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, src, 3, 0, 0);
1261         return;
1262     }
1263
1264     /* In pure B mode, we set G STA into B mode */
1265     if (wd->ap.wlanType[apId] == ZM_WLAN_TYPE_PURE_B && staType == 1)
1266     {
1267         staType = 0;
1268     }
1269
1270     /* AP : check 11i and WPA */
1271     /* AP : check 11h */
1272
1273     /* AP : check WME */
1274     offset = zfFindWifiElement(dev, buf, 2, 0);
1275     if (offset != 0xffff)
1276     {
1277         /* WME STA */
1278         qosType = 1;
1279         zm_msg0_mm(ZM_LV_0, "WME STA");
1280
1281         if (wd->ap.uapsdEnabled != 0)
1282         {
1283             qosInfo = zmw_rx_buf_readb(dev, buf, offset+8);
1284         }
1285     }
1286
1287     if (wd->ap.wpaSupport[apId] == 1)
1288     {
1289         offset = zfFindElement(dev, buf, ZM_WLAN_EID_WPA_IE);
1290         if (offset != 0xffff)
1291         {
1292             /* get WPA IE */
1293             u8_t length = zmw_rx_buf_readb(dev, buf, offset+1);
1294             if (length+2 < ZM_MAX_WPAIE_SIZE)
1295             {
1296                 zfCopyFromRxBuffer(dev, buf, wd->ap.stawpaIe[apId], offset, length+2);
1297                 wd->ap.stawpaLen[apId] = length+2;
1298                 encMode = 1;
1299
1300
1301                 zm_msg1_mm(ZM_LV_0, "WPA Mode zfwAsocNotify, apId=", apId);
1302
1303                 /* AP : Call zfwAsocNotify() */
1304                 if (wd->zfcbAsocNotify != NULL)
1305                 {
1306                     wd->zfcbAsocNotify(dev, src, wd->ap.stawpaIe[apId], wd->ap.stawpaLen[apId], apId);
1307                 }
1308             }
1309             else
1310             {
1311                 goto zlDeauth;
1312             }
1313         }
1314         else if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_RSN_IE)) != 0xffff )
1315         {
1316             /* get RSN IE */
1317             u8_t length = zmw_rx_buf_readb(dev, buf, offset+1);
1318             if (length+2 < ZM_MAX_WPAIE_SIZE)
1319             {
1320                 zfCopyFromRxBuffer(dev, buf, wd->ap.stawpaIe[apId], offset, length+2);
1321                 wd->ap.stawpaLen[apId] = length+2;
1322                 encMode = 1;
1323
1324                 zm_msg1_mm(ZM_LV_0, "RSN Mode zfwAsocNotify, apId=", apId);
1325
1326                 /* AP : Call zfwAsocNotify() */
1327                 if (wd->zfcbAsocNotify != NULL)
1328                 {
1329                     wd->zfcbAsocNotify(dev, src, wd->ap.stawpaIe[apId], wd->ap.stawpaLen[apId], apId);
1330                 }
1331             }
1332             else
1333             {
1334                 goto zlDeauth;
1335             }
1336         }
1337 #ifdef ZM_ENABLE_CENC
1338         else if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_CENC_IE)) != 0xffff )
1339         {
1340             /* get CENC IE */
1341             u8_t length = zmw_rx_buf_readb(dev, buf, offset+1);
1342
1343             if (length+2 < ZM_MAX_WPAIE_SIZE)
1344             {
1345                 zfCopyFromRxBuffer(dev, buf, wd->ap.stawpaIe[apId], offset, length+2);
1346                 wd->ap.stawpaLen[apId] = length+2;
1347                 encMode = 1;
1348
1349                 zm_msg1_mm(ZM_LV_0, "CENC Mode zfwAsocNotify, apId=", apId);
1350
1351                 /* AP : Call zfwAsocNotify() */
1352                 if (wd->zfcbCencAsocNotify != NULL)
1353                 {
1354                     wd->zfcbCencAsocNotify(dev, src, wd->ap.stawpaIe[apId],
1355                             wd->ap.stawpaLen[apId], apId);
1356                 }
1357             }
1358             else
1359             {
1360                 goto zlDeauth;
1361             }
1362         }
1363 #endif //ZM_ENABLE_CENC
1364         else
1365         {   /* ap is encryption but sta has no wpa/rsn ie */
1366             zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, src, 6, 0, 0);
1367             return;
1368         }
1369     }
1370     /* sta has wpa/rsn ie but ap is no encryption */
1371     if ((wd->ap.wpaSupport[apId] == 0) && (encMode == 1))
1372     {
1373         zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, src, 6, 0, 0);
1374         return;
1375     }
1376
1377     /* AP : update STA to asoc */
1378     aid = zfApAddSta(dev, src, ZM_STATE_ASOC, apId, staType, qosType, qosInfo);
1379
1380     zfApStoreAsocReqIe(dev, buf, aid);
1381
1382 zlDeauth:
1383     /* AP : send asoc rsp2 */
1384     if (aid != 0xffff)
1385     {
1386         frameType = zmw_rx_buf_readb(dev, buf, 0);
1387
1388         if (frameType == ZM_WLAN_FRAME_TYPE_ASOCREQ)
1389         {
1390             zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_ASOCRSP, src, 0, aid+1, apId);
1391         }
1392         else
1393         {
1394             zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_REASOCRSP, src, 0, aid+1, apId);
1395         }
1396     }
1397     else
1398     {
1399         /* TODO : send deauthentication */
1400         zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, src, 6, 0, 0);
1401     }
1402
1403     return;
1404 }
1405
1406 void zfApStoreAsocReqIe(zdev_t* dev, zbuf_t* buf, u16_t aid)
1407 {
1408     //struct zsWlanAssoFrameHeader* pAssoFrame;
1409     //u8_t  pBuf[sizeof(struct zsWlanAssoFrameHeader)];
1410     u16_t offset;
1411     u32_t i;
1412     u16_t length;
1413     u8_t  *htcap;
1414
1415     zmw_get_wlan_dev(dev);
1416
1417     for (i=0; i<wd->sta.asocRspFrameBodySize; i++)
1418     {
1419         wd->sta.asocRspFrameBody[i] = zmw_rx_buf_readb(dev, buf, i+24);
1420     }
1421     /* capability: 2 octets */
1422     offset = 24;
1423
1424     /* Listen interval: 2 octets */
1425     offset = 26;
1426
1427     /* SSID */
1428     offset = 28;
1429
1430     /* supported rates */
1431     offset = zfFindElement(dev, buf, ZM_WLAN_EID_SUPPORT_RATE);
1432     if (offset == 0xffff)
1433         return;
1434     length = zmw_rx_buf_readb(dev, buf, offset + 1);
1435
1436     /* extended supported rates */
1437     offset = zfFindElement(dev, buf, ZM_WLAN_EID_EXTENDED_RATE);
1438     if (offset == 0xffff)
1439         return;
1440     length = zmw_rx_buf_readb(dev, buf, offset + 1);
1441
1442     /* power capability:4 octets */
1443     offset = offset + 2 + length;
1444
1445     /* supported channels: 4 octets */
1446     offset = offset + 2 + 4;
1447
1448     /* RSN */
1449
1450     /* QoS */
1451
1452     /* HT capabilities: 28 octets */
1453     offset = zfFindElement(dev, buf, ZM_WLAN_EID_HT_CAPABILITY);
1454     if (offset != 0xffff) {
1455         /* atheros pre n */
1456         htcap = (u8_t *)&wd->ap.ie[aid].HtCap;
1457         htcap[0] = zmw_rx_buf_readb(dev, buf, offset);
1458         htcap[1] = 26;
1459         for (i=1; i<=26; i++)
1460         {
1461             htcap[i+1] = zmw_rx_buf_readb(dev, buf, offset + i);
1462             zm_debug_msg2("ASOC:  HT Capabilities, htcap=", htcap[i+1]);
1463         }
1464         return;
1465     }
1466     else if ((offset = zfFindElement(dev, buf, ZM_WLAN_PREN2_EID_HTCAPABILITY)) != 0xffff) {
1467         /* pre n 2.0 standard */
1468         htcap = (u8_t *)&wd->ap.ie[aid].HtCap;
1469         for (i=0; i<28; i++)
1470         {
1471             htcap[i] = zmw_rx_buf_readb(dev, buf, offset + i);
1472             zm_debug_msg2("ASOC:  HT Capabilities, htcap=", htcap[i]);
1473         }
1474     }
1475     else {
1476         /* not 11n AP */
1477         return;
1478     }
1479
1480
1481     /* supported regulatory classes */
1482     offset = offset + length;
1483     //length = zmw_rx_buf_readb(dev, buf, offset + 1);
1484     {
1485     u8_t *htcap;
1486     htcap = (u8_t *)&wd->sta.ie.HtInfo;
1487     //zm_debug_msg2("ASOC:  HT Capabilities info=", ((u16_t *)htcap)[1]);
1488     //zm_debug_msg2("ASOC:  A-MPDU parameters=", htcap[4]);
1489     //zm_debug_msg2("ASOC:  Supported MCS set=", ((u32_t *)htcap)[1]>>8);
1490     }
1491
1492 }
1493
1494 void zfApProcessAsocRsp(zdev_t* dev, zbuf_t* buf)
1495 {
1496
1497 }
1498
1499 void zfApProcessDeauth(zdev_t* dev, zbuf_t* buf, u16_t* src, u16_t apId)
1500 {
1501     u16_t aid;
1502     zmw_get_wlan_dev(dev);
1503     zmw_declare_for_critical_section();
1504
1505     zmw_enter_critical_section(dev);
1506     /* AP : if SA=associated STA then deauthenticate STA */
1507     aid = zfApFindSta(dev, src);
1508     if (aid != 0xffff)
1509     {
1510         /* Clear STA table */
1511         wd->ap.staTable[aid].valid = 0;
1512         if (wd->zfcbDisAsocNotify != NULL)
1513         {
1514             wd->zfcbDisAsocNotify(dev, (u8_t*)src, apId);
1515         }
1516     }
1517     zmw_leave_critical_section(dev);
1518
1519 }
1520
1521 void zfApProcessDisasoc(zdev_t* dev, zbuf_t* buf, u16_t* src, u16_t apId)
1522 {
1523     u16_t aid;
1524     zmw_get_wlan_dev(dev);
1525     zmw_declare_for_critical_section();
1526
1527     zmw_enter_critical_section(dev);
1528     /* AP : if SA=associated STA then deauthenticate STA */
1529     aid = zfApFindSta(dev, src);
1530     if (aid != 0xffff)
1531     {
1532         /* Clear STA table */
1533         wd->ap.staTable[aid].valid = 0;
1534         zmw_leave_critical_section(dev);
1535         if (wd->zfcbDisAsocNotify != NULL)
1536         {
1537             wd->zfcbDisAsocNotify(dev, (u8_t*)src, apId);
1538         }
1539     }
1540     zmw_leave_critical_section(dev);
1541
1542 }
1543
1544
1545 void zfApProcessProbeRsp(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* AddInfo)
1546 {
1547 #if 0
1548     zmw_get_wlan_dev(dev);
1549
1550     zm_msg0_mm(ZM_LV_0, "Rx probersp");
1551
1552     /* Gather scan result */
1553
1554     //zm_debug_msg1("bssList Count = ", wd->sta.bssList.bssCount);
1555     /* return if not in scanning */
1556     if ((wd->heartBeatNotification & ZM_BSSID_LIST_SCAN)
1557             != ZM_BSSID_LIST_SCAN)
1558     {
1559         return;
1560     }
1561
1562     //if ( wd->sta.pUpdateBssList->bssCount == ZM_MAX_BSS )
1563     if ( wd->sta.bssList.bssCount == ZM_MAX_BSS )
1564     {
1565         return;
1566     }
1567
1568     zfProcessProbeRsp(dev, buf, AddInfo);
1569
1570 #endif
1571 }
1572
1573 /************************************************************************/
1574 /*                                                                      */
1575 /*    FUNCTION DESCRIPTION                  zfApAddIeSsid               */
1576 /*      Add AP information element SSID to buffer.                      */
1577 /*                                                                      */
1578 /*    INPUTS                                                            */
1579 /*      dev : device pointer                                            */
1580 /*      buf : buffer to add information element                         */
1581 /*      offset : add information element from this offset               */
1582 /*      vap : virtual AP ID                                             */
1583 /*                                                                      */
1584 /*    OUTPUTS                                                           */
1585 /*      buffer offset after adding information element                  */
1586 /*                                                                      */
1587 /*    AUTHOR                                                            */
1588 /*      Stephen Chen        ZyDAS Technology Corporation    2005.11     */
1589 /*                                                                      */
1590 /************************************************************************/
1591 u16_t zfApAddIeSsid(zdev_t* dev, zbuf_t* buf, u16_t offset, u16_t vap)
1592 {
1593     u16_t i;
1594
1595     zmw_get_wlan_dev(dev);
1596
1597     /* Element ID */
1598     zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_SSID);
1599
1600     /* Element Length */
1601     zmw_tx_buf_writeb(dev, buf, offset++, wd->ap.ssidLen[vap]);
1602
1603     /* Information : SSID */
1604     for (i=0; i<wd->ap.ssidLen[vap]; i++)
1605     {
1606         zmw_tx_buf_writeb(dev, buf, offset++, wd->ap.ssid[vap][i]);
1607     }
1608
1609     return offset;
1610 }
1611
1612
1613 /************************************************************************/
1614 /*                                                                      */
1615 /*    FUNCTION DESCRIPTION                  zfApAddIeTim                */
1616 /*      Add AP information element TIM to buffer.                       */
1617 /*                                                                      */
1618 /*    INPUTS                                                            */
1619 /*      dev : device pointer                                            */
1620 /*      buf : buffer to add information element                         */
1621 /*      offset : add information element from this offset               */
1622 /*      vap : virtual AP ID                                             */
1623 /*                                                                      */
1624 /*    OUTPUTS                                                           */
1625 /*      buffer offset after adding information element                  */
1626 /*                                                                      */
1627 /*    AUTHOR                                                            */
1628 /*      Stephen Chen        ZyDAS Technology Corporation    2005.11     */
1629 /*                                                                      */
1630 /************************************************************************/
1631 u16_t zfApAddIeTim(zdev_t* dev, zbuf_t* buf, u16_t offset, u16_t vap)
1632 {
1633     u8_t uniBitMap[9];
1634     u16_t highestByte;
1635     u16_t i;
1636     u16_t lenOffset;
1637     u16_t id;
1638     u16_t dst[3];
1639     u16_t aid;
1640     u16_t bitPosition;
1641     u16_t bytePosition;
1642     zbuf_t* psBuf;
1643     zbuf_t* tmpBufArray[ZM_UNI_ARRAY_SIZE];
1644     u16_t tmpBufArraySize = 0;
1645
1646     zmw_get_wlan_dev(dev);
1647
1648     zmw_declare_for_critical_section();
1649
1650     /* Element ID */
1651     zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_TIM);
1652
1653     /* offset of Element Length */
1654     lenOffset = offset++;
1655
1656     /* Information : TIM */
1657     /* DTIM count */
1658     /* TODO : Doesn't work for Virtual AP's case */
1659     wd->CurrentDtimCount++;
1660     if (wd->CurrentDtimCount >= wd->dtim)
1661     {
1662         wd->CurrentDtimCount = 0;
1663     }
1664     zmw_tx_buf_writeb(dev, buf, offset++, wd->CurrentDtimCount);
1665     /* DTIM period */
1666     zmw_tx_buf_writeb(dev, buf, offset++, wd->dtim);
1667     /* bitmap offset */
1668     zmw_tx_buf_writeb(dev, buf, offset++, 0);
1669
1670     /* Update BCMC bit */
1671     if (wd->CurrentDtimCount == 0)
1672     {
1673         zmw_enter_critical_section(dev);
1674         wd->ap.timBcmcBit[vap] = (wd->ap.bcmcTail[vap]!=wd->ap.bcmcHead[vap])?1:0;
1675         zmw_leave_critical_section(dev);
1676     }
1677     else
1678     {
1679         wd->ap.timBcmcBit[vap] = 0;
1680     }
1681
1682     /* Update Unicast bitmap */
1683     /* reset bit map */
1684     for (i=0; i<9; i++)
1685     {
1686         uniBitMap[i] = 0;
1687     }
1688     highestByte = 0;
1689 #if 1
1690
1691     zmw_enter_critical_section(dev);
1692
1693     id = wd->ap.uniHead;
1694     while (id != wd->ap.uniTail)
1695     {
1696         psBuf = wd->ap.uniArray[id];
1697
1698         /* TODO : Aging PS frame after queuing for more than 10 seconds */
1699
1700         /* get destination STA's aid */
1701         dst[0] = zmw_tx_buf_readh(dev, psBuf, 0);
1702         dst[1] = zmw_tx_buf_readh(dev, psBuf, 2);
1703         dst[2] = zmw_tx_buf_readh(dev, psBuf, 4);
1704         aid = zfApFindSta(dev, dst);
1705         if (aid != 0xffff)
1706         {
1707             if (wd->ap.staTable[aid].psMode != 0)
1708             {
1709                 zm_msg1_mm(ZM_LV_0, "aid=",aid);
1710                 aid++;
1711                 zm_assert(aid<=64);
1712                 bitPosition = (1 << (aid & 0x7));
1713                 bytePosition = (aid >> 3);
1714                 uniBitMap[bytePosition] |= bitPosition;
1715
1716                 if (bytePosition>highestByte)
1717                 {
1718                     highestByte = bytePosition;
1719                 }
1720                 id = (id+1) & (ZM_UNI_ARRAY_SIZE-1);
1721             }
1722             else
1723             {
1724                 zm_msg0_mm(ZM_LV_0, "Send PS frame which STA no longer in PS mode");
1725                 /* Send PS frame which STA no longer in PS mode */
1726                 zfApRemoveFromPsQueue(dev, id, dst);
1727                 tmpBufArray[tmpBufArraySize++] = psBuf;
1728             }
1729         }
1730         else
1731         {
1732             zm_msg0_mm(ZM_LV_0, "Free garbage PS frame");
1733             /* Free garbage PS frame */
1734             zfApRemoveFromPsQueue(dev, id, dst);
1735             zfwBufFree(dev, psBuf, 0);
1736         }
1737     }
1738
1739     zmw_leave_critical_section(dev);
1740 #endif
1741
1742     zfQueueGenerateUapsdTim(dev, wd->ap.uapsdQ, uniBitMap, &highestByte);
1743
1744     zm_msg1_mm(ZM_LV_3, "bm=",uniBitMap[0]);
1745     zm_msg1_mm(ZM_LV_3, "highestByte=",highestByte);
1746     zm_msg1_mm(ZM_LV_3, "timBcmcBit[]=",wd->ap.timBcmcBit[vap]);
1747
1748     /* bitmap */
1749     zmw_tx_buf_writeb(dev, buf, offset++,
1750                          uniBitMap[0] | wd->ap.timBcmcBit[vap]);
1751     for (i=0; i<highestByte; i++)
1752     {
1753         zmw_tx_buf_writeb(dev, buf, offset++, uniBitMap[i+1]);
1754     }
1755
1756     /* Element Length */
1757     zmw_tx_buf_writeb(dev, buf, lenOffset, highestByte+4);
1758
1759     for (i=0; i<tmpBufArraySize; i++)
1760     {
1761         /* Put to VTXQ[ac] */
1762         zfPutVtxq(dev, tmpBufArray[i]);
1763     }
1764     /* Push VTXQ[ac] */
1765     zfPushVtxq(dev);
1766
1767     return offset;
1768 }
1769
1770
1771
1772 /************************************************************************/
1773 /*                                                                      */
1774 /*    FUNCTION DESCRIPTION                  zfApRemoveFromPsQueue       */
1775 /*      Remove zbuf from PS queue.                                      */
1776 /*                                                                      */
1777 /*    INPUTS                                                            */
1778 /*      dev : device pointer                                            */
1779 /*      id : index in ps queue                                          */
1780 /*                                                                      */
1781 /*    OUTPUTS                                                           */
1782 /*      more data bit                                                   */
1783 /*                                                                      */
1784 /*    AUTHOR                                                            */
1785 /*      Stephen Chen        Atheros Communications, INC.    2007.1      */
1786 /*                                                                      */
1787 /************************************************************************/
1788 u8_t zfApRemoveFromPsQueue(zdev_t* dev, u16_t id, u16_t* addr)
1789 {
1790     u16_t dst[3];
1791     u16_t nid;
1792     u8_t moreData = 0;
1793     zmw_get_wlan_dev(dev);
1794
1795     wd->ap.uniTail = (wd->ap.uniTail-1) & (ZM_UNI_ARRAY_SIZE-1);
1796     while (id != wd->ap.uniTail)
1797     {
1798         nid = (id + 1) & (ZM_UNI_ARRAY_SIZE - 1);
1799         wd->ap.uniArray[id] = wd->ap.uniArray[nid];
1800
1801         /* Search until tail to config more data bit */
1802         dst[0] = zmw_buf_readh(dev, wd->ap.uniArray[id], 0);
1803         dst[1] = zmw_buf_readh(dev, wd->ap.uniArray[id], 2);
1804         dst[2] = zmw_buf_readh(dev, wd->ap.uniArray[id], 4);
1805         if ((addr[0] == dst[0]) && (addr[1] == dst[1])
1806                 && (addr[2] == dst[2]))
1807         {
1808             moreData = 0x20;
1809         }
1810
1811         id = nid;
1812     }
1813     return moreData;
1814 }
1815
1816 /************************************************************************/
1817 /*                                                                      */
1818 /*    FUNCTION DESCRIPTION                  zfApAddIeWmePara            */
1819 /*      Add WME Parameter Element to buffer.                            */
1820 /*                                                                      */
1821 /*    INPUTS                                                            */
1822 /*      dev : device pointer                                            */
1823 /*      buf : buffer to add information element                         */
1824 /*      offset : add information element from this offset               */
1825 /*      vap : virtual AP ID                                             */
1826 /*                                                                      */
1827 /*    OUTPUTS                                                           */
1828 /*      buffer offset after adding information element                  */
1829 /*                                                                      */
1830 /*    AUTHOR                                                            */
1831 /*      Stephen Chen        ZyDAS Technology Corporation    2006.1      */
1832 /*                                                                      */
1833 /************************************************************************/
1834 u16_t zfApAddIeWmePara(zdev_t* dev, zbuf_t* buf, u16_t offset, u16_t vap)
1835 {
1836     zmw_get_wlan_dev(dev);
1837
1838     /* Element ID */
1839     zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_WIFI_IE);
1840
1841     /* Element Length */
1842     zmw_tx_buf_writeb(dev, buf, offset++, 24);
1843
1844     /* OUI */
1845     zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
1846     zmw_tx_buf_writeb(dev, buf, offset++, 0x50);
1847     zmw_tx_buf_writeb(dev, buf, offset++, 0xF2);
1848     zmw_tx_buf_writeb(dev, buf, offset++, 0x02);
1849     zmw_tx_buf_writeb(dev, buf, offset++, 0x01);
1850     zmw_tx_buf_writeb(dev, buf, offset++, 0x01);
1851
1852     /* QoS Info */
1853     if (wd->ap.uapsdEnabled)
1854     {
1855         zmw_tx_buf_writeb(dev, buf, offset++, 0x81);
1856     }
1857     else
1858     {
1859     zmw_tx_buf_writeb(dev, buf, offset++, 0x01);
1860     }
1861
1862     /* Reserved */
1863     zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
1864
1865     /* Best Effort AC parameters */
1866     zmw_tx_buf_writeb(dev, buf, offset++, 0x03);
1867     zmw_tx_buf_writeb(dev, buf, offset++, 0xA4);
1868     zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
1869     zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
1870     /* Backfround AC parameters */
1871     zmw_tx_buf_writeb(dev, buf, offset++, 0x27);
1872     zmw_tx_buf_writeb(dev, buf, offset++, 0xA4);
1873     zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
1874     zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
1875     /* Video AC parameters */
1876     zmw_tx_buf_writeb(dev, buf, offset++, 0x42);
1877     zmw_tx_buf_writeb(dev, buf, offset++, 0x43);
1878     zmw_tx_buf_writeb(dev, buf, offset++, 0x5E);
1879     zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
1880     /* Voice AC parameters */
1881     zmw_tx_buf_writeb(dev, buf, offset++, 0x62);
1882     zmw_tx_buf_writeb(dev, buf, offset++, 0x32);
1883     zmw_tx_buf_writeb(dev, buf, offset++, 0x2F);
1884     zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
1885
1886     return offset;
1887 }
1888
1889
1890 /************************************************************************/
1891 /*                                                                      */
1892 /*    FUNCTION DESCRIPTION                  zfApSendBeacon              */
1893 /*      Sned AP mode beacon.                                            */
1894 /*                                                                      */
1895 /*    INPUTS                                                            */
1896 /*      dev : device pointer                                            */
1897 /*                                                                      */
1898 /*    OUTPUTS                                                           */
1899 /*      none                                                            */
1900 /*                                                                      */
1901 /*    AUTHOR                                                            */
1902 /*      Stephen Chen        ZyDAS Technology Corporation    2005.11     */
1903 /*                                                                      */
1904 /************************************************************************/
1905 void zfApSendBeacon(zdev_t* dev)
1906 {
1907     zbuf_t* buf;
1908     u16_t offset;
1909     u16_t vap;
1910     u16_t seq;
1911
1912     zmw_get_wlan_dev(dev);
1913
1914     zmw_declare_for_critical_section();
1915
1916     wd->ap.beaconCounter++;
1917     if (wd->ap.beaconCounter >= wd->ap.vapNumber)
1918     {
1919         wd->ap.beaconCounter = 0;
1920     }
1921     vap = wd->ap.beaconCounter;
1922
1923
1924     zm_msg1_mm(ZM_LV_2, "Send beacon, vap=", vap);
1925
1926     /* TBD : Maximum size of beacon */
1927     buf = zfwBufAllocate(dev, 1024);
1928     if (buf == NULL)
1929     {
1930         zm_msg0_mm(ZM_LV_0, "Alloc beacon buf Fail!");
1931         return;
1932     }
1933
1934     offset = 0;
1935
1936     /* wlan header */
1937     /* Frame control */
1938     zmw_tx_buf_writeh(dev, buf, offset, 0x0080);
1939     offset+=2;
1940     /* Duration */
1941     zmw_tx_buf_writeh(dev, buf, offset, 0x0000);
1942     offset+=2;
1943     /* Address 1 */
1944     zmw_tx_buf_writeh(dev, buf, offset, 0xffff);
1945     offset+=2;
1946     zmw_tx_buf_writeh(dev, buf, offset, 0xffff);
1947     offset+=2;
1948     zmw_tx_buf_writeh(dev, buf, offset, 0xffff);
1949     offset+=2;
1950     /* Address 2 */
1951     zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[0]);
1952     offset+=2;
1953     zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[1]);
1954     offset+=2;
1955 #ifdef ZM_VAPMODE_MULTILE_SSID
1956     zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[2]); //Multiple SSID
1957 #else
1958     zmw_tx_buf_writeh(dev, buf, offset, (wd->macAddr[2]+(vap<<8))); //VAP
1959 #endif
1960     offset+=2;
1961     /* Address 3 */
1962     zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[0]);
1963     offset+=2;
1964     zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[1]);
1965     offset+=2;
1966 #ifdef ZM_VAPMODE_MULTILE_SSID
1967     zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[2]); //Multiple SSID
1968 #else
1969     zmw_tx_buf_writeh(dev, buf, offset, (wd->macAddr[2]+(vap<<8))); //VAP
1970 #endif
1971     offset+=2;
1972
1973     /* Sequence number */
1974     zmw_enter_critical_section(dev);
1975     seq = ((wd->mmseq++)<<4);
1976     zmw_leave_critical_section(dev);
1977     zmw_tx_buf_writeh(dev, buf, offset, seq);
1978     offset+=2;
1979
1980     /* 24-31 Time Stamp : hardware will fill this field */
1981     zmw_tx_buf_writeh(dev, buf, offset, 0);
1982     zmw_tx_buf_writeh(dev, buf, offset+2, 0);
1983     zmw_tx_buf_writeh(dev, buf, offset+4, 0);
1984     zmw_tx_buf_writeh(dev, buf, offset+6, 0);
1985     offset+=8;
1986
1987     /* Beacon Interval */
1988     zmw_tx_buf_writeh(dev, buf, offset, wd->beaconInterval);
1989     offset+=2;
1990
1991     /* Capability */
1992     zmw_tx_buf_writeh(dev, buf, offset, wd->ap.capab[vap]);
1993     offset+=2;
1994
1995     /* SSID */
1996     if (wd->ap.hideSsid[vap] == 0)
1997     {
1998         offset = zfApAddIeSsid(dev, buf, offset, vap);
1999     }
2000     else
2001     {
2002         zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_SSID);
2003         zmw_tx_buf_writeb(dev, buf, offset++, 0);
2004
2005     }
2006
2007     /* Support Rate */
2008     if ( wd->frequency < 3000 )
2009     {
2010     offset = zfMmAddIeSupportRate(dev, buf, offset,
2011                                   ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_CCK);
2012     }
2013     else
2014     {
2015         offset = zfMmAddIeSupportRate(dev, buf, offset,
2016                                   ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_OFDM);
2017     }
2018
2019     /* DS parameter set */
2020     offset = zfMmAddIeDs(dev, buf, offset);
2021
2022     /* TIM */
2023     offset = zfApAddIeTim(dev, buf, offset, vap);
2024
2025     /* If WLAN Type is not PURE B */
2026     if (wd->ap.wlanType[vap] != ZM_WLAN_TYPE_PURE_B)
2027     {
2028         if ( wd->frequency < 3000 )
2029         {
2030         /* ERP Information */
2031         offset = zfMmAddIeErp(dev, buf, offset);
2032
2033         /* Extended Supported Rates */
2034         offset = zfMmAddIeSupportRate(dev, buf, offset,
2035                                       ZM_WLAN_EID_EXTENDED_RATE, ZM_RATE_SET_OFDM);
2036     }
2037     }
2038
2039     /* TODO : country information */
2040     /* TODO : RSN */
2041     if (wd->ap.wpaSupport[vap] == 1)
2042     {
2043         offset = zfMmAddIeWpa(dev, buf, offset, vap);
2044     }
2045
2046     /* WME Parameters */
2047     if (wd->ap.qosMode == 1)
2048     {
2049         offset = zfApAddIeWmePara(dev, buf, offset, vap);
2050     }
2051
2052     /* HT Capabilities Info */
2053     offset = zfMmAddHTCapability(dev, buf, offset);
2054
2055     /* Extended HT Capabilities Info */
2056     offset = zfMmAddExtendedHTCapability(dev, buf, offset);
2057
2058     /* 1212 : write to beacon fifo */
2059     /* 1221 : write to share memory */
2060     zfHpSendBeacon(dev, buf, offset);
2061
2062     /* Free beacon buffer */
2063     /* TODO: In order to fit the madwifi beacon architecture, we need to
2064        free beacon buffer in the HAL layer.
2065      */
2066
2067     //zfwBufFree(dev, buf, 0);
2068 }
2069
2070
2071 /************************************************************************/
2072 /*                                                                      */
2073 /*    FUNCTION DESCRIPTION                  zfIntrabssForward           */
2074 /*      Called to transmit intra-BSS frame from upper layer.            */
2075 /*                                                                      */
2076 /*    INPUTS                                                            */
2077 /*      dev : device pointer                                            */
2078 /*      buf : buffer pointer                                            */
2079 /*      vap : virtual AP                                                */
2080 /*                                                                      */
2081 /*    OUTPUTS                                                           */
2082 /*      1 : unicast intras-BSS frame                                    */
2083 /*      0 : other frames                                                */
2084 /*                                                                      */
2085 /*    AUTHOR                                                            */
2086 /*      Stephen             ZyDAS Technology Corporation    2005.11     */
2087 /*                                                                      */
2088 /************************************************************************/
2089 u16_t zfIntrabssForward(zdev_t* dev, zbuf_t* buf, u8_t srcVap)
2090 {
2091     u16_t err;
2092     u16_t asocFlag = 0;
2093     u16_t dst[3];
2094     u16_t aid;
2095     u16_t staState;
2096     zbuf_t* txBuf;
2097     u16_t len;
2098     u16_t i;
2099     u16_t temp;
2100     u16_t ret;
2101     u8_t vap = 0;
2102 #ifdef ZM_ENABLE_NATIVE_WIFI
2103     dst[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET);
2104     dst[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+2);
2105     dst[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+4);
2106 #else
2107     dst[0] = zmw_rx_buf_readh(dev, buf, 0);
2108     dst[1] = zmw_rx_buf_readh(dev, buf, 2);
2109     dst[2] = zmw_rx_buf_readh(dev, buf, 4);
2110 #endif  // ZM_ENABLE_NATIVE_WIFI
2111
2112     /* Do Intra-BSS forward(data copy) if necessary*/
2113     if ((dst[0]&0x1) != 0x1)
2114     {
2115         aid = zfApGetSTAInfo(dev, dst, &staState, &vap);
2116         if ((aid != 0xffff) && (staState == ZM_STATE_ASOC) && (srcVap == vap))
2117         {
2118             asocFlag = 1;
2119             zm_msg0_rx(ZM_LV_2, "Intra-BSS forward : asoc STA");
2120         }
2121
2122     }
2123     else
2124     {
2125         vap = srcVap;
2126         zm_msg0_rx(ZM_LV_2, "Intra-BSS forward : BCorMC");
2127     }
2128
2129     /* destination address = associated STA or BC/MC */
2130     if ((asocFlag == 1) || ((dst[0]&0x1) == 0x1))
2131     {
2132         /* Allocate frame */
2133         txBuf = zfwBufAllocate(dev, ZM_RX_FRAME_SIZE);
2134         if (txBuf == NULL)
2135         {
2136             zm_msg0_rx(ZM_LV_1, "Alloc intra-bss buf Fail!");
2137             goto zlAllocError;
2138         }
2139
2140         /* Copy frame */
2141         len = zfwBufGetSize(dev, buf);
2142         for (i=0; i<len; i+=2)
2143         {
2144             temp = zmw_rx_buf_readh(dev, buf, i);
2145             zmw_tx_buf_writeh(dev, txBuf, i, temp);
2146         }
2147         zfwBufSetSize(dev, txBuf, len);
2148
2149 #ifdef ZM_ENABLE_NATIVE_WIFI
2150         /* Tx-A2 = Rx-A1, Tx-A3 = Rx-A2, Tx-A1 = Rx-A3 */
2151         for (i=0; i<6; i+=2)
2152         {
2153             temp = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET+i);
2154             zmw_tx_buf_writeh(dev, txBuf, ZM_WLAN_HEADER_A2_OFFSET+i, temp);
2155             temp = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+i);
2156             zmw_tx_buf_writeh(dev, txBuf, ZM_WLAN_HEADER_A3_OFFSET+i, temp);
2157             temp = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+i);
2158             zmw_tx_buf_writeh(dev, txBuf, ZM_WLAN_HEADER_A1_OFFSET+i, temp);
2159         }
2160
2161         #endif
2162
2163         /* Transmit frame */
2164         /* Return error if port is disabled */
2165         err = zfTxPortControl(dev, txBuf, vap);
2166         if (err == ZM_PORT_DISABLED)
2167         {
2168             err = ZM_ERR_TX_PORT_DISABLED;
2169             goto zlTxError;
2170         }
2171
2172 #if 1
2173         /* AP : Buffer frame for power saving STA */
2174         ret = zfApBufferPsFrame(dev, txBuf, vap);
2175         if (ret == 0)
2176         {
2177             /* forward frame if not been buffered */
2178             #if 1
2179             /* Put to VTXQ[ac] */
2180             ret = zfPutVtxq(dev, txBuf);
2181             /* Push VTXQ[ac] */
2182             zfPushVtxq(dev);
2183             #else
2184             zfTxSendEth(dev, txBuf, vap, ZM_INTERNAL_ALLOC_BUF, 0);
2185             #endif
2186
2187         }
2188 #endif
2189     }
2190     return asocFlag;
2191
2192 zlTxError:
2193     zfwBufFree(dev, txBuf, 0);
2194 zlAllocError:
2195     return asocFlag;
2196 }
2197
2198 struct zsMicVar* zfApGetRxMicKey(zdev_t* dev, zbuf_t* buf)
2199 {
2200     u8_t sa[6];
2201     u16_t id = 0, macAddr[3];
2202
2203     zmw_get_wlan_dev(dev);
2204
2205     zfCopyFromRxBuffer(dev, buf, sa, ZM_WLAN_HEADER_A2_OFFSET, 6);
2206
2207     macAddr[0] = sa[0] + (sa[1] << 8);
2208     macAddr[1] = sa[2] + (sa[3] << 8);
2209     macAddr[2] = sa[4] + (sa[5] << 8);
2210
2211     id = zfApFindSta(dev, macAddr);
2212     if (id != 0xffff)
2213         return (&wd->ap.staTable[id].rxMicKey);
2214
2215     return NULL;
2216 }
2217
2218 struct zsMicVar* zfApGetTxMicKey(zdev_t* dev, zbuf_t* buf, u8_t* qosType)
2219 {
2220     u8_t da[6];
2221     u16_t id = 0, macAddr[3];
2222
2223     zmw_get_wlan_dev(dev);
2224
2225     zfCopyFromIntTxBuffer(dev, buf, da, 0, 6);
2226
2227     macAddr[0] = da[0] + (da[1] << 8);
2228     macAddr[1] = da[2] + (da[3] << 8);
2229     macAddr[2] = da[4] + (da[5] << 8);
2230
2231     if ((macAddr[0] & 0x1))
2232     {
2233         return (&wd->ap.bcMicKey[0]);
2234     }
2235     else if ((id = zfApFindSta(dev, macAddr)) != 0xffff)
2236     {
2237         *qosType = wd->ap.staTable[id].qosType;
2238         return (&wd->ap.staTable[id].txMicKey);
2239     }
2240
2241     return NULL;
2242 }
2243
2244 u16_t zfApUpdatePsBit(zdev_t* dev, zbuf_t* buf, u8_t* vap, u8_t* uapsdTrig)
2245 {
2246     u16_t staState;
2247     u16_t aid;
2248     u16_t psBit;
2249     u16_t src[3];
2250     u16_t dst[1];
2251     u16_t i;
2252
2253     zmw_get_wlan_dev(dev);
2254
2255     src[0] = zmw_rx_buf_readh(dev, buf, 10);
2256     src[1] = zmw_rx_buf_readh(dev, buf, 12);
2257     src[2] = zmw_rx_buf_readh(dev, buf, 14);
2258
2259     if ((zmw_rx_buf_readb(dev, buf, 1) & 0x3) != 3)
2260     {
2261         /* AP */
2262         dst[0] = zmw_rx_buf_readh(dev, buf, 4);
2263
2264         psBit = (zmw_rx_buf_readb(dev, buf, 1) & 0x10) >> 4;
2265         /* Get AID and update STA PS mode */
2266         aid = zfApGetSTAInfoAndUpdatePs(dev, src, &staState, vap, psBit, uapsdTrig);
2267
2268         /* if STA not associated, send deauth */
2269         if ((aid == 0xffff) || (staState != ZM_STATE_ASOC))
2270         {
2271             if ((dst[0]&0x1)==0)
2272             {
2273                 zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, src, 0x7,
2274                         0, 0);
2275             }
2276
2277             return ZM_ERR_STA_NOT_ASSOCIATED;
2278         }
2279     } /* if ((zmw_rx_buf_readb(dev, buf, 1) & 0x3) != 3) */
2280     else
2281     {
2282         /* WDS */
2283         for (i=0; i<ZM_MAX_WDS_SUPPORT; i++)
2284         {
2285             if ((wd->ap.wds.wdsBitmap & (1<<i)) != 0)
2286             {
2287                 if ((src[0] == wd->ap.wds.macAddr[i][0])
2288                         && (src[1] == wd->ap.wds.macAddr[i][1])
2289                         && (src[2] == wd->ap.wds.macAddr[i][2]))
2290                 {
2291                     *vap = 0x20 + i;
2292                     break;
2293                 }
2294             }
2295         }
2296     }
2297     return ZM_SUCCESS;
2298 }
2299
2300 void zfApProcessPsPoll(zdev_t* dev, zbuf_t* buf)
2301 {
2302     u16_t src[3];
2303     u16_t dst[3];
2304     zbuf_t* psBuf = NULL;
2305     u16_t id;
2306     u8_t moreData = 0;
2307
2308     zmw_get_wlan_dev(dev);
2309
2310     zmw_declare_for_critical_section();
2311
2312     src[0] = zmw_tx_buf_readh(dev, buf, 10);
2313     src[1] = zmw_tx_buf_readh(dev, buf, 12);
2314     src[2] = zmw_tx_buf_readh(dev, buf, 14);
2315
2316     /* Find ps buffer for PsPoll */
2317     zmw_enter_critical_section(dev);
2318     id = wd->ap.uniHead;
2319     while (id != wd->ap.uniTail)
2320     {
2321         psBuf = wd->ap.uniArray[id];
2322
2323         dst[0] = zmw_tx_buf_readh(dev, psBuf, 0);
2324         dst[1] = zmw_tx_buf_readh(dev, psBuf, 2);
2325         dst[2] = zmw_tx_buf_readh(dev, psBuf, 4);
2326
2327         if ((src[0] == dst[0]) && (src[1] == dst[1]) && (src[2] == dst[2]))
2328         {
2329             moreData = zfApRemoveFromPsQueue(dev, id, src);
2330             break;
2331         }
2332         else
2333         {
2334             psBuf = NULL;
2335         }
2336         id = (id + 1) & (ZM_UNI_ARRAY_SIZE - 1);
2337     }
2338     zmw_leave_critical_section(dev);
2339
2340     /* Send ps buffer */
2341     if (psBuf != NULL)
2342     {
2343         /* Send with more data bit */
2344         zfTxSendEth(dev, psBuf, 0, ZM_EXTERNAL_ALLOC_BUF, moreData);
2345     }
2346
2347     return;
2348 }
2349
2350 void zfApSetProtectionMode(zdev_t* dev, u16_t mode)
2351 {
2352     zmw_get_wlan_dev(dev);
2353
2354     if (mode == 0)
2355     {
2356         if (wd->ap.protectionMode != mode)
2357         {
2358             /* Write MAC&PHY registers to disable protection */
2359
2360             wd->ap.protectionMode = mode;
2361         }
2362
2363     }
2364     else
2365     {
2366         if (wd->ap.protectionMode != mode)
2367         {
2368             /* Write MAC&PHY registers to enable protection */
2369
2370             wd->ap.protectionMode = mode;
2371         }
2372     }
2373     return;
2374 }
2375
2376
2377 /************************************************************************/
2378 /*                                                                      */
2379 /*    FUNCTION DESCRIPTION                  zfApSendFailure             */
2380 /*      Send failure.                                                   */
2381 /*                                                                      */
2382 /*    INPUTS                                                            */
2383 /*      dev : device pointer                                            */
2384 /*      addr : receiver address                                         */
2385 /*                                                                      */
2386 /*    OUTPUTS                                                           */
2387 /*      None                                                            */
2388 /*                                                                      */
2389 /*    AUTHOR                                                            */
2390 /*      Stephen Chen        Atheros Communications, INC.    2007.1      */
2391 /*                                                                      */
2392 /************************************************************************/
2393 void zfApSendFailure(zdev_t* dev, u8_t* addr)
2394 {
2395     u16_t id;
2396     u16_t staAddr[3];
2397     zmw_get_wlan_dev(dev);
2398     zmw_declare_for_critical_section();
2399
2400     staAddr[0] = addr[0] + (((u16_t)addr[1])<<8);
2401     staAddr[1] = addr[2] + (((u16_t)addr[3])<<8);
2402     staAddr[2] = addr[4] + (((u16_t)addr[5])<<8);
2403     zmw_enter_critical_section(dev);
2404     id = zfApFindSta(dev, staAddr);
2405     if (id != 0xffff)
2406     {
2407         /* Send failture : Add 3 minutes to inactive time that will */
2408         /*                 will make STA been kicked out soon */
2409         wd->ap.staTable[id].time -= (3*ZM_TICK_PER_MINUTE);
2410     }
2411     zmw_leave_critical_section(dev);
2412 }
2413
2414
2415 void zfApProcessAction(zdev_t* dev, zbuf_t* buf)
2416 {
2417     u8_t category;
2418
2419     //zmw_get_wlan_dev(dev);
2420
2421     //zmw_declare_for_critical_section();
2422
2423     category = zmw_rx_buf_readb(dev, buf, 24);
2424
2425     switch (category)
2426     {
2427     case ZM_WLAN_BLOCK_ACK_ACTION_FRAME:
2428         zfAggBlockAckActionFrame(dev, buf);
2429         break;
2430     default:
2431         break;
2432     }
2433
2434     return;
2435 }