diff options
author | Larry Finger <Larry.Finger@lwfinger.net> | 2011-04-08 21:33:25 -0400 |
---|---|---|
committer | Larry Finger <Larry.Finger@lwfinger.net> | 2011-04-08 21:33:25 -0400 |
commit | fefecc6989b4b24276797270c0e229c07be02ad3 (patch) | |
tree | 7c03f0f798ab84e5cf0c14a6648c991efd37c160 /drivers/staging/rt2860/common | |
parent | 0c3efe54d0165cecf0698b468e253577b555dde6 (diff) |
staging: rt2860sta and rt2870sta: Remove drivers replaced in net/wireless
The staging driver rt2860sta is replaced by mainline driver rt2800pci, and
rt2870sta is replaced by rt2800usb. As a result, the staging drivers are
deleted.
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
Diffstat (limited to 'drivers/staging/rt2860/common')
31 files changed, 0 insertions, 36712 deletions
diff --git a/drivers/staging/rt2860/common/action.c b/drivers/staging/rt2860/common/action.c deleted file mode 100644 index 56ad236e114..00000000000 --- a/drivers/staging/rt2860/common/action.c +++ /dev/null | |||
@@ -1,606 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | |||
27 | Module Name: | ||
28 | action.c | ||
29 | |||
30 | Abstract: | ||
31 | Handle association related requests either from WSTA or from local MLME | ||
32 | |||
33 | Revision History: | ||
34 | Who When What | ||
35 | -------- ---------- ---------------------------------------------- | ||
36 | Jan Lee 2006 created for rt2860 | ||
37 | */ | ||
38 | |||
39 | #include "../rt_config.h" | ||
40 | #include "action.h" | ||
41 | |||
42 | static void ReservedAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); | ||
43 | |||
44 | /* | ||
45 | ========================================================================== | ||
46 | Description: | ||
47 | association state machine init, including state transition and timer init | ||
48 | Parameters: | ||
49 | S - pointer to the association state machine | ||
50 | Note: | ||
51 | The state machine looks like the following | ||
52 | |||
53 | ASSOC_IDLE | ||
54 | MT2_MLME_DISASSOC_REQ mlme_disassoc_req_action | ||
55 | MT2_PEER_DISASSOC_REQ peer_disassoc_action | ||
56 | MT2_PEER_ASSOC_REQ drop | ||
57 | MT2_PEER_REASSOC_REQ drop | ||
58 | MT2_CLS3ERR cls3err_action | ||
59 | ========================================================================== | ||
60 | */ | ||
61 | void ActionStateMachineInit(struct rt_rtmp_adapter *pAd, | ||
62 | struct rt_state_machine *S, | ||
63 | OUT STATE_MACHINE_FUNC Trans[]) | ||
64 | { | ||
65 | StateMachineInit(S, (STATE_MACHINE_FUNC *) Trans, MAX_ACT_STATE, | ||
66 | MAX_ACT_MSG, (STATE_MACHINE_FUNC) Drop, ACT_IDLE, | ||
67 | ACT_MACHINE_BASE); | ||
68 | |||
69 | StateMachineSetAction(S, ACT_IDLE, MT2_PEER_SPECTRUM_CATE, | ||
70 | (STATE_MACHINE_FUNC) PeerSpectrumAction); | ||
71 | StateMachineSetAction(S, ACT_IDLE, MT2_PEER_QOS_CATE, | ||
72 | (STATE_MACHINE_FUNC) PeerQOSAction); | ||
73 | |||
74 | StateMachineSetAction(S, ACT_IDLE, MT2_PEER_DLS_CATE, | ||
75 | (STATE_MACHINE_FUNC) ReservedAction); | ||
76 | |||
77 | StateMachineSetAction(S, ACT_IDLE, MT2_PEER_BA_CATE, | ||
78 | (STATE_MACHINE_FUNC) PeerBAAction); | ||
79 | StateMachineSetAction(S, ACT_IDLE, MT2_PEER_HT_CATE, | ||
80 | (STATE_MACHINE_FUNC) PeerHTAction); | ||
81 | StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ADD_BA_CATE, | ||
82 | (STATE_MACHINE_FUNC) MlmeADDBAAction); | ||
83 | StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ORI_DELBA_CATE, | ||
84 | (STATE_MACHINE_FUNC) MlmeDELBAAction); | ||
85 | StateMachineSetAction(S, ACT_IDLE, MT2_MLME_REC_DELBA_CATE, | ||
86 | (STATE_MACHINE_FUNC) MlmeDELBAAction); | ||
87 | |||
88 | StateMachineSetAction(S, ACT_IDLE, MT2_PEER_PUBLIC_CATE, | ||
89 | (STATE_MACHINE_FUNC) PeerPublicAction); | ||
90 | StateMachineSetAction(S, ACT_IDLE, MT2_PEER_RM_CATE, | ||
91 | (STATE_MACHINE_FUNC) PeerRMAction); | ||
92 | |||
93 | StateMachineSetAction(S, ACT_IDLE, MT2_MLME_QOS_CATE, | ||
94 | (STATE_MACHINE_FUNC) MlmeQOSAction); | ||
95 | StateMachineSetAction(S, ACT_IDLE, MT2_MLME_DLS_CATE, | ||
96 | (STATE_MACHINE_FUNC) MlmeDLSAction); | ||
97 | StateMachineSetAction(S, ACT_IDLE, MT2_ACT_INVALID, | ||
98 | (STATE_MACHINE_FUNC) MlmeInvalidAction); | ||
99 | } | ||
100 | |||
101 | void MlmeADDBAAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) | ||
102 | { | ||
103 | struct rt_mlme_addba_req *pInfo; | ||
104 | u8 Addr[6]; | ||
105 | u8 *pOutBuffer = NULL; | ||
106 | int NStatus; | ||
107 | unsigned long Idx; | ||
108 | struct rt_frame_addba_req Frame; | ||
109 | unsigned long FrameLen; | ||
110 | struct rt_ba_ori_entry *pBAEntry = NULL; | ||
111 | |||
112 | pInfo = (struct rt_mlme_addba_req *)Elem->Msg; | ||
113 | NdisZeroMemory(&Frame, sizeof(struct rt_frame_addba_req)); | ||
114 | |||
115 | if (MlmeAddBAReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr)) { | ||
116 | NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ | ||
117 | if (NStatus != NDIS_STATUS_SUCCESS) { | ||
118 | DBGPRINT(RT_DEBUG_TRACE, | ||
119 | ("BA - MlmeADDBAAction() allocate memory failed \n")); | ||
120 | return; | ||
121 | } | ||
122 | /* 1. find entry */ | ||
123 | Idx = | ||
124 | pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID]; | ||
125 | if (Idx == 0) { | ||
126 | MlmeFreeMemory(pAd, pOutBuffer); | ||
127 | DBGPRINT(RT_DEBUG_ERROR, | ||
128 | ("BA - MlmeADDBAAction() can't find BAOriEntry \n")); | ||
129 | return; | ||
130 | } else { | ||
131 | pBAEntry = &pAd->BATable.BAOriEntry[Idx]; | ||
132 | } | ||
133 | |||
134 | { | ||
135 | if (ADHOC_ON(pAd)) | ||
136 | ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, | ||
137 | pAd->CurrentAddress, | ||
138 | pAd->CommonCfg.Bssid); | ||
139 | else | ||
140 | ActHeaderInit(pAd, &Frame.Hdr, | ||
141 | pAd->CommonCfg.Bssid, | ||
142 | pAd->CurrentAddress, | ||
143 | pInfo->pAddr); | ||
144 | } | ||
145 | |||
146 | Frame.Category = CATEGORY_BA; | ||
147 | Frame.Action = ADDBA_REQ; | ||
148 | Frame.BaParm.AMSDUSupported = 0; | ||
149 | Frame.BaParm.BAPolicy = IMMED_BA; | ||
150 | Frame.BaParm.TID = pInfo->TID; | ||
151 | Frame.BaParm.BufSize = pInfo->BaBufSize; | ||
152 | Frame.Token = pInfo->Token; | ||
153 | Frame.TimeOutValue = pInfo->TimeOutValue; | ||
154 | Frame.BaStartSeq.field.FragNum = 0; | ||
155 | Frame.BaStartSeq.field.StartSeq = | ||
156 | pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID]; | ||
157 | |||
158 | *(u16 *) (&Frame.BaParm) = | ||
159 | cpu2le16(*(u16 *) (&Frame.BaParm)); | ||
160 | Frame.TimeOutValue = cpu2le16(Frame.TimeOutValue); | ||
161 | Frame.BaStartSeq.word = cpu2le16(Frame.BaStartSeq.word); | ||
162 | |||
163 | MakeOutgoingFrame(pOutBuffer, &FrameLen, | ||
164 | sizeof(struct rt_frame_addba_req), &Frame, END_OF_ARGS); | ||
165 | |||
166 | MiniportMMRequest(pAd, | ||
167 | (MGMT_USE_QUEUE_FLAG | | ||
168 | MapUserPriorityToAccessCategory[pInfo->TID]), | ||
169 | pOutBuffer, FrameLen); | ||
170 | |||
171 | MlmeFreeMemory(pAd, pOutBuffer); | ||
172 | |||
173 | DBGPRINT(RT_DEBUG_TRACE, | ||
174 | ("BA - Send ADDBA request. StartSeq = %x, FrameLen = %ld. BufSize = %d\n", | ||
175 | Frame.BaStartSeq.field.StartSeq, FrameLen, | ||
176 | Frame.BaParm.BufSize)); | ||
177 | } | ||
178 | } | ||
179 | |||
180 | /* | ||
181 | ========================================================================== | ||
182 | Description: | ||
183 | send DELBA and delete BaEntry if any | ||
184 | Parametrs: | ||
185 | Elem - MLME message struct rt_mlme_delba_req | ||
186 | |||
187 | IRQL = DISPATCH_LEVEL | ||
188 | |||
189 | ========================================================================== | ||
190 | */ | ||
191 | void MlmeDELBAAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) | ||
192 | { | ||
193 | struct rt_mlme_delba_req *pInfo; | ||
194 | u8 *pOutBuffer = NULL; | ||
195 | u8 *pOutBuffer2 = NULL; | ||
196 | int NStatus; | ||
197 | unsigned long Idx; | ||
198 | struct rt_frame_delba_req Frame; | ||
199 | unsigned long FrameLen; | ||
200 | struct rt_frame_bar FrameBar; | ||
201 | |||
202 | pInfo = (struct rt_mlme_delba_req *)Elem->Msg; | ||
203 | /* must send back DELBA */ | ||
204 | NdisZeroMemory(&Frame, sizeof(struct rt_frame_delba_req)); | ||
205 | DBGPRINT(RT_DEBUG_TRACE, | ||
206 | ("==> MlmeDELBAAction(), Initiator(%d) \n", pInfo->Initiator)); | ||
207 | |||
208 | if (MlmeDelBAReqSanity(pAd, Elem->Msg, Elem->MsgLen)) { | ||
209 | NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ | ||
210 | if (NStatus != NDIS_STATUS_SUCCESS) { | ||
211 | DBGPRINT(RT_DEBUG_ERROR, | ||
212 | ("BA - MlmeDELBAAction() allocate memory failed 1. \n")); | ||
213 | return; | ||
214 | } | ||
215 | |||
216 | NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); /*Get an unused nonpaged memory */ | ||
217 | if (NStatus != NDIS_STATUS_SUCCESS) { | ||
218 | MlmeFreeMemory(pAd, pOutBuffer); | ||
219 | DBGPRINT(RT_DEBUG_ERROR, | ||
220 | ("BA - MlmeDELBAAction() allocate memory failed 2. \n")); | ||
221 | return; | ||
222 | } | ||
223 | /* SEND BAR (Send BAR to refresh peer reordering buffer.) */ | ||
224 | Idx = | ||
225 | pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID]; | ||
226 | |||
227 | BarHeaderInit(pAd, &FrameBar, | ||
228 | pAd->MacTab.Content[pInfo->Wcid].Addr, | ||
229 | pAd->CurrentAddress); | ||
230 | |||
231 | FrameBar.StartingSeq.field.FragNum = 0; /* make sure sequence not clear in DEL funciton. */ | ||
232 | FrameBar.StartingSeq.field.StartSeq = pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID]; /* make sure sequence not clear in DEL funciton. */ | ||
233 | FrameBar.BarControl.TID = pInfo->TID; /* make sure sequence not clear in DEL funciton. */ | ||
234 | FrameBar.BarControl.ACKPolicy = IMMED_BA; /* make sure sequence not clear in DEL funciton. */ | ||
235 | FrameBar.BarControl.Compressed = 1; /* make sure sequence not clear in DEL funciton. */ | ||
236 | FrameBar.BarControl.MTID = 0; /* make sure sequence not clear in DEL funciton. */ | ||
237 | |||
238 | MakeOutgoingFrame(pOutBuffer2, &FrameLen, | ||
239 | sizeof(struct rt_frame_bar), &FrameBar, END_OF_ARGS); | ||
240 | MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen); | ||
241 | MlmeFreeMemory(pAd, pOutBuffer2); | ||
242 | DBGPRINT(RT_DEBUG_TRACE, | ||
243 | ("BA - MlmeDELBAAction() . Send BAR to refresh peer reordering buffer \n")); | ||
244 | |||
245 | /* SEND DELBA FRAME */ | ||
246 | FrameLen = 0; | ||
247 | |||
248 | { | ||
249 | if (ADHOC_ON(pAd)) | ||
250 | ActHeaderInit(pAd, &Frame.Hdr, | ||
251 | pAd->MacTab.Content[pInfo->Wcid]. | ||
252 | Addr, pAd->CurrentAddress, | ||
253 | pAd->CommonCfg.Bssid); | ||
254 | else | ||
255 | ActHeaderInit(pAd, &Frame.Hdr, | ||
256 | pAd->CommonCfg.Bssid, | ||
257 | pAd->CurrentAddress, | ||
258 | pAd->MacTab.Content[pInfo->Wcid]. | ||
259 | Addr); | ||
260 | } | ||
261 | |||
262 | Frame.Category = CATEGORY_BA; | ||
263 | Frame.Action = DELBA; | ||
264 | Frame.DelbaParm.Initiator = pInfo->Initiator; | ||
265 | Frame.DelbaParm.TID = pInfo->TID; | ||
266 | Frame.ReasonCode = 39; /* Time Out */ | ||
267 | *(u16 *) (&Frame.DelbaParm) = | ||
268 | cpu2le16(*(u16 *) (&Frame.DelbaParm)); | ||
269 | Frame.ReasonCode = cpu2le16(Frame.ReasonCode); | ||
270 | |||
271 | MakeOutgoingFrame(pOutBuffer, &FrameLen, | ||
272 | sizeof(struct rt_frame_delba_req), &Frame, END_OF_ARGS); | ||
273 | MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); | ||
274 | MlmeFreeMemory(pAd, pOutBuffer); | ||
275 | DBGPRINT(RT_DEBUG_TRACE, | ||
276 | ("BA - MlmeDELBAAction() . 3 DELBA sent. Initiator(%d)\n", | ||
277 | pInfo->Initiator)); | ||
278 | } | ||
279 | } | ||
280 | |||
281 | void MlmeQOSAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) | ||
282 | { | ||
283 | } | ||
284 | |||
285 | void MlmeDLSAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) | ||
286 | { | ||
287 | } | ||
288 | |||
289 | void MlmeInvalidAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) | ||
290 | { | ||
291 | /*u8 * pOutBuffer = NULL; */ | ||
292 | /*Return the receiving frame except the MSB of category filed set to 1. 7.3.1.11 */ | ||
293 | } | ||
294 | |||
295 | void PeerQOSAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) | ||
296 | { | ||
297 | } | ||
298 | |||
299 | void PeerBAAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) | ||
300 | { | ||
301 | u8 Action = Elem->Msg[LENGTH_802_11 + 1]; | ||
302 | |||
303 | switch (Action) { | ||
304 | case ADDBA_REQ: | ||
305 | PeerAddBAReqAction(pAd, Elem); | ||
306 | break; | ||
307 | case ADDBA_RESP: | ||
308 | PeerAddBARspAction(pAd, Elem); | ||
309 | break; | ||
310 | case DELBA: | ||
311 | PeerDelBAAction(pAd, Elem); | ||
312 | break; | ||
313 | } | ||
314 | } | ||
315 | |||
316 | void PeerPublicAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) | ||
317 | { | ||
318 | if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) | ||
319 | return; | ||
320 | } | ||
321 | |||
322 | static void ReservedAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) | ||
323 | { | ||
324 | u8 Category; | ||
325 | |||
326 | if (Elem->MsgLen <= LENGTH_802_11) { | ||
327 | return; | ||
328 | } | ||
329 | |||
330 | Category = Elem->Msg[LENGTH_802_11]; | ||
331 | DBGPRINT(RT_DEBUG_TRACE, | ||
332 | ("Rcv reserved category(%d) Action Frame\n", Category)); | ||
333 | hex_dump("Reserved Action Frame", &Elem->Msg[0], Elem->MsgLen); | ||
334 | } | ||
335 | |||
336 | void PeerRMAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) | ||
337 | { | ||
338 | return; | ||
339 | } | ||
340 | |||
341 | static void respond_ht_information_exchange_action(struct rt_rtmp_adapter *pAd, | ||
342 | struct rt_mlme_queue_elem *Elem) | ||
343 | { | ||
344 | u8 *pOutBuffer = NULL; | ||
345 | int NStatus; | ||
346 | unsigned long FrameLen; | ||
347 | struct rt_frame_ht_info HTINFOframe, *pFrame; | ||
348 | u8 *pAddr; | ||
349 | |||
350 | /* 2. Always send back ADDBA Response */ | ||
351 | NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ | ||
352 | |||
353 | if (NStatus != NDIS_STATUS_SUCCESS) { | ||
354 | DBGPRINT(RT_DEBUG_TRACE, | ||
355 | ("ACTION - respond_ht_information_exchange_action() allocate memory failed \n")); | ||
356 | return; | ||
357 | } | ||
358 | /* get RA */ | ||
359 | pFrame = (struct rt_frame_ht_info *) & Elem->Msg[0]; | ||
360 | pAddr = pFrame->Hdr.Addr2; | ||
361 | |||
362 | NdisZeroMemory(&HTINFOframe, sizeof(struct rt_frame_ht_info)); | ||
363 | /* 2-1. Prepare ADDBA Response frame. */ | ||
364 | { | ||
365 | if (ADHOC_ON(pAd)) | ||
366 | ActHeaderInit(pAd, &HTINFOframe.Hdr, pAddr, | ||
367 | pAd->CurrentAddress, | ||
368 | pAd->CommonCfg.Bssid); | ||
369 | else | ||
370 | ActHeaderInit(pAd, &HTINFOframe.Hdr, | ||
371 | pAd->CommonCfg.Bssid, pAd->CurrentAddress, | ||
372 | pAddr); | ||
373 | } | ||
374 | |||
375 | HTINFOframe.Category = CATEGORY_HT; | ||
376 | HTINFOframe.Action = HT_INFO_EXCHANGE; | ||
377 | HTINFOframe.HT_Info.Request = 0; | ||
378 | HTINFOframe.HT_Info.Forty_MHz_Intolerant = | ||
379 | pAd->CommonCfg.HtCapability.HtCapInfo.Forty_Mhz_Intolerant; | ||
380 | HTINFOframe.HT_Info.STA_Channel_Width = | ||
381 | pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth; | ||
382 | |||
383 | MakeOutgoingFrame(pOutBuffer, &FrameLen, | ||
384 | sizeof(struct rt_frame_ht_info), &HTINFOframe, END_OF_ARGS); | ||
385 | |||
386 | MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); | ||
387 | MlmeFreeMemory(pAd, pOutBuffer); | ||
388 | } | ||
389 | |||
390 | void PeerHTAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) | ||
391 | { | ||
392 | u8 Action = Elem->Msg[LENGTH_802_11 + 1]; | ||
393 | |||
394 | if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) | ||
395 | return; | ||
396 | |||
397 | switch (Action) { | ||
398 | case NOTIFY_BW_ACTION: | ||
399 | DBGPRINT(RT_DEBUG_TRACE, | ||
400 | ("ACTION - HT Notify Channel bandwidth action----> \n")); | ||
401 | |||
402 | if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) { | ||
403 | /* Note, this is to patch DIR-1353 AP. When the AP set to Wep, it will use legacy mode. But AP still keeps */ | ||
404 | /* sending BW_Notify Action frame, and cause us to linkup and linkdown. */ | ||
405 | /* In legacy mode, don't need to parse HT action frame. */ | ||
406 | DBGPRINT(RT_DEBUG_TRACE, | ||
407 | ("ACTION -Ignore HT Notify Channel BW when link as legacy mode. BW = %d---> \n", | ||
408 | Elem->Msg[LENGTH_802_11 + 2])); | ||
409 | break; | ||
410 | } | ||
411 | |||
412 | if (Elem->Msg[LENGTH_802_11 + 2] == 0) /* 7.4.8.2. if value is 1, keep the same as supported channel bandwidth. */ | ||
413 | pAd->MacTab.Content[Elem->Wcid].HTPhyMode.field.BW = 0; | ||
414 | |||
415 | break; | ||
416 | case SMPS_ACTION: | ||
417 | /* 7.3.1.25 */ | ||
418 | DBGPRINT(RT_DEBUG_TRACE, ("ACTION - SMPS action----> \n")); | ||
419 | if (((Elem->Msg[LENGTH_802_11 + 2] & 0x1) == 0)) { | ||
420 | pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_ENABLE; | ||
421 | } else if (((Elem->Msg[LENGTH_802_11 + 2] & 0x2) == 0)) { | ||
422 | pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_STATIC; | ||
423 | } else { | ||
424 | pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_DYNAMIC; | ||
425 | } | ||
426 | |||
427 | DBGPRINT(RT_DEBUG_TRACE, | ||
428 | ("Aid(%d) MIMO PS = %d\n", Elem->Wcid, | ||
429 | pAd->MacTab.Content[Elem->Wcid].MmpsMode)); | ||
430 | /* rt2860c : add something for smps change. */ | ||
431 | break; | ||
432 | |||
433 | case SETPCO_ACTION: | ||
434 | break; | ||
435 | case MIMO_CHA_MEASURE_ACTION: | ||
436 | break; | ||
437 | case HT_INFO_EXCHANGE: | ||
438 | { | ||
439 | struct rt_ht_information_octet *pHT_info; | ||
440 | |||
441 | pHT_info = | ||
442 | (struct rt_ht_information_octet *) & Elem->Msg[LENGTH_802_11 + | ||
443 | 2]; | ||
444 | /* 7.4.8.10 */ | ||
445 | DBGPRINT(RT_DEBUG_TRACE, | ||
446 | ("ACTION - HT Information Exchange action----> \n")); | ||
447 | if (pHT_info->Request) { | ||
448 | respond_ht_information_exchange_action(pAd, | ||
449 | Elem); | ||
450 | } | ||
451 | } | ||
452 | break; | ||
453 | } | ||
454 | } | ||
455 | |||
456 | /* | ||
457 | ========================================================================== | ||
458 | Description: | ||
459 | Retry sending ADDBA Reqest. | ||
460 | |||
461 | IRQL = DISPATCH_LEVEL | ||
462 | |||
463 | Parametrs: | ||
464 | p8023Header: if this is already 802.3 format, p8023Header is NULL | ||
465 | |||
466 | Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere. | ||
467 | FALSE , then continue indicaterx at this moment. | ||
468 | ========================================================================== | ||
469 | */ | ||
470 | void ORIBATimerTimeout(struct rt_rtmp_adapter *pAd) | ||
471 | { | ||
472 | struct rt_mac_table_entry *pEntry; | ||
473 | int i, total; | ||
474 | u8 TID; | ||
475 | |||
476 | total = pAd->MacTab.Size * NUM_OF_TID; | ||
477 | |||
478 | for (i = 1; ((i < MAX_LEN_OF_BA_ORI_TABLE) && (total > 0)); i++) { | ||
479 | if (pAd->BATable.BAOriEntry[i].ORI_BA_Status == Originator_Done) { | ||
480 | pEntry = | ||
481 | &pAd->MacTab.Content[pAd->BATable.BAOriEntry[i]. | ||
482 | Wcid]; | ||
483 | TID = pAd->BATable.BAOriEntry[i].TID; | ||
484 | |||
485 | ASSERT(pAd->BATable.BAOriEntry[i].Wcid < | ||
486 | MAX_LEN_OF_MAC_TABLE); | ||
487 | } | ||
488 | total--; | ||
489 | } | ||
490 | } | ||
491 | |||
492 | void SendRefreshBAR(struct rt_rtmp_adapter *pAd, struct rt_mac_table_entry *pEntry) | ||
493 | { | ||
494 | struct rt_frame_bar FrameBar; | ||
495 | unsigned long FrameLen; | ||
496 | int NStatus; | ||
497 | u8 *pOutBuffer = NULL; | ||
498 | u16 Sequence; | ||
499 | u8 i, TID; | ||
500 | u16 idx; | ||
501 | struct rt_ba_ori_entry *pBAEntry; | ||
502 | |||
503 | for (i = 0; i < NUM_OF_TID; i++) { | ||
504 | idx = pEntry->BAOriWcidArray[i]; | ||
505 | if (idx == 0) { | ||
506 | continue; | ||
507 | } | ||
508 | pBAEntry = &pAd->BATable.BAOriEntry[idx]; | ||
509 | |||
510 | if (pBAEntry->ORI_BA_Status == Originator_Done) { | ||
511 | TID = pBAEntry->TID; | ||
512 | |||
513 | ASSERT(pBAEntry->Wcid < MAX_LEN_OF_MAC_TABLE); | ||
514 | |||
515 | NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ | ||
516 | if (NStatus != NDIS_STATUS_SUCCESS) { | ||
517 | DBGPRINT(RT_DEBUG_ERROR, | ||
518 | ("BA - MlmeADDBAAction() allocate memory failed \n")); | ||
519 | return; | ||
520 | } | ||
521 | |||
522 | Sequence = pEntry->TxSeq[TID]; | ||
523 | |||
524 | BarHeaderInit(pAd, &FrameBar, pEntry->Addr, | ||
525 | pAd->CurrentAddress); | ||
526 | |||
527 | FrameBar.StartingSeq.field.FragNum = 0; /* make sure sequence not clear in DEL function. */ | ||
528 | FrameBar.StartingSeq.field.StartSeq = Sequence; /* make sure sequence not clear in DEL funciton. */ | ||
529 | FrameBar.BarControl.TID = TID; /* make sure sequence not clear in DEL funciton. */ | ||
530 | |||
531 | MakeOutgoingFrame(pOutBuffer, &FrameLen, | ||
532 | sizeof(struct rt_frame_bar), &FrameBar, | ||
533 | END_OF_ARGS); | ||
534 | /*if (!(CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET))) */ | ||
535 | if (1) /* Now we always send BAR. */ | ||
536 | { | ||
537 | /*MiniportMMRequestUnlock(pAd, 0, pOutBuffer, FrameLen); */ | ||
538 | MiniportMMRequest(pAd, | ||
539 | (MGMT_USE_QUEUE_FLAG | | ||
540 | MapUserPriorityToAccessCategory | ||
541 | [TID]), pOutBuffer, | ||
542 | FrameLen); | ||
543 | |||
544 | } | ||
545 | MlmeFreeMemory(pAd, pOutBuffer); | ||
546 | } | ||
547 | } | ||
548 | } | ||
549 | |||
550 | void ActHeaderInit(struct rt_rtmp_adapter *pAd, | ||
551 | struct rt_header_802_11 * pHdr80211, | ||
552 | u8 *Addr1, u8 *Addr2, u8 *Addr3) | ||
553 | { | ||
554 | NdisZeroMemory(pHdr80211, sizeof(struct rt_header_802_11)); | ||
555 | pHdr80211->FC.Type = BTYPE_MGMT; | ||
556 | pHdr80211->FC.SubType = SUBTYPE_ACTION; | ||
557 | |||
558 | COPY_MAC_ADDR(pHdr80211->Addr1, Addr1); | ||
559 | COPY_MAC_ADDR(pHdr80211->Addr2, Addr2); | ||
560 | COPY_MAC_ADDR(pHdr80211->Addr3, Addr3); | ||
561 | } | ||
562 | |||
563 | void BarHeaderInit(struct rt_rtmp_adapter *pAd, | ||
564 | struct rt_frame_bar * pCntlBar, u8 *pDA, u8 *pSA) | ||
565 | { | ||
566 | NdisZeroMemory(pCntlBar, sizeof(struct rt_frame_bar)); | ||
567 | pCntlBar->FC.Type = BTYPE_CNTL; | ||
568 | pCntlBar->FC.SubType = SUBTYPE_BLOCK_ACK_REQ; | ||
569 | pCntlBar->BarControl.MTID = 0; | ||
570 | pCntlBar->BarControl.Compressed = 1; | ||
571 | pCntlBar->BarControl.ACKPolicy = 0; | ||
572 | |||
573 | pCntlBar->Duration = | ||
574 | 16 + RTMPCalcDuration(pAd, RATE_1, sizeof(struct rt_frame_ba)); | ||
575 | |||
576 | COPY_MAC_ADDR(pCntlBar->Addr1, pDA); | ||
577 | COPY_MAC_ADDR(pCntlBar->Addr2, pSA); | ||
578 | } | ||
579 | |||
580 | /* | ||
581 | ========================================================================== | ||
582 | Description: | ||
583 | Insert Category and action code into the action frame. | ||
584 | |||
585 | Parametrs: | ||
586 | 1. frame buffer pointer. | ||
587 | 2. frame length. | ||
588 | 3. category code of the frame. | ||
589 | 4. action code of the frame. | ||
590 | |||
591 | Return : None. | ||
592 | ========================================================================== | ||
593 | */ | ||
594 | void InsertActField(struct rt_rtmp_adapter *pAd, | ||
595 | u8 *pFrameBuf, | ||
596 | unsigned long *pFrameLen, u8 Category, u8 ActCode) | ||
597 | { | ||
598 | unsigned long TempLen; | ||
599 | |||
600 | MakeOutgoingFrame(pFrameBuf, &TempLen, | ||
601 | 1, &Category, 1, &ActCode, END_OF_ARGS); | ||
602 | |||
603 | *pFrameLen = *pFrameLen + TempLen; | ||
604 | |||
605 | return; | ||
606 | } | ||
diff --git a/drivers/staging/rt2860/common/action.h b/drivers/staging/rt2860/common/action.h deleted file mode 100644 index 974f8b84039..00000000000 --- a/drivers/staging/rt2860/common/action.h +++ /dev/null | |||
@@ -1,56 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | |||
27 | Module Name: | ||
28 | aironet.h | ||
29 | |||
30 | Abstract: | ||
31 | |||
32 | Revision History: | ||
33 | Who When What | ||
34 | -------- ---------- ---------------------------------------------- | ||
35 | Name Date Modification logs | ||
36 | Paul Lin 04-06-15 Initial | ||
37 | */ | ||
38 | |||
39 | #ifndef __ACTION_H__ | ||
40 | #define __ACTION_H__ | ||
41 | |||
42 | struct PACKED rt_ht_information_octet { | ||
43 | u8 Request:1; | ||
44 | u8 Forty_MHz_Intolerant:1; | ||
45 | u8 STA_Channel_Width:1; | ||
46 | u8 Reserved:5; | ||
47 | }; | ||
48 | |||
49 | struct PACKED rt_frame_ht_info { | ||
50 | struct rt_header_802_11 Hdr; | ||
51 | u8 Category; | ||
52 | u8 Action; | ||
53 | struct rt_ht_information_octet HT_Info; | ||
54 | }; | ||
55 | |||
56 | #endif /* __ACTION_H__ */ | ||
diff --git a/drivers/staging/rt2860/common/ba_action.c b/drivers/staging/rt2860/common/ba_action.c deleted file mode 100644 index 133bc1b87d2..00000000000 --- a/drivers/staging/rt2860/common/ba_action.c +++ /dev/null | |||
@@ -1,1650 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | */ | ||
27 | |||
28 | #include "../rt_config.h" | ||
29 | #include <linux/kernel.h> | ||
30 | |||
31 | #define BA_ORI_INIT_SEQ (pEntry->TxSeq[TID]) /*1 // initial sequence number of BA session */ | ||
32 | |||
33 | #define ORI_SESSION_MAX_RETRY 8 | ||
34 | #define ORI_BA_SESSION_TIMEOUT (2000) /* ms */ | ||
35 | #define REC_BA_SESSION_IDLE_TIMEOUT (1000) /* ms */ | ||
36 | |||
37 | #define REORDERING_PACKET_TIMEOUT ((100 * OS_HZ)/1000) /* system ticks -- 100 ms */ | ||
38 | #define MAX_REORDERING_PACKET_TIMEOUT ((3000 * OS_HZ)/1000) /* system ticks -- 100 ms */ | ||
39 | |||
40 | #define RESET_RCV_SEQ (0xFFFF) | ||
41 | |||
42 | static void ba_mpdu_blk_free(struct rt_rtmp_adapter *pAd, | ||
43 | struct reordering_mpdu *mpdu_blk); | ||
44 | |||
45 | struct rt_ba_ori_entry *BATableAllocOriEntry(struct rt_rtmp_adapter *pAd, u16 * Idx); | ||
46 | |||
47 | struct rt_ba_rec_entry *BATableAllocRecEntry(struct rt_rtmp_adapter *pAd, u16 * Idx); | ||
48 | |||
49 | void BAOriSessionSetupTimeout(void *SystemSpecific1, | ||
50 | void *FunctionContext, | ||
51 | void *SystemSpecific2, | ||
52 | void *SystemSpecific3); | ||
53 | |||
54 | void BARecSessionIdleTimeout(void *SystemSpecific1, | ||
55 | void *FunctionContext, | ||
56 | void *SystemSpecific2, | ||
57 | void *SystemSpecific3); | ||
58 | |||
59 | BUILD_TIMER_FUNCTION(BAOriSessionSetupTimeout); | ||
60 | BUILD_TIMER_FUNCTION(BARecSessionIdleTimeout); | ||
61 | |||
62 | #define ANNOUNCE_REORDERING_PACKET(_pAd, _mpdu_blk) \ | ||
63 | Announce_Reordering_Packet(_pAd, _mpdu_blk); | ||
64 | |||
65 | void BA_MaxWinSizeReasign(struct rt_rtmp_adapter *pAd, | ||
66 | struct rt_mac_table_entry *pEntryPeer, u8 * pWinSize) | ||
67 | { | ||
68 | u8 MaxSize; | ||
69 | |||
70 | if (pAd->MACVersion >= RALINK_2883_VERSION) /* 3*3 */ | ||
71 | { | ||
72 | if (pAd->MACVersion >= RALINK_3070_VERSION) { | ||
73 | if (pEntryPeer->WepStatus != | ||
74 | Ndis802_11EncryptionDisabled) | ||
75 | MaxSize = 7; /* for non-open mode */ | ||
76 | else | ||
77 | MaxSize = 13; | ||
78 | } else | ||
79 | MaxSize = 31; | ||
80 | } else if (pAd->MACVersion >= RALINK_2880E_VERSION) /* 2880 e */ | ||
81 | { | ||
82 | if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled) | ||
83 | MaxSize = 7; /* for non-open mode */ | ||
84 | else | ||
85 | MaxSize = 13; | ||
86 | } else | ||
87 | MaxSize = 7; | ||
88 | |||
89 | DBGPRINT(RT_DEBUG_TRACE, ("ba> Win Size = %d, Max Size = %d\n", | ||
90 | *pWinSize, MaxSize)); | ||
91 | |||
92 | if ((*pWinSize) > MaxSize) { | ||
93 | DBGPRINT(RT_DEBUG_TRACE, | ||
94 | ("ba> reassign max win size from %d to %d\n", | ||
95 | *pWinSize, MaxSize)); | ||
96 | |||
97 | *pWinSize = MaxSize; | ||
98 | } | ||
99 | } | ||
100 | |||
101 | void Announce_Reordering_Packet(struct rt_rtmp_adapter *pAd, | ||
102 | IN struct reordering_mpdu *mpdu) | ||
103 | { | ||
104 | void *pPacket; | ||
105 | |||
106 | pPacket = mpdu->pPacket; | ||
107 | |||
108 | if (mpdu->bAMSDU) { | ||
109 | ASSERT(0); | ||
110 | BA_Reorder_AMSDU_Announce(pAd, pPacket); | ||
111 | } else { | ||
112 | /* */ | ||
113 | /* pass this 802.3 packet to upper layer or forward this packet to WM directly */ | ||
114 | /* */ | ||
115 | |||
116 | ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket, | ||
117 | RTMP_GET_PACKET_IF(pPacket)); | ||
118 | } | ||
119 | } | ||
120 | |||
121 | /* | ||
122 | * Insert a reordering mpdu into sorted linked list by sequence no. | ||
123 | */ | ||
124 | BOOLEAN ba_reordering_mpdu_insertsorted(struct reordering_list *list, | ||
125 | struct reordering_mpdu *mpdu) | ||
126 | { | ||
127 | |||
128 | struct reordering_mpdu **ppScan = &list->next; | ||
129 | |||
130 | while (*ppScan != NULL) { | ||
131 | if (SEQ_SMALLER((*ppScan)->Sequence, mpdu->Sequence, MAXSEQ)) { | ||
132 | ppScan = &(*ppScan)->next; | ||
133 | } else if ((*ppScan)->Sequence == mpdu->Sequence) { | ||
134 | /* give up this duplicated frame */ | ||
135 | return (FALSE); | ||
136 | } else { | ||
137 | /* find position */ | ||
138 | break; | ||
139 | } | ||
140 | } | ||
141 | |||
142 | mpdu->next = *ppScan; | ||
143 | *ppScan = mpdu; | ||
144 | list->qlen++; | ||
145 | return TRUE; | ||
146 | } | ||
147 | |||
148 | /* | ||
149 | * caller lock critical section if necessary | ||
150 | */ | ||
151 | static inline void ba_enqueue(struct reordering_list *list, | ||
152 | struct reordering_mpdu *mpdu_blk) | ||
153 | { | ||
154 | list->qlen++; | ||
155 | mpdu_blk->next = list->next; | ||
156 | list->next = mpdu_blk; | ||
157 | } | ||
158 | |||
159 | /* | ||
160 | * caller lock critical section if necessary | ||
161 | */ | ||
162 | static inline struct reordering_mpdu *ba_dequeue(struct reordering_list *list) | ||
163 | { | ||
164 | struct reordering_mpdu *mpdu_blk = NULL; | ||
165 | |||
166 | ASSERT(list); | ||
167 | |||
168 | if (list->qlen) { | ||
169 | list->qlen--; | ||
170 | mpdu_blk = list->next; | ||
171 | if (mpdu_blk) { | ||
172 | list->next = mpdu_blk->next; | ||
173 | mpdu_blk->next = NULL; | ||
174 | } | ||
175 | } | ||
176 | return mpdu_blk; | ||
177 | } | ||
178 | |||
179 | static inline struct reordering_mpdu *ba_reordering_mpdu_dequeue(struct | ||
180 | reordering_list | ||
181 | *list) | ||
182 | { | ||
183 | return (ba_dequeue(list)); | ||
184 | } | ||
185 | |||
186 | static inline struct reordering_mpdu *ba_reordering_mpdu_probe(struct | ||
187 | reordering_list | ||
188 | *list) | ||
189 | { | ||
190 | ASSERT(list); | ||
191 | |||
192 | return (list->next); | ||
193 | } | ||
194 | |||
195 | /* | ||
196 | * free all resource for reordering mechanism | ||
197 | */ | ||
198 | void ba_reordering_resource_release(struct rt_rtmp_adapter *pAd) | ||
199 | { | ||
200 | struct rt_ba_table *Tab; | ||
201 | struct rt_ba_rec_entry *pBAEntry; | ||
202 | struct reordering_mpdu *mpdu_blk; | ||
203 | int i; | ||
204 | |||
205 | Tab = &pAd->BATable; | ||
206 | |||
207 | /* I. release all pending reordering packet */ | ||
208 | NdisAcquireSpinLock(&pAd->BATabLock); | ||
209 | for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) { | ||
210 | pBAEntry = &Tab->BARecEntry[i]; | ||
211 | if (pBAEntry->REC_BA_Status != Recipient_NONE) { | ||
212 | while ((mpdu_blk = | ||
213 | ba_reordering_mpdu_dequeue(&pBAEntry->list))) { | ||
214 | ASSERT(mpdu_blk->pPacket); | ||
215 | RELEASE_NDIS_PACKET(pAd, mpdu_blk->pPacket, | ||
216 | NDIS_STATUS_FAILURE); | ||
217 | ba_mpdu_blk_free(pAd, mpdu_blk); | ||
218 | } | ||
219 | } | ||
220 | } | ||
221 | NdisReleaseSpinLock(&pAd->BATabLock); | ||
222 | |||
223 | ASSERT(pBAEntry->list.qlen == 0); | ||
224 | /* II. free memory of reordering mpdu table */ | ||
225 | NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock); | ||
226 | os_free_mem(pAd, pAd->mpdu_blk_pool.mem); | ||
227 | NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock); | ||
228 | } | ||
229 | |||
230 | /* | ||
231 | * Allocate all resource for reordering mechanism | ||
232 | */ | ||
233 | BOOLEAN ba_reordering_resource_init(struct rt_rtmp_adapter *pAd, int num) | ||
234 | { | ||
235 | int i; | ||
236 | u8 *mem; | ||
237 | struct reordering_mpdu *mpdu_blk; | ||
238 | struct reordering_list *freelist; | ||
239 | |||
240 | /* allocate spinlock */ | ||
241 | NdisAllocateSpinLock(&pAd->mpdu_blk_pool.lock); | ||
242 | |||
243 | /* initialize freelist */ | ||
244 | freelist = &pAd->mpdu_blk_pool.freelist; | ||
245 | freelist->next = NULL; | ||
246 | freelist->qlen = 0; | ||
247 | |||
248 | DBGPRINT(RT_DEBUG_TRACE, | ||
249 | ("Allocate %d memory for BA reordering\n", | ||
250 | (u32)(num * sizeof(struct reordering_mpdu)))); | ||
251 | |||
252 | /* allocate number of mpdu_blk memory */ | ||
253 | os_alloc_mem(pAd, (u8 **) & mem, | ||
254 | (num * sizeof(struct reordering_mpdu))); | ||
255 | |||
256 | pAd->mpdu_blk_pool.mem = mem; | ||
257 | |||
258 | if (mem == NULL) { | ||
259 | DBGPRINT(RT_DEBUG_ERROR, | ||
260 | ("Can't Allocate Memory for BA Reordering\n")); | ||
261 | return (FALSE); | ||
262 | } | ||
263 | |||
264 | /* build mpdu_blk free list */ | ||
265 | for (i = 0; i < num; i++) { | ||
266 | /* get mpdu_blk */ | ||
267 | mpdu_blk = (struct reordering_mpdu *)mem; | ||
268 | /* initial mpdu_blk */ | ||
269 | NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu)); | ||
270 | /* next mpdu_blk */ | ||
271 | mem += sizeof(struct reordering_mpdu); | ||
272 | /* insert mpdu_blk into freelist */ | ||
273 | ba_enqueue(freelist, mpdu_blk); | ||
274 | } | ||
275 | |||
276 | return (TRUE); | ||
277 | } | ||
278 | |||
279 | /*static int blk_count=0; // sample take off, no use */ | ||
280 | |||
281 | static struct reordering_mpdu *ba_mpdu_blk_alloc(struct rt_rtmp_adapter *pAd) | ||
282 | { | ||
283 | struct reordering_mpdu *mpdu_blk; | ||
284 | |||
285 | NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock); | ||
286 | mpdu_blk = ba_dequeue(&pAd->mpdu_blk_pool.freelist); | ||
287 | if (mpdu_blk) { | ||
288 | /* blk_count++; */ | ||
289 | /* reset mpdu_blk */ | ||
290 | NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu)); | ||
291 | } | ||
292 | NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock); | ||
293 | return mpdu_blk; | ||
294 | } | ||
295 | |||
296 | static void ba_mpdu_blk_free(struct rt_rtmp_adapter *pAd, | ||
297 | struct reordering_mpdu *mpdu_blk) | ||
298 | { | ||
299 | ASSERT(mpdu_blk); | ||
300 | |||
301 | NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock); | ||
302 | /* blk_count--; */ | ||
303 | ba_enqueue(&pAd->mpdu_blk_pool.freelist, mpdu_blk); | ||
304 | NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock); | ||
305 | } | ||
306 | |||
307 | static u16 ba_indicate_reordering_mpdus_in_order(struct rt_rtmp_adapter *pAd, | ||
308 | struct rt_ba_rec_entry *pBAEntry, | ||
309 | u16 StartSeq) | ||
310 | { | ||
311 | struct reordering_mpdu *mpdu_blk; | ||
312 | u16 LastIndSeq = RESET_RCV_SEQ; | ||
313 | |||
314 | NdisAcquireSpinLock(&pBAEntry->RxReRingLock); | ||
315 | |||
316 | while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list))) { | ||
317 | /* find in-order frame */ | ||
318 | if (!SEQ_STEPONE(mpdu_blk->Sequence, StartSeq, MAXSEQ)) { | ||
319 | break; | ||
320 | } | ||
321 | /* dequeue in-order frame from reodering list */ | ||
322 | mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list); | ||
323 | /* pass this frame up */ | ||
324 | ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); | ||
325 | /* move to next sequence */ | ||
326 | StartSeq = mpdu_blk->Sequence; | ||
327 | LastIndSeq = StartSeq; | ||
328 | /* free mpdu_blk */ | ||
329 | ba_mpdu_blk_free(pAd, mpdu_blk); | ||
330 | } | ||
331 | |||
332 | NdisReleaseSpinLock(&pBAEntry->RxReRingLock); | ||
333 | |||
334 | /* update last indicated sequence */ | ||
335 | return LastIndSeq; | ||
336 | } | ||
337 | |||
338 | static void ba_indicate_reordering_mpdus_le_seq(struct rt_rtmp_adapter *pAd, | ||
339 | struct rt_ba_rec_entry *pBAEntry, | ||
340 | u16 Sequence) | ||
341 | { | ||
342 | struct reordering_mpdu *mpdu_blk; | ||
343 | |||
344 | NdisAcquireSpinLock(&pBAEntry->RxReRingLock); | ||
345 | while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list))) { | ||
346 | /* find in-order frame */ | ||
347 | if ((mpdu_blk->Sequence == Sequence) | ||
348 | || SEQ_SMALLER(mpdu_blk->Sequence, Sequence, MAXSEQ)) { | ||
349 | /* dequeue in-order frame from reodering list */ | ||
350 | mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list); | ||
351 | /* pass this frame up */ | ||
352 | ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); | ||
353 | /* free mpdu_blk */ | ||
354 | ba_mpdu_blk_free(pAd, mpdu_blk); | ||
355 | } else { | ||
356 | break; | ||
357 | } | ||
358 | } | ||
359 | NdisReleaseSpinLock(&pBAEntry->RxReRingLock); | ||
360 | } | ||
361 | |||
362 | static void ba_refresh_reordering_mpdus(struct rt_rtmp_adapter *pAd, | ||
363 | struct rt_ba_rec_entry *pBAEntry) | ||
364 | { | ||
365 | struct reordering_mpdu *mpdu_blk; | ||
366 | |||
367 | NdisAcquireSpinLock(&pBAEntry->RxReRingLock); | ||
368 | |||
369 | /* dequeue in-order frame from reodering list */ | ||
370 | while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list))) { | ||
371 | /* pass this frame up */ | ||
372 | ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); | ||
373 | |||
374 | pBAEntry->LastIndSeq = mpdu_blk->Sequence; | ||
375 | ba_mpdu_blk_free(pAd, mpdu_blk); | ||
376 | |||
377 | /* update last indicated sequence */ | ||
378 | } | ||
379 | ASSERT(pBAEntry->list.qlen == 0); | ||
380 | pBAEntry->LastIndSeq = RESET_RCV_SEQ; | ||
381 | NdisReleaseSpinLock(&pBAEntry->RxReRingLock); | ||
382 | } | ||
383 | |||
384 | /*static */ | ||
385 | void ba_flush_reordering_timeout_mpdus(struct rt_rtmp_adapter *pAd, | ||
386 | struct rt_ba_rec_entry *pBAEntry, | ||
387 | unsigned long Now32) | ||
388 | { | ||
389 | u16 Sequence; | ||
390 | |||
391 | /* if ((RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+REORDERING_PACKET_TIMEOUT)) && */ | ||
392 | /* (pBAEntry->list.qlen > ((pBAEntry->BAWinSize*7)/8))) //|| */ | ||
393 | /* (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(10*REORDERING_PACKET_TIMEOUT))) && */ | ||
394 | /* (pBAEntry->list.qlen > (pBAEntry->BAWinSize/8))) */ | ||
395 | if (RTMP_TIME_AFTER | ||
396 | ((unsigned long)Now32, | ||
397 | (unsigned long)(pBAEntry->LastIndSeqAtTimer + | ||
398 | (MAX_REORDERING_PACKET_TIMEOUT / 6))) | ||
399 | && (pBAEntry->list.qlen > 1) | ||
400 | ) { | ||
401 | DBGPRINT(RT_DEBUG_TRACE, | ||
402 | ("timeout[%d] (%08lx-%08lx = %d > %d): %x, flush all!\n ", | ||
403 | pBAEntry->list.qlen, Now32, | ||
404 | (pBAEntry->LastIndSeqAtTimer), | ||
405 | (int)((long)Now32 - | ||
406 | (long)(pBAEntry->LastIndSeqAtTimer)), | ||
407 | MAX_REORDERING_PACKET_TIMEOUT, pBAEntry->LastIndSeq)); | ||
408 | ba_refresh_reordering_mpdus(pAd, pBAEntry); | ||
409 | pBAEntry->LastIndSeqAtTimer = Now32; | ||
410 | } else | ||
411 | if (RTMP_TIME_AFTER | ||
412 | ((unsigned long)Now32, | ||
413 | (unsigned long)(pBAEntry->LastIndSeqAtTimer + | ||
414 | (REORDERING_PACKET_TIMEOUT))) | ||
415 | && (pBAEntry->list.qlen > 0) | ||
416 | ) { | ||
417 | /* */ | ||
418 | /* force LastIndSeq to shift to LastIndSeq+1 */ | ||
419 | /* */ | ||
420 | Sequence = (pBAEntry->LastIndSeq + 1) & MAXSEQ; | ||
421 | ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence); | ||
422 | pBAEntry->LastIndSeqAtTimer = Now32; | ||
423 | pBAEntry->LastIndSeq = Sequence; | ||
424 | /* */ | ||
425 | /* indicate in-order mpdus */ | ||
426 | /* */ | ||
427 | Sequence = | ||
428 | ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, | ||
429 | Sequence); | ||
430 | if (Sequence != RESET_RCV_SEQ) { | ||
431 | pBAEntry->LastIndSeq = Sequence; | ||
432 | } | ||
433 | |||
434 | DBGPRINT(RT_DEBUG_OFF, | ||
435 | ("%x, flush one!\n", pBAEntry->LastIndSeq)); | ||
436 | |||
437 | } | ||
438 | } | ||
439 | |||
440 | /* | ||
441 | * generate ADDBA request to | ||
442 | * set up BA agreement | ||
443 | */ | ||
444 | void BAOriSessionSetUp(struct rt_rtmp_adapter *pAd, | ||
445 | struct rt_mac_table_entry *pEntry, | ||
446 | u8 TID, | ||
447 | u16 TimeOut, | ||
448 | unsigned long DelayTime, IN BOOLEAN isForced) | ||
449 | { | ||
450 | /*struct rt_mlme_addba_req AddbaReq; */ | ||
451 | struct rt_ba_ori_entry *pBAEntry = NULL; | ||
452 | u16 Idx; | ||
453 | BOOLEAN Cancelled; | ||
454 | |||
455 | if ((pAd->CommonCfg.BACapability.field.AutoBA != TRUE) | ||
456 | && (isForced == FALSE)) | ||
457 | return; | ||
458 | |||
459 | /* if this entry is limited to use legacy tx mode, it doesn't generate BA. */ | ||
460 | if (RTMPStaFixedTxMode(pAd, pEntry) != FIXED_TXMODE_HT) | ||
461 | return; | ||
462 | |||
463 | if ((pEntry->BADeclineBitmap & (1 << TID)) && (isForced == FALSE)) { | ||
464 | /* try again after 3 secs */ | ||
465 | DelayTime = 3000; | ||
466 | /* DBGPRINT(RT_DEBUG_TRACE, ("DeCline BA from Peer\n")); */ | ||
467 | /* return; */ | ||
468 | } | ||
469 | |||
470 | Idx = pEntry->BAOriWcidArray[TID]; | ||
471 | if (Idx == 0) { | ||
472 | /* allocate a BA session */ | ||
473 | pBAEntry = BATableAllocOriEntry(pAd, &Idx); | ||
474 | if (pBAEntry == NULL) { | ||
475 | DBGPRINT(RT_DEBUG_TRACE, | ||
476 | ("ADDBA - MlmeADDBAAction() allocate BA session failed \n")); | ||
477 | return; | ||
478 | } | ||
479 | } else { | ||
480 | pBAEntry = &pAd->BATable.BAOriEntry[Idx]; | ||
481 | } | ||
482 | |||
483 | if (pBAEntry->ORI_BA_Status >= Originator_WaitRes) { | ||
484 | return; | ||
485 | } | ||
486 | |||
487 | pEntry->BAOriWcidArray[TID] = Idx; | ||
488 | |||
489 | /* Initialize BA session */ | ||
490 | pBAEntry->ORI_BA_Status = Originator_WaitRes; | ||
491 | pBAEntry->Wcid = pEntry->Aid; | ||
492 | pBAEntry->BAWinSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit; | ||
493 | pBAEntry->Sequence = BA_ORI_INIT_SEQ; | ||
494 | pBAEntry->Token = 1; /* (2008-01-21) Jan Lee recommends it - this token can't be 0 */ | ||
495 | pBAEntry->TID = TID; | ||
496 | pBAEntry->TimeOutValue = TimeOut; | ||
497 | pBAEntry->pAdapter = pAd; | ||
498 | |||
499 | if (!(pEntry->TXBAbitmap & (1 << TID))) { | ||
500 | RTMPInitTimer(pAd, &pBAEntry->ORIBATimer, | ||
501 | GET_TIMER_FUNCTION(BAOriSessionSetupTimeout), | ||
502 | pBAEntry, FALSE); | ||
503 | } else | ||
504 | RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled); | ||
505 | |||
506 | /* set timer to send ADDBA request */ | ||
507 | RTMPSetTimer(&pBAEntry->ORIBATimer, DelayTime); | ||
508 | } | ||
509 | |||
510 | void BAOriSessionAdd(struct rt_rtmp_adapter *pAd, | ||
511 | struct rt_mac_table_entry *pEntry, struct rt_frame_addba_rsp * pFrame) | ||
512 | { | ||
513 | struct rt_ba_ori_entry *pBAEntry = NULL; | ||
514 | BOOLEAN Cancelled; | ||
515 | u8 TID; | ||
516 | u16 Idx; | ||
517 | u8 *pOutBuffer2 = NULL; | ||
518 | int NStatus; | ||
519 | unsigned long FrameLen; | ||
520 | struct rt_frame_bar FrameBar; | ||
521 | |||
522 | TID = pFrame->BaParm.TID; | ||
523 | Idx = pEntry->BAOriWcidArray[TID]; | ||
524 | pBAEntry = &pAd->BATable.BAOriEntry[Idx]; | ||
525 | |||
526 | /* Start fill in parameters. */ | ||
527 | if ((Idx != 0) && (pBAEntry->TID == TID) | ||
528 | && (pBAEntry->ORI_BA_Status == Originator_WaitRes)) { | ||
529 | pBAEntry->BAWinSize = | ||
530 | min(pBAEntry->BAWinSize, ((u8)pFrame->BaParm.BufSize)); | ||
531 | BA_MaxWinSizeReasign(pAd, pEntry, &pBAEntry->BAWinSize); | ||
532 | |||
533 | pBAEntry->TimeOutValue = pFrame->TimeOutValue; | ||
534 | pBAEntry->ORI_BA_Status = Originator_Done; | ||
535 | pAd->BATable.numDoneOriginator++; | ||
536 | |||
537 | /* reset sequence number */ | ||
538 | pBAEntry->Sequence = BA_ORI_INIT_SEQ; | ||
539 | /* Set Bitmap flag. */ | ||
540 | pEntry->TXBAbitmap |= (1 << TID); | ||
541 | RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled); | ||
542 | |||
543 | pBAEntry->ORIBATimer.TimerValue = 0; /*pFrame->TimeOutValue; */ | ||
544 | |||
545 | DBGPRINT(RT_DEBUG_TRACE, | ||
546 | ("%s : TXBAbitmap = %x, BAWinSize = %d, TimeOut = %ld\n", | ||
547 | __func__, pEntry->TXBAbitmap, pBAEntry->BAWinSize, | ||
548 | pBAEntry->ORIBATimer.TimerValue)); | ||
549 | |||
550 | /* SEND BAR ; */ | ||
551 | NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); /*Get an unused nonpaged memory */ | ||
552 | if (NStatus != NDIS_STATUS_SUCCESS) { | ||
553 | DBGPRINT(RT_DEBUG_TRACE, | ||
554 | ("BA - BAOriSessionAdd() allocate memory failed \n")); | ||
555 | return; | ||
556 | } | ||
557 | |||
558 | BarHeaderInit(pAd, &FrameBar, | ||
559 | pAd->MacTab.Content[pBAEntry->Wcid].Addr, | ||
560 | pAd->CurrentAddress); | ||
561 | |||
562 | FrameBar.StartingSeq.field.FragNum = 0; /* make sure sequence not clear in DEL function. */ | ||
563 | FrameBar.StartingSeq.field.StartSeq = pBAEntry->Sequence; /* make sure sequence not clear in DEL funciton. */ | ||
564 | FrameBar.BarControl.TID = pBAEntry->TID; /* make sure sequence not clear in DEL funciton. */ | ||
565 | MakeOutgoingFrame(pOutBuffer2, &FrameLen, | ||
566 | sizeof(struct rt_frame_bar), &FrameBar, END_OF_ARGS); | ||
567 | MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen); | ||
568 | MlmeFreeMemory(pAd, pOutBuffer2); | ||
569 | |||
570 | if (pBAEntry->ORIBATimer.TimerValue) | ||
571 | RTMPSetTimer(&pBAEntry->ORIBATimer, pBAEntry->ORIBATimer.TimerValue); /* in mSec */ | ||
572 | } | ||
573 | } | ||
574 | |||
575 | BOOLEAN BARecSessionAdd(struct rt_rtmp_adapter *pAd, | ||
576 | struct rt_mac_table_entry *pEntry, struct rt_frame_addba_req * pFrame) | ||
577 | { | ||
578 | struct rt_ba_rec_entry *pBAEntry = NULL; | ||
579 | BOOLEAN Status = TRUE; | ||
580 | BOOLEAN Cancelled; | ||
581 | u16 Idx; | ||
582 | u8 TID; | ||
583 | u8 BAWinSize; | ||
584 | /*u32 Value; */ | ||
585 | /*u32 offset; */ | ||
586 | |||
587 | ASSERT(pEntry); | ||
588 | |||
589 | /* find TID */ | ||
590 | TID = pFrame->BaParm.TID; | ||
591 | |||
592 | BAWinSize = | ||
593 | min(((u8)pFrame->BaParm.BufSize), | ||
594 | (u8)pAd->CommonCfg.BACapability.field.RxBAWinLimit); | ||
595 | |||
596 | /* Intel patch */ | ||
597 | if (BAWinSize == 0) { | ||
598 | BAWinSize = 64; | ||
599 | } | ||
600 | |||
601 | Idx = pEntry->BARecWcidArray[TID]; | ||
602 | |||
603 | if (Idx == 0) { | ||
604 | pBAEntry = BATableAllocRecEntry(pAd, &Idx); | ||
605 | } else { | ||
606 | pBAEntry = &pAd->BATable.BARecEntry[Idx]; | ||
607 | /* flush all pending reordering mpdus */ | ||
608 | ba_refresh_reordering_mpdus(pAd, pBAEntry); | ||
609 | } | ||
610 | |||
611 | DBGPRINT(RT_DEBUG_TRACE, | ||
612 | ("%s(%ld): Idx = %d, BAWinSize(req %d) = %d\n", __func__, | ||
613 | pAd->BATable.numAsRecipient, Idx, pFrame->BaParm.BufSize, | ||
614 | BAWinSize)); | ||
615 | |||
616 | /* Start fill in parameters. */ | ||
617 | if (pBAEntry != NULL) { | ||
618 | ASSERT(pBAEntry->list.qlen == 0); | ||
619 | |||
620 | pBAEntry->REC_BA_Status = Recipient_HandleRes; | ||
621 | pBAEntry->BAWinSize = BAWinSize; | ||
622 | pBAEntry->Wcid = pEntry->Aid; | ||
623 | pBAEntry->TID = TID; | ||
624 | pBAEntry->TimeOutValue = pFrame->TimeOutValue; | ||
625 | pBAEntry->REC_BA_Status = Recipient_Accept; | ||
626 | /* initial sequence number */ | ||
627 | pBAEntry->LastIndSeq = RESET_RCV_SEQ; /*pFrame->BaStartSeq.field.StartSeq; */ | ||
628 | |||
629 | DBGPRINT(RT_DEBUG_OFF, | ||
630 | ("Start Seq = %08x\n", | ||
631 | pFrame->BaStartSeq.field.StartSeq)); | ||
632 | |||
633 | if (pEntry->RXBAbitmap & (1 << TID)) { | ||
634 | RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled); | ||
635 | } else { | ||
636 | RTMPInitTimer(pAd, &pBAEntry->RECBATimer, | ||
637 | GET_TIMER_FUNCTION | ||
638 | (BARecSessionIdleTimeout), pBAEntry, | ||
639 | TRUE); | ||
640 | } | ||
641 | |||
642 | /* Set Bitmap flag. */ | ||
643 | pEntry->RXBAbitmap |= (1 << TID); | ||
644 | pEntry->BARecWcidArray[TID] = Idx; | ||
645 | |||
646 | pEntry->BADeclineBitmap &= ~(1 << TID); | ||
647 | |||
648 | /* Set BA session mask in WCID table. */ | ||
649 | RTMP_ADD_BA_SESSION_TO_ASIC(pAd, pEntry->Aid, TID); | ||
650 | |||
651 | DBGPRINT(RT_DEBUG_TRACE, | ||
652 | ("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n", | ||
653 | pEntry->Aid, pEntry->RXBAbitmap, | ||
654 | pEntry->BARecWcidArray[TID])); | ||
655 | } else { | ||
656 | Status = FALSE; | ||
657 | DBGPRINT(RT_DEBUG_TRACE, | ||
658 | ("Can't Accept ADDBA for %pM TID = %d\n", | ||
659 | pEntry->Addr, TID)); | ||
660 | } | ||
661 | return (Status); | ||
662 | } | ||
663 | |||
664 | struct rt_ba_rec_entry *BATableAllocRecEntry(struct rt_rtmp_adapter *pAd, u16 * Idx) | ||
665 | { | ||
666 | int i; | ||
667 | struct rt_ba_rec_entry *pBAEntry = NULL; | ||
668 | |||
669 | NdisAcquireSpinLock(&pAd->BATabLock); | ||
670 | |||
671 | if (pAd->BATable.numAsRecipient >= MAX_BARECI_SESSION) { | ||
672 | DBGPRINT(RT_DEBUG_OFF, ("BA Recipeint Session (%ld) > %d\n", | ||
673 | pAd->BATable.numAsRecipient, | ||
674 | MAX_BARECI_SESSION)); | ||
675 | goto done; | ||
676 | } | ||
677 | /* reserve idx 0 to identify BAWcidArray[TID] as empty */ | ||
678 | for (i = 1; i < MAX_LEN_OF_BA_REC_TABLE; i++) { | ||
679 | pBAEntry = &pAd->BATable.BARecEntry[i]; | ||
680 | if ((pBAEntry->REC_BA_Status == Recipient_NONE)) { | ||
681 | /* get one */ | ||
682 | pAd->BATable.numAsRecipient++; | ||
683 | pBAEntry->REC_BA_Status = Recipient_USED; | ||
684 | *Idx = i; | ||
685 | break; | ||
686 | } | ||
687 | } | ||
688 | |||
689 | done: | ||
690 | NdisReleaseSpinLock(&pAd->BATabLock); | ||
691 | return pBAEntry; | ||
692 | } | ||
693 | |||
694 | struct rt_ba_ori_entry *BATableAllocOriEntry(struct rt_rtmp_adapter *pAd, u16 * Idx) | ||
695 | { | ||
696 | int i; | ||
697 | struct rt_ba_ori_entry *pBAEntry = NULL; | ||
698 | |||
699 | NdisAcquireSpinLock(&pAd->BATabLock); | ||
700 | |||
701 | if (pAd->BATable.numAsOriginator >= (MAX_LEN_OF_BA_ORI_TABLE)) { | ||
702 | goto done; | ||
703 | } | ||
704 | /* reserve idx 0 to identify BAWcidArray[TID] as empty */ | ||
705 | for (i = 1; i < MAX_LEN_OF_BA_ORI_TABLE; i++) { | ||
706 | pBAEntry = &pAd->BATable.BAOriEntry[i]; | ||
707 | if ((pBAEntry->ORI_BA_Status == Originator_NONE)) { | ||
708 | /* get one */ | ||
709 | pAd->BATable.numAsOriginator++; | ||
710 | pBAEntry->ORI_BA_Status = Originator_USED; | ||
711 | pBAEntry->pAdapter = pAd; | ||
712 | *Idx = i; | ||
713 | break; | ||
714 | } | ||
715 | } | ||
716 | |||
717 | done: | ||
718 | NdisReleaseSpinLock(&pAd->BATabLock); | ||
719 | return pBAEntry; | ||
720 | } | ||
721 | |||
722 | void BATableFreeOriEntry(struct rt_rtmp_adapter *pAd, unsigned long Idx) | ||
723 | { | ||
724 | struct rt_ba_ori_entry *pBAEntry = NULL; | ||
725 | struct rt_mac_table_entry *pEntry; | ||
726 | |||
727 | if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE)) | ||
728 | return; | ||
729 | |||
730 | pBAEntry = &pAd->BATable.BAOriEntry[Idx]; | ||
731 | |||
732 | if (pBAEntry->ORI_BA_Status != Originator_NONE) { | ||
733 | pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; | ||
734 | pEntry->BAOriWcidArray[pBAEntry->TID] = 0; | ||
735 | |||
736 | NdisAcquireSpinLock(&pAd->BATabLock); | ||
737 | if (pBAEntry->ORI_BA_Status == Originator_Done) { | ||
738 | pAd->BATable.numDoneOriginator -= 1; | ||
739 | pEntry->TXBAbitmap &= (~(1 << (pBAEntry->TID))); | ||
740 | DBGPRINT(RT_DEBUG_TRACE, | ||
741 | ("BATableFreeOriEntry numAsOriginator= %ld\n", | ||
742 | pAd->BATable.numAsRecipient)); | ||
743 | /* Erase Bitmap flag. */ | ||
744 | } | ||
745 | |||
746 | ASSERT(pAd->BATable.numAsOriginator != 0); | ||
747 | |||
748 | pAd->BATable.numAsOriginator -= 1; | ||
749 | |||
750 | pBAEntry->ORI_BA_Status = Originator_NONE; | ||
751 | pBAEntry->Token = 0; | ||
752 | NdisReleaseSpinLock(&pAd->BATabLock); | ||
753 | } | ||
754 | } | ||
755 | |||
756 | void BATableFreeRecEntry(struct rt_rtmp_adapter *pAd, unsigned long Idx) | ||
757 | { | ||
758 | struct rt_ba_rec_entry *pBAEntry = NULL; | ||
759 | struct rt_mac_table_entry *pEntry; | ||
760 | |||
761 | if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_REC_TABLE)) | ||
762 | return; | ||
763 | |||
764 | pBAEntry = &pAd->BATable.BARecEntry[Idx]; | ||
765 | |||
766 | if (pBAEntry->REC_BA_Status != Recipient_NONE) { | ||
767 | pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; | ||
768 | pEntry->BARecWcidArray[pBAEntry->TID] = 0; | ||
769 | |||
770 | NdisAcquireSpinLock(&pAd->BATabLock); | ||
771 | |||
772 | ASSERT(pAd->BATable.numAsRecipient != 0); | ||
773 | |||
774 | pAd->BATable.numAsRecipient -= 1; | ||
775 | |||
776 | pBAEntry->REC_BA_Status = Recipient_NONE; | ||
777 | NdisReleaseSpinLock(&pAd->BATabLock); | ||
778 | } | ||
779 | } | ||
780 | |||
781 | void BAOriSessionTearDown(struct rt_rtmp_adapter *pAd, | ||
782 | u8 Wcid, | ||
783 | u8 TID, | ||
784 | IN BOOLEAN bPassive, IN BOOLEAN bForceSend) | ||
785 | { | ||
786 | unsigned long Idx = 0; | ||
787 | struct rt_ba_ori_entry *pBAEntry; | ||
788 | BOOLEAN Cancelled; | ||
789 | |||
790 | if (Wcid >= MAX_LEN_OF_MAC_TABLE) { | ||
791 | return; | ||
792 | } | ||
793 | /* */ | ||
794 | /* Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID). */ | ||
795 | /* */ | ||
796 | Idx = pAd->MacTab.Content[Wcid].BAOriWcidArray[TID]; | ||
797 | if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE)) { | ||
798 | if (bForceSend == TRUE) { | ||
799 | /* force send specified TID DelBA */ | ||
800 | struct rt_mlme_delba_req DelbaReq; | ||
801 | struct rt_mlme_queue_elem *Elem = | ||
802 | kmalloc(sizeof(struct rt_mlme_queue_elem), | ||
803 | MEM_ALLOC_FLAG); | ||
804 | if (Elem != NULL) { | ||
805 | NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); | ||
806 | NdisZeroMemory(Elem, sizeof(struct rt_mlme_queue_elem)); | ||
807 | |||
808 | COPY_MAC_ADDR(DelbaReq.Addr, | ||
809 | pAd->MacTab.Content[Wcid].Addr); | ||
810 | DelbaReq.Wcid = Wcid; | ||
811 | DelbaReq.TID = TID; | ||
812 | DelbaReq.Initiator = ORIGINATOR; | ||
813 | Elem->MsgLen = sizeof(DelbaReq); | ||
814 | NdisMoveMemory(Elem->Msg, &DelbaReq, | ||
815 | sizeof(DelbaReq)); | ||
816 | MlmeDELBAAction(pAd, Elem); | ||
817 | kfree(Elem); | ||
818 | } else { | ||
819 | DBGPRINT(RT_DEBUG_ERROR, | ||
820 | ("%s(bForceSend):alloc memory failed!\n", | ||
821 | __func__)); | ||
822 | } | ||
823 | } | ||
824 | |||
825 | return; | ||
826 | } | ||
827 | |||
828 | DBGPRINT(RT_DEBUG_TRACE, | ||
829 | ("%s===>Wcid=%d.TID=%d \n", __func__, Wcid, TID)); | ||
830 | |||
831 | pBAEntry = &pAd->BATable.BAOriEntry[Idx]; | ||
832 | DBGPRINT(RT_DEBUG_TRACE, | ||
833 | ("\t===>Idx = %ld, Wcid=%d.TID=%d, ORI_BA_Status = %d \n", Idx, | ||
834 | Wcid, TID, pBAEntry->ORI_BA_Status)); | ||
835 | /* */ | ||
836 | /* Prepare DelBA action frame and send to the peer. */ | ||
837 | /* */ | ||
838 | if ((bPassive == FALSE) && (TID == pBAEntry->TID) | ||
839 | && (pBAEntry->ORI_BA_Status == Originator_Done)) { | ||
840 | struct rt_mlme_delba_req DelbaReq; | ||
841 | struct rt_mlme_queue_elem *Elem = | ||
842 | kmalloc(sizeof(struct rt_mlme_queue_elem), | ||
843 | MEM_ALLOC_FLAG); | ||
844 | if (Elem != NULL) { | ||
845 | NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); | ||
846 | NdisZeroMemory(Elem, sizeof(struct rt_mlme_queue_elem)); | ||
847 | |||
848 | COPY_MAC_ADDR(DelbaReq.Addr, | ||
849 | pAd->MacTab.Content[Wcid].Addr); | ||
850 | DelbaReq.Wcid = Wcid; | ||
851 | DelbaReq.TID = pBAEntry->TID; | ||
852 | DelbaReq.Initiator = ORIGINATOR; | ||
853 | Elem->MsgLen = sizeof(DelbaReq); | ||
854 | NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq)); | ||
855 | MlmeDELBAAction(pAd, Elem); | ||
856 | kfree(Elem); | ||
857 | } else { | ||
858 | DBGPRINT(RT_DEBUG_ERROR, | ||
859 | ("%s():alloc memory failed!\n", __func__)); | ||
860 | return; | ||
861 | } | ||
862 | } | ||
863 | RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled); | ||
864 | BATableFreeOriEntry(pAd, Idx); | ||
865 | |||
866 | if (bPassive) { | ||
867 | /*BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE); */ | ||
868 | } | ||
869 | } | ||
870 | |||
871 | void BARecSessionTearDown(struct rt_rtmp_adapter *pAd, | ||
872 | u8 Wcid, u8 TID, IN BOOLEAN bPassive) | ||
873 | { | ||
874 | unsigned long Idx = 0; | ||
875 | struct rt_ba_rec_entry *pBAEntry; | ||
876 | |||
877 | if (Wcid >= MAX_LEN_OF_MAC_TABLE) { | ||
878 | return; | ||
879 | } | ||
880 | /* */ | ||
881 | /* Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID). */ | ||
882 | /* */ | ||
883 | Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; | ||
884 | if (Idx == 0) | ||
885 | return; | ||
886 | |||
887 | DBGPRINT(RT_DEBUG_TRACE, | ||
888 | ("%s===>Wcid=%d.TID=%d \n", __func__, Wcid, TID)); | ||
889 | |||
890 | pBAEntry = &pAd->BATable.BARecEntry[Idx]; | ||
891 | DBGPRINT(RT_DEBUG_TRACE, | ||
892 | ("\t===>Idx = %ld, Wcid=%d.TID=%d, REC_BA_Status = %d \n", Idx, | ||
893 | Wcid, TID, pBAEntry->REC_BA_Status)); | ||
894 | /* */ | ||
895 | /* Prepare DelBA action frame and send to the peer. */ | ||
896 | /* */ | ||
897 | if ((TID == pBAEntry->TID) | ||
898 | && (pBAEntry->REC_BA_Status == Recipient_Accept)) { | ||
899 | struct rt_mlme_delba_req DelbaReq; | ||
900 | BOOLEAN Cancelled; | ||
901 | /*unsigned long offset; */ | ||
902 | /*u32 VALUE; */ | ||
903 | |||
904 | RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled); | ||
905 | |||
906 | /* */ | ||
907 | /* 1. Send DELBA Action Frame */ | ||
908 | /* */ | ||
909 | if (bPassive == FALSE) { | ||
910 | struct rt_mlme_queue_elem *Elem = | ||
911 | kmalloc(sizeof(struct rt_mlme_queue_elem), | ||
912 | MEM_ALLOC_FLAG); | ||
913 | if (Elem != NULL) { | ||
914 | NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); | ||
915 | NdisZeroMemory(Elem, sizeof(struct rt_mlme_queue_elem)); | ||
916 | |||
917 | COPY_MAC_ADDR(DelbaReq.Addr, | ||
918 | pAd->MacTab.Content[Wcid].Addr); | ||
919 | DelbaReq.Wcid = Wcid; | ||
920 | DelbaReq.TID = TID; | ||
921 | DelbaReq.Initiator = RECIPIENT; | ||
922 | Elem->MsgLen = sizeof(DelbaReq); | ||
923 | NdisMoveMemory(Elem->Msg, &DelbaReq, | ||
924 | sizeof(DelbaReq)); | ||
925 | MlmeDELBAAction(pAd, Elem); | ||
926 | kfree(Elem); | ||
927 | } else { | ||
928 | DBGPRINT(RT_DEBUG_ERROR, | ||
929 | ("%s():alloc memory failed!\n", | ||
930 | __func__)); | ||
931 | return; | ||
932 | } | ||
933 | } | ||
934 | |||
935 | /* */ | ||
936 | /* 2. Free resource of BA session */ | ||
937 | /* */ | ||
938 | /* flush all pending reordering mpdus */ | ||
939 | ba_refresh_reordering_mpdus(pAd, pBAEntry); | ||
940 | |||
941 | NdisAcquireSpinLock(&pAd->BATabLock); | ||
942 | |||
943 | /* Erase Bitmap flag. */ | ||
944 | pBAEntry->LastIndSeq = RESET_RCV_SEQ; | ||
945 | pBAEntry->BAWinSize = 0; | ||
946 | /* Erase Bitmap flag at software mactable */ | ||
947 | pAd->MacTab.Content[Wcid].RXBAbitmap &= | ||
948 | (~(1 << (pBAEntry->TID))); | ||
949 | pAd->MacTab.Content[Wcid].BARecWcidArray[TID] = 0; | ||
950 | |||
951 | RTMP_DEL_BA_SESSION_FROM_ASIC(pAd, Wcid, TID); | ||
952 | |||
953 | NdisReleaseSpinLock(&pAd->BATabLock); | ||
954 | |||
955 | } | ||
956 | |||
957 | BATableFreeRecEntry(pAd, Idx); | ||
958 | } | ||
959 | |||
960 | void BASessionTearDownALL(struct rt_rtmp_adapter *pAd, u8 Wcid) | ||
961 | { | ||
962 | int i; | ||
963 | |||
964 | for (i = 0; i < NUM_OF_TID; i++) { | ||
965 | BAOriSessionTearDown(pAd, Wcid, i, FALSE, FALSE); | ||
966 | BARecSessionTearDown(pAd, Wcid, i, FALSE); | ||
967 | } | ||
968 | } | ||
969 | |||
970 | /* | ||
971 | ========================================================================== | ||
972 | Description: | ||
973 | Retry sending ADDBA Reqest. | ||
974 | |||
975 | IRQL = DISPATCH_LEVEL | ||
976 | |||
977 | Parametrs: | ||
978 | p8023Header: if this is already 802.3 format, p8023Header is NULL | ||
979 | |||
980 | Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere. | ||
981 | FALSE , then continue indicaterx at this moment. | ||
982 | ========================================================================== | ||
983 | */ | ||
984 | void BAOriSessionSetupTimeout(void *SystemSpecific1, | ||
985 | void *FunctionContext, | ||
986 | void *SystemSpecific2, | ||
987 | void *SystemSpecific3) | ||
988 | { | ||
989 | struct rt_ba_ori_entry *pBAEntry = (struct rt_ba_ori_entry *)FunctionContext; | ||
990 | struct rt_mac_table_entry *pEntry; | ||
991 | struct rt_rtmp_adapter *pAd; | ||
992 | |||
993 | if (pBAEntry == NULL) | ||
994 | return; | ||
995 | |||
996 | pAd = pBAEntry->pAdapter; | ||
997 | |||
998 | { | ||
999 | /* Do nothing if monitor mode is on */ | ||
1000 | if (MONITOR_ON(pAd)) | ||
1001 | return; | ||
1002 | } | ||
1003 | |||
1004 | pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; | ||
1005 | |||
1006 | if ((pBAEntry->ORI_BA_Status == Originator_WaitRes) | ||
1007 | && (pBAEntry->Token < ORI_SESSION_MAX_RETRY)) { | ||
1008 | struct rt_mlme_addba_req AddbaReq; | ||
1009 | |||
1010 | NdisZeroMemory(&AddbaReq, sizeof(AddbaReq)); | ||
1011 | COPY_MAC_ADDR(AddbaReq.pAddr, pEntry->Addr); | ||
1012 | AddbaReq.Wcid = (u8)(pEntry->Aid); | ||
1013 | AddbaReq.TID = pBAEntry->TID; | ||
1014 | AddbaReq.BaBufSize = | ||
1015 | pAd->CommonCfg.BACapability.field.RxBAWinLimit; | ||
1016 | AddbaReq.TimeOutValue = 0; | ||
1017 | AddbaReq.Token = pBAEntry->Token; | ||
1018 | MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ADD_BA_CATE, | ||
1019 | sizeof(struct rt_mlme_addba_req), (void *)& AddbaReq); | ||
1020 | RTMP_MLME_HANDLER(pAd); | ||
1021 | DBGPRINT(RT_DEBUG_TRACE, | ||
1022 | ("BA Ori Session Timeout(%d) : Send ADD BA again\n", | ||
1023 | pBAEntry->Token)); | ||
1024 | |||
1025 | pBAEntry->Token++; | ||
1026 | RTMPSetTimer(&pBAEntry->ORIBATimer, ORI_BA_SESSION_TIMEOUT); | ||
1027 | } else { | ||
1028 | BATableFreeOriEntry(pAd, pEntry->BAOriWcidArray[pBAEntry->TID]); | ||
1029 | } | ||
1030 | } | ||
1031 | |||
1032 | /* | ||
1033 | ========================================================================== | ||
1034 | Description: | ||
1035 | Retry sending ADDBA Reqest. | ||
1036 | |||
1037 | IRQL = DISPATCH_LEVEL | ||
1038 | |||
1039 | Parametrs: | ||
1040 | p8023Header: if this is already 802.3 format, p8023Header is NULL | ||
1041 | |||
1042 | Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere. | ||
1043 | FALSE , then continue indicaterx at this moment. | ||
1044 | ========================================================================== | ||
1045 | */ | ||
1046 | void BARecSessionIdleTimeout(void *SystemSpecific1, | ||
1047 | void *FunctionContext, | ||
1048 | void *SystemSpecific2, void *SystemSpecific3) | ||
1049 | { | ||
1050 | |||
1051 | struct rt_ba_rec_entry *pBAEntry = (struct rt_ba_rec_entry *)FunctionContext; | ||
1052 | struct rt_rtmp_adapter *pAd; | ||
1053 | unsigned long Now32; | ||
1054 | |||
1055 | if (pBAEntry == NULL) | ||
1056 | return; | ||
1057 | |||
1058 | if ((pBAEntry->REC_BA_Status == Recipient_Accept)) { | ||
1059 | NdisGetSystemUpTime(&Now32); | ||
1060 | |||
1061 | if (RTMP_TIME_AFTER | ||
1062 | ((unsigned long)Now32, | ||
1063 | (unsigned long)(pBAEntry->LastIndSeqAtTimer + | ||
1064 | REC_BA_SESSION_IDLE_TIMEOUT))) { | ||
1065 | pAd = pBAEntry->pAdapter; | ||
1066 | /* flush all pending reordering mpdus */ | ||
1067 | ba_refresh_reordering_mpdus(pAd, pBAEntry); | ||
1068 | DBGPRINT(RT_DEBUG_OFF, | ||
1069 | ("%ld: REC BA session Timeout\n", Now32)); | ||
1070 | } | ||
1071 | } | ||
1072 | } | ||
1073 | |||
1074 | void PeerAddBAReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) | ||
1075 | { | ||
1076 | /* 7.4.4.1 */ | ||
1077 | /*unsigned long Idx; */ | ||
1078 | u8 Status = 1; | ||
1079 | u8 pAddr[6]; | ||
1080 | struct rt_frame_addba_rsp ADDframe; | ||
1081 | u8 *pOutBuffer = NULL; | ||
1082 | int NStatus; | ||
1083 | struct rt_frame_addba_req * pAddreqFrame = NULL; | ||
1084 | /*u8 BufSize; */ | ||
1085 | unsigned long FrameLen; | ||
1086 | unsigned long *ptemp; | ||
1087 | struct rt_mac_table_entry *pMacEntry; | ||
1088 | |||
1089 | DBGPRINT(RT_DEBUG_TRACE, | ||
1090 | ("%s ==> (Wcid = %d)\n", __func__, Elem->Wcid)); | ||
1091 | |||
1092 | /*hex_dump("AddBAReq", Elem->Msg, Elem->MsgLen); */ | ||
1093 | |||
1094 | /*ADDBA Request from unknown peer, ignore this. */ | ||
1095 | if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) | ||
1096 | return; | ||
1097 | |||
1098 | pMacEntry = &pAd->MacTab.Content[Elem->Wcid]; | ||
1099 | DBGPRINT(RT_DEBUG_TRACE, ("BA - PeerAddBAReqAction----> \n")); | ||
1100 | ptemp = (unsigned long *)Elem->Msg; | ||
1101 | /*DBGPRINT_RAW(RT_DEBUG_EMU, ("%08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x\n", *(ptemp), *(ptemp+1), *(ptemp+2), *(ptemp+3), *(ptemp+4), *(ptemp+5), *(ptemp+6), *(ptemp+7), *(ptemp+8))); */ | ||
1102 | |||
1103 | if (PeerAddBAReqActionSanity(pAd, Elem->Msg, Elem->MsgLen, pAddr)) { | ||
1104 | |||
1105 | if ((pAd->CommonCfg.bBADecline == FALSE) | ||
1106 | && IS_HT_STA(pMacEntry)) { | ||
1107 | pAddreqFrame = (struct rt_frame_addba_req *) (&Elem->Msg[0]); | ||
1108 | DBGPRINT(RT_DEBUG_OFF, | ||
1109 | ("Rcv Wcid(%d) AddBAReq\n", Elem->Wcid)); | ||
1110 | if (BARecSessionAdd | ||
1111 | (pAd, &pAd->MacTab.Content[Elem->Wcid], | ||
1112 | pAddreqFrame)) | ||
1113 | Status = 0; | ||
1114 | else | ||
1115 | Status = 38; /* more parameters have invalid values */ | ||
1116 | } else { | ||
1117 | Status = 37; /* the request has been declined. */ | ||
1118 | } | ||
1119 | } | ||
1120 | |||
1121 | if (pAd->MacTab.Content[Elem->Wcid].ValidAsCLI) | ||
1122 | ASSERT(pAd->MacTab.Content[Elem->Wcid].Sst == SST_ASSOC); | ||
1123 | |||
1124 | pAddreqFrame = (struct rt_frame_addba_req *) (&Elem->Msg[0]); | ||
1125 | /* 2. Always send back ADDBA Response */ | ||
1126 | NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ | ||
1127 | if (NStatus != NDIS_STATUS_SUCCESS) { | ||
1128 | DBGPRINT(RT_DEBUG_TRACE, | ||
1129 | ("ACTION - PeerBAAction() allocate memory failed \n")); | ||
1130 | return; | ||
1131 | } | ||
1132 | |||
1133 | NdisZeroMemory(&ADDframe, sizeof(struct rt_frame_addba_rsp)); | ||
1134 | |||
1135 | /* 2-1. Prepare ADDBA Response frame. */ | ||
1136 | { | ||
1137 | if (ADHOC_ON(pAd)) | ||
1138 | ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, | ||
1139 | pAd->CurrentAddress, | ||
1140 | pAd->CommonCfg.Bssid); | ||
1141 | else | ||
1142 | ActHeaderInit(pAd, &ADDframe.Hdr, pAd->CommonCfg.Bssid, | ||
1143 | pAd->CurrentAddress, pAddr); | ||
1144 | } | ||
1145 | |||
1146 | ADDframe.Category = CATEGORY_BA; | ||
1147 | ADDframe.Action = ADDBA_RESP; | ||
1148 | ADDframe.Token = pAddreqFrame->Token; | ||
1149 | /* What is the Status code?? need to check. */ | ||
1150 | ADDframe.StatusCode = Status; | ||
1151 | ADDframe.BaParm.BAPolicy = IMMED_BA; | ||
1152 | ADDframe.BaParm.AMSDUSupported = 0; | ||
1153 | ADDframe.BaParm.TID = pAddreqFrame->BaParm.TID; | ||
1154 | ADDframe.BaParm.BufSize = | ||
1155 | min(((u8)pAddreqFrame->BaParm.BufSize), | ||
1156 | (u8)pAd->CommonCfg.BACapability.field.RxBAWinLimit); | ||
1157 | if (ADDframe.BaParm.BufSize == 0) { | ||
1158 | ADDframe.BaParm.BufSize = 64; | ||
1159 | } | ||
1160 | ADDframe.TimeOutValue = 0; /*pAddreqFrame->TimeOutValue; */ | ||
1161 | |||
1162 | *(u16 *) (&ADDframe.BaParm) = | ||
1163 | cpu2le16(*(u16 *) (&ADDframe.BaParm)); | ||
1164 | ADDframe.StatusCode = cpu2le16(ADDframe.StatusCode); | ||
1165 | ADDframe.TimeOutValue = cpu2le16(ADDframe.TimeOutValue); | ||
1166 | |||
1167 | MakeOutgoingFrame(pOutBuffer, &FrameLen, | ||
1168 | sizeof(struct rt_frame_addba_rsp), &ADDframe, END_OF_ARGS); | ||
1169 | MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); | ||
1170 | MlmeFreeMemory(pAd, pOutBuffer); | ||
1171 | |||
1172 | DBGPRINT(RT_DEBUG_TRACE, | ||
1173 | ("%s(%d): TID(%d), BufSize(%d) <== \n", __func__, Elem->Wcid, | ||
1174 | ADDframe.BaParm.TID, ADDframe.BaParm.BufSize)); | ||
1175 | } | ||
1176 | |||
1177 | void PeerAddBARspAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) | ||
1178 | { | ||
1179 | /*u8 Idx, i; */ | ||
1180 | /*u8 * pOutBuffer = NULL; */ | ||
1181 | struct rt_frame_addba_rsp * pFrame = NULL; | ||
1182 | /*struct rt_ba_ori_entry *pBAEntry; */ | ||
1183 | |||
1184 | /*ADDBA Response from unknown peer, ignore this. */ | ||
1185 | if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) | ||
1186 | return; | ||
1187 | |||
1188 | DBGPRINT(RT_DEBUG_TRACE, ("%s ==> Wcid(%d)\n", __func__, Elem->Wcid)); | ||
1189 | |||
1190 | /*hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen); */ | ||
1191 | |||
1192 | if (PeerAddBARspActionSanity(pAd, Elem->Msg, Elem->MsgLen)) { | ||
1193 | pFrame = (struct rt_frame_addba_rsp *) (&Elem->Msg[0]); | ||
1194 | |||
1195 | DBGPRINT(RT_DEBUG_TRACE, | ||
1196 | ("\t\t StatusCode = %d\n", pFrame->StatusCode)); | ||
1197 | switch (pFrame->StatusCode) { | ||
1198 | case 0: | ||
1199 | /* I want a BAsession with this peer as an originator. */ | ||
1200 | BAOriSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], | ||
1201 | pFrame); | ||
1202 | break; | ||
1203 | default: | ||
1204 | /* check status == USED ??? */ | ||
1205 | BAOriSessionTearDown(pAd, Elem->Wcid, | ||
1206 | pFrame->BaParm.TID, TRUE, FALSE); | ||
1207 | break; | ||
1208 | } | ||
1209 | /* Rcv Decline StatusCode */ | ||
1210 | if ((pFrame->StatusCode == 37) | ||
1211 | || ((pAd->OpMode == OPMODE_STA) && STA_TGN_WIFI_ON(pAd) | ||
1212 | && (pFrame->StatusCode != 0)) | ||
1213 | ) { | ||
1214 | pAd->MacTab.Content[Elem->Wcid].BADeclineBitmap |= | ||
1215 | 1 << pFrame->BaParm.TID; | ||
1216 | } | ||
1217 | } | ||
1218 | } | ||
1219 | |||
1220 | void PeerDelBAAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) | ||
1221 | { | ||
1222 | /*u8 Idx; */ | ||
1223 | /*u8 * pOutBuffer = NULL; */ | ||
1224 | struct rt_frame_delba_req * pDelFrame = NULL; | ||
1225 | |||
1226 | DBGPRINT(RT_DEBUG_TRACE, ("%s ==>\n", __func__)); | ||
1227 | /*DELBA Request from unknown peer, ignore this. */ | ||
1228 | if (PeerDelBAActionSanity(pAd, Elem->Wcid, Elem->Msg, Elem->MsgLen)) { | ||
1229 | pDelFrame = (struct rt_frame_delba_req *) (&Elem->Msg[0]); | ||
1230 | if (pDelFrame->DelbaParm.Initiator == ORIGINATOR) { | ||
1231 | DBGPRINT(RT_DEBUG_TRACE, | ||
1232 | ("BA - PeerDelBAAction----> ORIGINATOR\n")); | ||
1233 | BARecSessionTearDown(pAd, Elem->Wcid, | ||
1234 | pDelFrame->DelbaParm.TID, TRUE); | ||
1235 | } else { | ||
1236 | DBGPRINT(RT_DEBUG_TRACE, | ||
1237 | ("BA - PeerDelBAAction----> RECIPIENT, Reason = %d\n", | ||
1238 | pDelFrame->ReasonCode)); | ||
1239 | /*hex_dump("DelBA Frame", pDelFrame, Elem->MsgLen); */ | ||
1240 | BAOriSessionTearDown(pAd, Elem->Wcid, | ||
1241 | pDelFrame->DelbaParm.TID, TRUE, | ||
1242 | FALSE); | ||
1243 | } | ||
1244 | } | ||
1245 | } | ||
1246 | |||
1247 | BOOLEAN CntlEnqueueForRecv(struct rt_rtmp_adapter *pAd, | ||
1248 | unsigned long Wcid, | ||
1249 | unsigned long MsgLen, struct rt_frame_ba_req * pMsg) | ||
1250 | { | ||
1251 | struct rt_frame_ba_req * pFrame = pMsg; | ||
1252 | /*PRTMP_REORDERBUF pBuffer; */ | ||
1253 | /*PRTMP_REORDERBUF pDmaBuf; */ | ||
1254 | struct rt_ba_rec_entry *pBAEntry; | ||
1255 | /*BOOLEAN Result; */ | ||
1256 | unsigned long Idx; | ||
1257 | /*u8 NumRxPkt; */ | ||
1258 | u8 TID; /*, i; */ | ||
1259 | |||
1260 | TID = (u8)pFrame->BARControl.TID; | ||
1261 | |||
1262 | DBGPRINT(RT_DEBUG_TRACE, | ||
1263 | ("%s(): BAR-Wcid(%ld), Tid (%d)\n", __func__, Wcid, TID)); | ||
1264 | /*hex_dump("BAR", (char *)pFrame, MsgLen); */ | ||
1265 | /* Do nothing if the driver is starting halt state. */ | ||
1266 | /* This might happen when timer already been fired before cancel timer with mlmehalt */ | ||
1267 | if (RTMP_TEST_FLAG | ||
1268 | (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) | ||
1269 | return FALSE; | ||
1270 | |||
1271 | /* First check the size, it MUST not exceed the mlme queue size */ | ||
1272 | if (MsgLen > MGMT_DMA_BUFFER_SIZE) { | ||
1273 | DBGPRINT_ERR("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen); | ||
1274 | return FALSE; | ||
1275 | } else if (MsgLen != sizeof(struct rt_frame_ba_req)) { | ||
1276 | DBGPRINT_ERR("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen); | ||
1277 | return FALSE; | ||
1278 | } else if (MsgLen != sizeof(struct rt_frame_ba_req)) { | ||
1279 | DBGPRINT_ERR("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen); | ||
1280 | return FALSE; | ||
1281 | } | ||
1282 | |||
1283 | if ((Wcid < MAX_LEN_OF_MAC_TABLE) && (TID < 8)) { | ||
1284 | /* if this receiving packet is from SA that is in our OriEntry. Since WCID <9 has direct mapping. no need search. */ | ||
1285 | Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; | ||
1286 | pBAEntry = &pAd->BATable.BARecEntry[Idx]; | ||
1287 | } else { | ||
1288 | return FALSE; | ||
1289 | } | ||
1290 | |||
1291 | DBGPRINT(RT_DEBUG_TRACE, | ||
1292 | ("BAR(%ld) : Tid (%d) - %04x:%04x\n", Wcid, TID, | ||
1293 | pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq)); | ||
1294 | |||
1295 | if (SEQ_SMALLER | ||
1296 | (pBAEntry->LastIndSeq, pFrame->BAStartingSeq.field.StartSeq, | ||
1297 | MAXSEQ)) { | ||
1298 | /*DBGPRINT(RT_DEBUG_TRACE, ("BAR Seq = %x, LastIndSeq = %x\n", pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq)); */ | ||
1299 | ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, | ||
1300 | pFrame->BAStartingSeq.field. | ||
1301 | StartSeq); | ||
1302 | pBAEntry->LastIndSeq = | ||
1303 | (pFrame->BAStartingSeq.field.StartSeq == | ||
1304 | 0) ? MAXSEQ : (pFrame->BAStartingSeq.field.StartSeq - 1); | ||
1305 | } | ||
1306 | /*ba_refresh_reordering_mpdus(pAd, pBAEntry); */ | ||
1307 | return TRUE; | ||
1308 | } | ||
1309 | |||
1310 | /* | ||
1311 | Description : Send PSMP Action frame If PSMP mode switches. | ||
1312 | */ | ||
1313 | void SendPSMPAction(struct rt_rtmp_adapter *pAd, u8 Wcid, u8 Psmp) | ||
1314 | { | ||
1315 | u8 *pOutBuffer = NULL; | ||
1316 | int NStatus; | ||
1317 | /*unsigned long Idx; */ | ||
1318 | struct rt_frame_psmp_action Frame; | ||
1319 | unsigned long FrameLen; | ||
1320 | |||
1321 | NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ | ||
1322 | if (NStatus != NDIS_STATUS_SUCCESS) { | ||
1323 | DBGPRINT(RT_DEBUG_ERROR, | ||
1324 | ("BA - MlmeADDBAAction() allocate memory failed \n")); | ||
1325 | return; | ||
1326 | } | ||
1327 | |||
1328 | ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, | ||
1329 | pAd->CurrentAddress, pAd->MacTab.Content[Wcid].Addr); | ||
1330 | |||
1331 | Frame.Category = CATEGORY_HT; | ||
1332 | Frame.Action = SMPS_ACTION; | ||
1333 | switch (Psmp) { | ||
1334 | case MMPS_ENABLE: | ||
1335 | #ifdef RT30xx | ||
1336 | if (IS_RT30xx(pAd) | ||
1337 | && (pAd->Antenna.field.RxPath > 1 | ||
1338 | || pAd->Antenna.field.TxPath > 1)) { | ||
1339 | RTMP_ASIC_MMPS_DISABLE(pAd); | ||
1340 | } | ||
1341 | #endif /* RT30xx // */ | ||
1342 | Frame.Psmp = 0; | ||
1343 | break; | ||
1344 | case MMPS_DYNAMIC: | ||
1345 | Frame.Psmp = 3; | ||
1346 | break; | ||
1347 | case MMPS_STATIC: | ||
1348 | #ifdef RT30xx | ||
1349 | if (IS_RT30xx(pAd) | ||
1350 | && (pAd->Antenna.field.RxPath > 1 | ||
1351 | || pAd->Antenna.field.TxPath > 1)) { | ||
1352 | RTMP_ASIC_MMPS_ENABLE(pAd); | ||
1353 | } | ||
1354 | #endif /* RT30xx // */ | ||
1355 | Frame.Psmp = 1; | ||
1356 | break; | ||
1357 | } | ||
1358 | MakeOutgoingFrame(pOutBuffer, &FrameLen, | ||
1359 | sizeof(struct rt_frame_psmp_action), &Frame, END_OF_ARGS); | ||
1360 | MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); | ||
1361 | MlmeFreeMemory(pAd, pOutBuffer); | ||
1362 | DBGPRINT(RT_DEBUG_ERROR, ("HT - SendPSMPAction( %d ) \n", Frame.Psmp)); | ||
1363 | } | ||
1364 | |||
1365 | #define RADIO_MEASUREMENT_REQUEST_ACTION 0 | ||
1366 | |||
1367 | struct PACKED rt_beacon_request { | ||
1368 | u8 RegulatoryClass; | ||
1369 | u8 ChannelNumber; | ||
1370 | u16 RandomInterval; | ||
1371 | u16 MeasurementDuration; | ||
1372 | u8 MeasurementMode; | ||
1373 | u8 BSSID[MAC_ADDR_LEN]; | ||
1374 | u8 ReportingCondition; | ||
1375 | u8 Threshold; | ||
1376 | u8 SSIDIE[2]; /* 2 byte */ | ||
1377 | }; | ||
1378 | |||
1379 | struct PACKED rt_measurement_req { | ||
1380 | u8 ID; | ||
1381 | u8 Length; | ||
1382 | u8 Token; | ||
1383 | u8 RequestMode; | ||
1384 | u8 Type; | ||
1385 | }; | ||
1386 | |||
1387 | void convert_reordering_packet_to_preAMSDU_or_802_3_packet(struct rt_rtmp_adapter *pAd, | ||
1388 | struct rt_rx_blk *pRxBlk, | ||
1389 | u8 | ||
1390 | FromWhichBSSID) | ||
1391 | { | ||
1392 | void *pRxPkt; | ||
1393 | u8 Header802_3[LENGTH_802_3]; | ||
1394 | |||
1395 | /* 1. get 802.3 Header */ | ||
1396 | /* 2. remove LLC */ | ||
1397 | /* a. pointer pRxBlk->pData to payload */ | ||
1398 | /* b. modify pRxBlk->DataSize */ | ||
1399 | |||
1400 | RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); | ||
1401 | |||
1402 | ASSERT(pRxBlk->pRxPacket); | ||
1403 | pRxPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); | ||
1404 | |||
1405 | SET_OS_PKT_NETDEV(pRxPkt, get_netdev_from_bssid(pAd, FromWhichBSSID)); | ||
1406 | SET_OS_PKT_DATAPTR(pRxPkt, pRxBlk->pData); | ||
1407 | SET_OS_PKT_LEN(pRxPkt, pRxBlk->DataSize); | ||
1408 | SET_OS_PKT_DATATAIL(pRxPkt, pRxBlk->pData, pRxBlk->DataSize); | ||
1409 | |||
1410 | /* */ | ||
1411 | /* copy 802.3 header, if necessary */ | ||
1412 | /* */ | ||
1413 | if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) { | ||
1414 | { | ||
1415 | #ifdef LINUX | ||
1416 | NdisMoveMemory(skb_push(pRxPkt, LENGTH_802_3), | ||
1417 | Header802_3, LENGTH_802_3); | ||
1418 | #endif | ||
1419 | } | ||
1420 | } | ||
1421 | } | ||
1422 | |||
1423 | #define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _fromWhichBSSID) \ | ||
1424 | do \ | ||
1425 | { \ | ||
1426 | if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU)) \ | ||
1427 | { \ | ||
1428 | Indicate_AMSDU_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \ | ||
1429 | } \ | ||
1430 | else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_EAP)) \ | ||
1431 | { \ | ||
1432 | Indicate_EAPOL_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \ | ||
1433 | } \ | ||
1434 | else \ | ||
1435 | { \ | ||
1436 | Indicate_Legacy_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \ | ||
1437 | } \ | ||
1438 | } while (0); | ||
1439 | |||
1440 | static void ba_enqueue_reordering_packet(struct rt_rtmp_adapter *pAd, | ||
1441 | struct rt_ba_rec_entry *pBAEntry, | ||
1442 | struct rt_rx_blk *pRxBlk, | ||
1443 | u8 FromWhichBSSID) | ||
1444 | { | ||
1445 | struct reordering_mpdu *mpdu_blk; | ||
1446 | u16 Sequence = (u16)pRxBlk->pHeader->Sequence; | ||
1447 | |||
1448 | mpdu_blk = ba_mpdu_blk_alloc(pAd); | ||
1449 | if ((mpdu_blk != NULL) && (!RX_BLK_TEST_FLAG(pRxBlk, fRX_EAP))) { | ||
1450 | /* Write RxD buffer address & allocated buffer length */ | ||
1451 | NdisAcquireSpinLock(&pBAEntry->RxReRingLock); | ||
1452 | |||
1453 | mpdu_blk->Sequence = Sequence; | ||
1454 | |||
1455 | mpdu_blk->bAMSDU = RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU); | ||
1456 | |||
1457 | convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd, | ||
1458 | pRxBlk, | ||
1459 | FromWhichBSSID); | ||
1460 | |||
1461 | STATS_INC_RX_PACKETS(pAd, FromWhichBSSID); | ||
1462 | |||
1463 | /* */ | ||
1464 | /* it is necessary for reordering packet to record */ | ||
1465 | /* which BSS it come from */ | ||
1466 | /* */ | ||
1467 | RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID); | ||
1468 | |||
1469 | mpdu_blk->pPacket = pRxBlk->pRxPacket; | ||
1470 | |||
1471 | if (ba_reordering_mpdu_insertsorted(&pBAEntry->list, mpdu_blk) | ||
1472 | == FALSE) { | ||
1473 | /* had been already within reordering list */ | ||
1474 | /* don't indicate */ | ||
1475 | RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, | ||
1476 | NDIS_STATUS_SUCCESS); | ||
1477 | ba_mpdu_blk_free(pAd, mpdu_blk); | ||
1478 | } | ||
1479 | |||
1480 | ASSERT((0 <= pBAEntry->list.qlen) | ||
1481 | && (pBAEntry->list.qlen <= pBAEntry->BAWinSize)); | ||
1482 | NdisReleaseSpinLock(&pBAEntry->RxReRingLock); | ||
1483 | } else { | ||
1484 | DBGPRINT(RT_DEBUG_ERROR, | ||
1485 | (" (%d) Can't allocate reordering mpdu blk\n", | ||
1486 | pBAEntry->list.qlen)); | ||
1487 | |||
1488 | /* | ||
1489 | * flush all pending reordering mpdus | ||
1490 | * and receiving mpdu to upper layer | ||
1491 | * make tcp/ip to take care reordering mechanism | ||
1492 | */ | ||
1493 | /*ba_refresh_reordering_mpdus(pAd, pBAEntry); */ | ||
1494 | ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence); | ||
1495 | |||
1496 | pBAEntry->LastIndSeq = Sequence; | ||
1497 | INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); | ||
1498 | } | ||
1499 | } | ||
1500 | |||
1501 | /* | ||
1502 | ========================================================================== | ||
1503 | Description: | ||
1504 | Indicate this packet to upper layer or put it into reordering buffer | ||
1505 | |||
1506 | Parametrs: | ||
1507 | pRxBlk : carry necessary packet info 802.11 format | ||
1508 | FromWhichBSSID : the packet received from which BSS | ||
1509 | |||
1510 | Return : | ||
1511 | none | ||
1512 | |||
1513 | Note : | ||
1514 | the packet queued into reordering buffer need to cover to 802.3 format | ||
1515 | or pre_AMSDU format | ||
1516 | ========================================================================== | ||
1517 | */ | ||
1518 | |||
1519 | void Indicate_AMPDU_Packet(struct rt_rtmp_adapter *pAd, | ||
1520 | struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID) | ||
1521 | { | ||
1522 | u16 Idx; | ||
1523 | struct rt_ba_rec_entry *pBAEntry = NULL; | ||
1524 | u16 Sequence = pRxBlk->pHeader->Sequence; | ||
1525 | unsigned long Now32; | ||
1526 | u8 Wcid = pRxBlk->pRxWI->WirelessCliID; | ||
1527 | u8 TID = pRxBlk->pRxWI->TID; | ||
1528 | |||
1529 | if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU) | ||
1530 | && (pRxBlk->DataSize > MAX_RX_PKT_LEN)) { | ||
1531 | /* release packet */ | ||
1532 | RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, | ||
1533 | NDIS_STATUS_FAILURE); | ||
1534 | return; | ||
1535 | } | ||
1536 | |||
1537 | if (Wcid < MAX_LEN_OF_MAC_TABLE) { | ||
1538 | Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; | ||
1539 | if (Idx == 0) { | ||
1540 | /* Rec BA Session had been torn down */ | ||
1541 | INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); | ||
1542 | return; | ||
1543 | } | ||
1544 | pBAEntry = &pAd->BATable.BARecEntry[Idx]; | ||
1545 | } else { | ||
1546 | /* impossible ! */ | ||
1547 | ASSERT(0); | ||
1548 | /* release packet */ | ||
1549 | RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, | ||
1550 | NDIS_STATUS_FAILURE); | ||
1551 | return; | ||
1552 | } | ||
1553 | |||
1554 | ASSERT(pBAEntry); | ||
1555 | |||
1556 | /* update last rx time */ | ||
1557 | NdisGetSystemUpTime(&Now32); | ||
1558 | |||
1559 | pBAEntry->rcvSeq = Sequence; | ||
1560 | |||
1561 | ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32); | ||
1562 | pBAEntry->LastIndSeqAtTimer = Now32; | ||
1563 | |||
1564 | /* */ | ||
1565 | /* Reset Last Indicate Sequence */ | ||
1566 | /* */ | ||
1567 | if (pBAEntry->LastIndSeq == RESET_RCV_SEQ) { | ||
1568 | ASSERT((pBAEntry->list.qlen == 0) | ||
1569 | && (pBAEntry->list.next == NULL)); | ||
1570 | |||
1571 | /* reset rcv sequence of BA session */ | ||
1572 | pBAEntry->LastIndSeq = Sequence; | ||
1573 | pBAEntry->LastIndSeqAtTimer = Now32; | ||
1574 | INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); | ||
1575 | return; | ||
1576 | } | ||
1577 | |||
1578 | /* */ | ||
1579 | /* I. Check if in order. */ | ||
1580 | /* */ | ||
1581 | if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) { | ||
1582 | u16 LastIndSeq; | ||
1583 | |||
1584 | pBAEntry->LastIndSeq = Sequence; | ||
1585 | INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); | ||
1586 | LastIndSeq = | ||
1587 | ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, | ||
1588 | pBAEntry->LastIndSeq); | ||
1589 | if (LastIndSeq != RESET_RCV_SEQ) { | ||
1590 | pBAEntry->LastIndSeq = LastIndSeq; | ||
1591 | } | ||
1592 | pBAEntry->LastIndSeqAtTimer = Now32; | ||
1593 | } | ||
1594 | /* */ | ||
1595 | /* II. Drop Duplicated Packet */ | ||
1596 | /* */ | ||
1597 | else if (Sequence == pBAEntry->LastIndSeq) { | ||
1598 | |||
1599 | /* drop and release packet */ | ||
1600 | pBAEntry->nDropPacket++; | ||
1601 | RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, | ||
1602 | NDIS_STATUS_FAILURE); | ||
1603 | } | ||
1604 | /* */ | ||
1605 | /* III. Drop Old Received Packet */ | ||
1606 | /* */ | ||
1607 | else if (SEQ_SMALLER(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) { | ||
1608 | |||
1609 | /* drop and release packet */ | ||
1610 | pBAEntry->nDropPacket++; | ||
1611 | RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, | ||
1612 | NDIS_STATUS_FAILURE); | ||
1613 | } | ||
1614 | /* */ | ||
1615 | /* IV. Receive Sequence within Window Size */ | ||
1616 | /* */ | ||
1617 | else if (SEQ_SMALLER | ||
1618 | (Sequence, | ||
1619 | (((pBAEntry->LastIndSeq + pBAEntry->BAWinSize + 1)) & MAXSEQ), | ||
1620 | MAXSEQ)) { | ||
1621 | ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, | ||
1622 | FromWhichBSSID); | ||
1623 | } | ||
1624 | /* */ | ||
1625 | /* V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer */ | ||
1626 | /* */ | ||
1627 | else { | ||
1628 | long WinStartSeq, TmpSeq; | ||
1629 | |||
1630 | TmpSeq = Sequence - (pBAEntry->BAWinSize) - 1; | ||
1631 | if (TmpSeq < 0) { | ||
1632 | TmpSeq = (MAXSEQ + 1) + TmpSeq; | ||
1633 | } | ||
1634 | WinStartSeq = (TmpSeq + 1) & MAXSEQ; | ||
1635 | ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, WinStartSeq); | ||
1636 | pBAEntry->LastIndSeq = WinStartSeq; /*TmpSeq; */ | ||
1637 | |||
1638 | pBAEntry->LastIndSeqAtTimer = Now32; | ||
1639 | |||
1640 | ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, | ||
1641 | FromWhichBSSID); | ||
1642 | |||
1643 | TmpSeq = | ||
1644 | ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, | ||
1645 | pBAEntry->LastIndSeq); | ||
1646 | if (TmpSeq != RESET_RCV_SEQ) { | ||
1647 | pBAEntry->LastIndSeq = TmpSeq; | ||
1648 | } | ||
1649 | } | ||
1650 | } | ||
diff --git a/drivers/staging/rt2860/common/cmm_aes.c b/drivers/staging/rt2860/common/cmm_aes.c deleted file mode 100644 index d70d229a6e5..00000000000 --- a/drivers/staging/rt2860/common/cmm_aes.c +++ /dev/null | |||
@@ -1,1311 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | |||
27 | Module Name: | ||
28 | cmm_aes.c | ||
29 | |||
30 | Abstract: | ||
31 | |||
32 | Revision History: | ||
33 | Who When What | ||
34 | -------- ---------- ---------------------------------------------- | ||
35 | Paul Wu 02-25-02 Initial | ||
36 | */ | ||
37 | |||
38 | #include "../rt_config.h" | ||
39 | |||
40 | struct aes_context { | ||
41 | u32 erk[64]; /* encryption round keys */ | ||
42 | u32 drk[64]; /* decryption round keys */ | ||
43 | int nr; /* number of rounds */ | ||
44 | }; | ||
45 | |||
46 | /*****************************/ | ||
47 | /******** SBOX Table *********/ | ||
48 | /*****************************/ | ||
49 | |||
50 | u8 SboxTable[256] = { | ||
51 | 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, | ||
52 | 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, | ||
53 | 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, | ||
54 | 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, | ||
55 | 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, | ||
56 | 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, | ||
57 | 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, | ||
58 | 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, | ||
59 | 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, | ||
60 | 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, | ||
61 | 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, | ||
62 | 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, | ||
63 | 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, | ||
64 | 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, | ||
65 | 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, | ||
66 | 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, | ||
67 | 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, | ||
68 | 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, | ||
69 | 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, | ||
70 | 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, | ||
71 | 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, | ||
72 | 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, | ||
73 | 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, | ||
74 | 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, | ||
75 | 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, | ||
76 | 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, | ||
77 | 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, | ||
78 | 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, | ||
79 | 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, | ||
80 | 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, | ||
81 | 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, | ||
82 | 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 | ||
83 | }; | ||
84 | |||
85 | void xor_32(u8 *a, u8 *b, u8 *out) | ||
86 | { | ||
87 | int i; | ||
88 | |||
89 | for (i = 0; i < 4; i++) { | ||
90 | out[i] = a[i] ^ b[i]; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | void xor_128(u8 *a, u8 *b, u8 *out) | ||
95 | { | ||
96 | int i; | ||
97 | |||
98 | for (i = 0; i < 16; i++) { | ||
99 | out[i] = a[i] ^ b[i]; | ||
100 | } | ||
101 | } | ||
102 | |||
103 | u8 RTMPCkipSbox(u8 a) | ||
104 | { | ||
105 | return SboxTable[(int)a]; | ||
106 | } | ||
107 | |||
108 | void next_key(u8 *key, int round) | ||
109 | { | ||
110 | u8 rcon; | ||
111 | u8 sbox_key[4]; | ||
112 | u8 rcon_table[12] = { | ||
113 | 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, | ||
114 | 0x1b, 0x36, 0x36, 0x36 | ||
115 | }; | ||
116 | |||
117 | sbox_key[0] = RTMPCkipSbox(key[13]); | ||
118 | sbox_key[1] = RTMPCkipSbox(key[14]); | ||
119 | sbox_key[2] = RTMPCkipSbox(key[15]); | ||
120 | sbox_key[3] = RTMPCkipSbox(key[12]); | ||
121 | |||
122 | rcon = rcon_table[round]; | ||
123 | |||
124 | xor_32(&key[0], sbox_key, &key[0]); | ||
125 | key[0] = key[0] ^ rcon; | ||
126 | |||
127 | xor_32(&key[4], &key[0], &key[4]); | ||
128 | xor_32(&key[8], &key[4], &key[8]); | ||
129 | xor_32(&key[12], &key[8], &key[12]); | ||
130 | } | ||
131 | |||
132 | void byte_sub(u8 *in, u8 *out) | ||
133 | { | ||
134 | int i; | ||
135 | |||
136 | for (i = 0; i < 16; i++) { | ||
137 | out[i] = RTMPCkipSbox(in[i]); | ||
138 | } | ||
139 | } | ||
140 | |||
141 | /************************************/ | ||
142 | /* bitwise_xor() */ | ||
143 | /* A 128 bit, bitwise exclusive or */ | ||
144 | /************************************/ | ||
145 | |||
146 | void bitwise_xor(unsigned char *ina, unsigned char *inb, unsigned char *out) | ||
147 | { | ||
148 | int i; | ||
149 | for (i = 0; i < 16; i++) { | ||
150 | out[i] = ina[i] ^ inb[i]; | ||
151 | } | ||
152 | } | ||
153 | |||
154 | void shift_row(u8 *in, u8 *out) | ||
155 | { | ||
156 | out[0] = in[0]; | ||
157 | out[1] = in[5]; | ||
158 | out[2] = in[10]; | ||
159 | out[3] = in[15]; | ||
160 | out[4] = in[4]; | ||
161 | out[5] = in[9]; | ||
162 | out[6] = in[14]; | ||
163 | out[7] = in[3]; | ||
164 | out[8] = in[8]; | ||
165 | out[9] = in[13]; | ||
166 | out[10] = in[2]; | ||
167 | out[11] = in[7]; | ||
168 | out[12] = in[12]; | ||
169 | out[13] = in[1]; | ||
170 | out[14] = in[6]; | ||
171 | out[15] = in[11]; | ||
172 | } | ||
173 | |||
174 | void mix_column(u8 *in, u8 *out) | ||
175 | { | ||
176 | int i; | ||
177 | u8 add1b[4]; | ||
178 | u8 add1bf7[4]; | ||
179 | u8 rotl[4]; | ||
180 | u8 swap_halfs[4]; | ||
181 | u8 andf7[4]; | ||
182 | u8 rotr[4]; | ||
183 | u8 temp[4]; | ||
184 | u8 tempb[4]; | ||
185 | |||
186 | for (i = 0; i < 4; i++) { | ||
187 | if ((in[i] & 0x80) == 0x80) | ||
188 | add1b[i] = 0x1b; | ||
189 | else | ||
190 | add1b[i] = 0x00; | ||
191 | } | ||
192 | |||
193 | swap_halfs[0] = in[2]; /* Swap halfs */ | ||
194 | swap_halfs[1] = in[3]; | ||
195 | swap_halfs[2] = in[0]; | ||
196 | swap_halfs[3] = in[1]; | ||
197 | |||
198 | rotl[0] = in[3]; /* Rotate left 8 bits */ | ||
199 | rotl[1] = in[0]; | ||
200 | rotl[2] = in[1]; | ||
201 | rotl[3] = in[2]; | ||
202 | |||
203 | andf7[0] = in[0] & 0x7f; | ||
204 | andf7[1] = in[1] & 0x7f; | ||
205 | andf7[2] = in[2] & 0x7f; | ||
206 | andf7[3] = in[3] & 0x7f; | ||
207 | |||
208 | for (i = 3; i > 0; i--) { /* logical shift left 1 bit */ | ||
209 | andf7[i] = andf7[i] << 1; | ||
210 | if ((andf7[i - 1] & 0x80) == 0x80) { | ||
211 | andf7[i] = (andf7[i] | 0x01); | ||
212 | } | ||
213 | } | ||
214 | andf7[0] = andf7[0] << 1; | ||
215 | andf7[0] = andf7[0] & 0xfe; | ||
216 | |||
217 | xor_32(add1b, andf7, add1bf7); | ||
218 | |||
219 | xor_32(in, add1bf7, rotr); | ||
220 | |||
221 | temp[0] = rotr[0]; /* Rotate right 8 bits */ | ||
222 | rotr[0] = rotr[1]; | ||
223 | rotr[1] = rotr[2]; | ||
224 | rotr[2] = rotr[3]; | ||
225 | rotr[3] = temp[0]; | ||
226 | |||
227 | xor_32(add1bf7, rotr, temp); | ||
228 | xor_32(swap_halfs, rotl, tempb); | ||
229 | xor_32(temp, tempb, out); | ||
230 | } | ||
231 | |||
232 | /************************************************/ | ||
233 | /* construct_mic_header1() */ | ||
234 | /* Builds the first MIC header block from */ | ||
235 | /* header fields. */ | ||
236 | /************************************************/ | ||
237 | |||
238 | void construct_mic_header1(unsigned char *mic_header1, | ||
239 | int header_length, unsigned char *mpdu) | ||
240 | { | ||
241 | mic_header1[0] = (unsigned char)((header_length - 2) / 256); | ||
242 | mic_header1[1] = (unsigned char)((header_length - 2) % 256); | ||
243 | mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */ | ||
244 | mic_header1[3] = mpdu[1] & 0xc7; /* Mute retry, more data and pwr mgt bits */ | ||
245 | mic_header1[4] = mpdu[4]; /* A1 */ | ||
246 | mic_header1[5] = mpdu[5]; | ||
247 | mic_header1[6] = mpdu[6]; | ||
248 | mic_header1[7] = mpdu[7]; | ||
249 | mic_header1[8] = mpdu[8]; | ||
250 | mic_header1[9] = mpdu[9]; | ||
251 | mic_header1[10] = mpdu[10]; /* A2 */ | ||
252 | mic_header1[11] = mpdu[11]; | ||
253 | mic_header1[12] = mpdu[12]; | ||
254 | mic_header1[13] = mpdu[13]; | ||
255 | mic_header1[14] = mpdu[14]; | ||
256 | mic_header1[15] = mpdu[15]; | ||
257 | } | ||
258 | |||
259 | /************************************************/ | ||
260 | /* construct_mic_header2() */ | ||
261 | /* Builds the last MIC header block from */ | ||
262 | /* header fields. */ | ||
263 | /************************************************/ | ||
264 | |||
265 | void construct_mic_header2(unsigned char *mic_header2, | ||
266 | unsigned char *mpdu, int a4_exists, int qc_exists) | ||
267 | { | ||
268 | int i; | ||
269 | |||
270 | for (i = 0; i < 16; i++) | ||
271 | mic_header2[i] = 0x00; | ||
272 | |||
273 | mic_header2[0] = mpdu[16]; /* A3 */ | ||
274 | mic_header2[1] = mpdu[17]; | ||
275 | mic_header2[2] = mpdu[18]; | ||
276 | mic_header2[3] = mpdu[19]; | ||
277 | mic_header2[4] = mpdu[20]; | ||
278 | mic_header2[5] = mpdu[21]; | ||
279 | |||
280 | /* In Sequence Control field, mute sequence numer bits (12-bit) */ | ||
281 | mic_header2[6] = mpdu[22] & 0x0f; /* SC */ | ||
282 | mic_header2[7] = 0x00; /* mpdu[23]; */ | ||
283 | |||
284 | if ((!qc_exists) && a4_exists) { | ||
285 | for (i = 0; i < 6; i++) | ||
286 | mic_header2[8 + i] = mpdu[24 + i]; /* A4 */ | ||
287 | |||
288 | } | ||
289 | |||
290 | if (qc_exists && (!a4_exists)) { | ||
291 | mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */ | ||
292 | mic_header2[9] = mpdu[25] & 0x00; | ||
293 | } | ||
294 | |||
295 | if (qc_exists && a4_exists) { | ||
296 | for (i = 0; i < 6; i++) | ||
297 | mic_header2[8 + i] = mpdu[24 + i]; /* A4 */ | ||
298 | |||
299 | mic_header2[14] = mpdu[30] & 0x0f; | ||
300 | mic_header2[15] = mpdu[31] & 0x00; | ||
301 | } | ||
302 | } | ||
303 | |||
304 | /************************************************/ | ||
305 | /* construct_mic_iv() */ | ||
306 | /* Builds the MIC IV from header fields and PN */ | ||
307 | /************************************************/ | ||
308 | |||
309 | void construct_mic_iv(unsigned char *mic_iv, | ||
310 | int qc_exists, | ||
311 | int a4_exists, | ||
312 | unsigned char *mpdu, | ||
313 | unsigned int payload_length, unsigned char *pn_vector) | ||
314 | { | ||
315 | int i; | ||
316 | |||
317 | mic_iv[0] = 0x59; | ||
318 | if (qc_exists && a4_exists) | ||
319 | mic_iv[1] = mpdu[30] & 0x0f; /* QoS_TC */ | ||
320 | if (qc_exists && !a4_exists) | ||
321 | mic_iv[1] = mpdu[24] & 0x0f; /* mute bits 7-4 */ | ||
322 | if (!qc_exists) | ||
323 | mic_iv[1] = 0x00; | ||
324 | for (i = 2; i < 8; i++) | ||
325 | mic_iv[i] = mpdu[i + 8]; /* mic_iv[2:7] = A2[0:5] = mpdu[10:15] */ | ||
326 | #ifdef CONSISTENT_PN_ORDER | ||
327 | for (i = 8; i < 14; i++) | ||
328 | mic_iv[i] = pn_vector[i - 8]; /* mic_iv[8:13] = PN[0:5] */ | ||
329 | #else | ||
330 | for (i = 8; i < 14; i++) | ||
331 | mic_iv[i] = pn_vector[13 - i]; /* mic_iv[8:13] = PN[5:0] */ | ||
332 | #endif | ||
333 | mic_iv[14] = (unsigned char)(payload_length / 256); | ||
334 | mic_iv[15] = (unsigned char)(payload_length % 256); | ||
335 | |||
336 | } | ||
337 | |||
338 | /****************************************/ | ||
339 | /* aes128k128d() */ | ||
340 | /* Performs a 128 bit AES encrypt with */ | ||
341 | /* 128 bit data. */ | ||
342 | /****************************************/ | ||
343 | void aes128k128d(unsigned char *key, unsigned char *data, | ||
344 | unsigned char *ciphertext) | ||
345 | { | ||
346 | int round; | ||
347 | int i; | ||
348 | unsigned char intermediatea[16]; | ||
349 | unsigned char intermediateb[16]; | ||
350 | unsigned char round_key[16]; | ||
351 | |||
352 | for (i = 0; i < 16; i++) | ||
353 | round_key[i] = key[i]; | ||
354 | |||
355 | for (round = 0; round < 11; round++) { | ||
356 | if (round == 0) { | ||
357 | xor_128(round_key, data, ciphertext); | ||
358 | next_key(round_key, round); | ||
359 | } else if (round == 10) { | ||
360 | byte_sub(ciphertext, intermediatea); | ||
361 | shift_row(intermediatea, intermediateb); | ||
362 | xor_128(intermediateb, round_key, ciphertext); | ||
363 | } else { /* 1 - 9 */ | ||
364 | |||
365 | byte_sub(ciphertext, intermediatea); | ||
366 | shift_row(intermediatea, intermediateb); | ||
367 | mix_column(&intermediateb[0], &intermediatea[0]); | ||
368 | mix_column(&intermediateb[4], &intermediatea[4]); | ||
369 | mix_column(&intermediateb[8], &intermediatea[8]); | ||
370 | mix_column(&intermediateb[12], &intermediatea[12]); | ||
371 | xor_128(intermediatea, round_key, ciphertext); | ||
372 | next_key(round_key, round); | ||
373 | } | ||
374 | } | ||
375 | |||
376 | } | ||
377 | |||
378 | void construct_ctr_preload(unsigned char *ctr_preload, | ||
379 | int a4_exists, | ||
380 | int qc_exists, | ||
381 | unsigned char *mpdu, unsigned char *pn_vector, int c) | ||
382 | { | ||
383 | |||
384 | int i = 0; | ||
385 | for (i = 0; i < 16; i++) | ||
386 | ctr_preload[i] = 0x00; | ||
387 | i = 0; | ||
388 | |||
389 | ctr_preload[0] = 0x01; /* flag */ | ||
390 | if (qc_exists && a4_exists) | ||
391 | ctr_preload[1] = mpdu[30] & 0x0f; /* QoC_Control */ | ||
392 | if (qc_exists && !a4_exists) | ||
393 | ctr_preload[1] = mpdu[24] & 0x0f; | ||
394 | |||
395 | for (i = 2; i < 8; i++) | ||
396 | ctr_preload[i] = mpdu[i + 8]; /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */ | ||
397 | #ifdef CONSISTENT_PN_ORDER | ||
398 | for (i = 8; i < 14; i++) | ||
399 | ctr_preload[i] = pn_vector[i - 8]; /* ctr_preload[8:13] = PN[0:5] */ | ||
400 | #else | ||
401 | for (i = 8; i < 14; i++) | ||
402 | ctr_preload[i] = pn_vector[13 - i]; /* ctr_preload[8:13] = PN[5:0] */ | ||
403 | #endif | ||
404 | ctr_preload[14] = (unsigned char)(c / 256); /* Ctr */ | ||
405 | ctr_preload[15] = (unsigned char)(c % 256); | ||
406 | |||
407 | } | ||
408 | |||
409 | BOOLEAN RTMPSoftDecryptAES(struct rt_rtmp_adapter *pAd, | ||
410 | u8 *pData, | ||
411 | unsigned long DataByteCnt, struct rt_cipher_key *pWpaKey) | ||
412 | { | ||
413 | u8 KeyID; | ||
414 | u32 HeaderLen; | ||
415 | u8 PN[6]; | ||
416 | u32 payload_len; | ||
417 | u32 num_blocks; | ||
418 | u32 payload_remainder; | ||
419 | u16 fc; | ||
420 | u8 fc0; | ||
421 | u8 fc1; | ||
422 | u32 frame_type; | ||
423 | u32 frame_subtype; | ||
424 | u32 from_ds; | ||
425 | u32 to_ds; | ||
426 | int a4_exists; | ||
427 | int qc_exists; | ||
428 | u8 aes_out[16]; | ||
429 | int payload_index; | ||
430 | u32 i; | ||
431 | u8 ctr_preload[16]; | ||
432 | u8 chain_buffer[16]; | ||
433 | u8 padded_buffer[16]; | ||
434 | u8 mic_iv[16]; | ||
435 | u8 mic_header1[16]; | ||
436 | u8 mic_header2[16]; | ||
437 | u8 MIC[8]; | ||
438 | u8 TrailMIC[8]; | ||
439 | |||
440 | fc0 = *pData; | ||
441 | fc1 = *(pData + 1); | ||
442 | |||
443 | fc = *((u16 *)pData); | ||
444 | |||
445 | frame_type = ((fc0 >> 2) & 0x03); | ||
446 | frame_subtype = ((fc0 >> 4) & 0x0f); | ||
447 | |||
448 | from_ds = (fc1 & 0x2) >> 1; | ||
449 | to_ds = (fc1 & 0x1); | ||
450 | |||
451 | a4_exists = (from_ds & to_ds); | ||
452 | qc_exists = ((frame_subtype == 0x08) || /* Assumed QoS subtypes */ | ||
453 | (frame_subtype == 0x09) || /* Likely to change. */ | ||
454 | (frame_subtype == 0x0a) || (frame_subtype == 0x0b) | ||
455 | ); | ||
456 | |||
457 | HeaderLen = 24; | ||
458 | if (a4_exists) | ||
459 | HeaderLen += 6; | ||
460 | |||
461 | KeyID = *((u8 *)(pData + HeaderLen + 3)); | ||
462 | KeyID = KeyID >> 6; | ||
463 | |||
464 | if (pWpaKey[KeyID].KeyLen == 0) { | ||
465 | DBGPRINT(RT_DEBUG_TRACE, | ||
466 | ("RTMPSoftDecryptAES failed!(KeyID[%d] Length can not be 0)\n", | ||
467 | KeyID)); | ||
468 | return FALSE; | ||
469 | } | ||
470 | |||
471 | PN[0] = *(pData + HeaderLen); | ||
472 | PN[1] = *(pData + HeaderLen + 1); | ||
473 | PN[2] = *(pData + HeaderLen + 4); | ||
474 | PN[3] = *(pData + HeaderLen + 5); | ||
475 | PN[4] = *(pData + HeaderLen + 6); | ||
476 | PN[5] = *(pData + HeaderLen + 7); | ||
477 | |||
478 | payload_len = DataByteCnt - HeaderLen - 8 - 8; /* 8 bytes for CCMP header , 8 bytes for MIC */ | ||
479 | payload_remainder = (payload_len) % 16; | ||
480 | num_blocks = (payload_len) / 16; | ||
481 | |||
482 | /* Find start of payload */ | ||
483 | payload_index = HeaderLen + 8; /*IV+EIV */ | ||
484 | |||
485 | for (i = 0; i < num_blocks; i++) { | ||
486 | construct_ctr_preload(ctr_preload, | ||
487 | a4_exists, qc_exists, pData, PN, i + 1); | ||
488 | |||
489 | aes128k128d(pWpaKey[KeyID].Key, ctr_preload, aes_out); | ||
490 | |||
491 | bitwise_xor(aes_out, pData + payload_index, chain_buffer); | ||
492 | NdisMoveMemory(pData + payload_index - 8, chain_buffer, 16); | ||
493 | payload_index += 16; | ||
494 | } | ||
495 | |||
496 | /* */ | ||
497 | /* If there is a short final block, then pad it */ | ||
498 | /* encrypt it and copy the unpadded part back */ | ||
499 | /* */ | ||
500 | if (payload_remainder > 0) { | ||
501 | construct_ctr_preload(ctr_preload, | ||
502 | a4_exists, | ||
503 | qc_exists, pData, PN, num_blocks + 1); | ||
504 | |||
505 | NdisZeroMemory(padded_buffer, 16); | ||
506 | NdisMoveMemory(padded_buffer, pData + payload_index, | ||
507 | payload_remainder); | ||
508 | |||
509 | aes128k128d(pWpaKey[KeyID].Key, ctr_preload, aes_out); | ||
510 | |||
511 | bitwise_xor(aes_out, padded_buffer, chain_buffer); | ||
512 | NdisMoveMemory(pData + payload_index - 8, chain_buffer, | ||
513 | payload_remainder); | ||
514 | payload_index += payload_remainder; | ||
515 | } | ||
516 | /* */ | ||
517 | /* Descrypt the MIC */ | ||
518 | /* */ | ||
519 | construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pData, PN, 0); | ||
520 | NdisZeroMemory(padded_buffer, 16); | ||
521 | NdisMoveMemory(padded_buffer, pData + payload_index, 8); | ||
522 | |||
523 | aes128k128d(pWpaKey[KeyID].Key, ctr_preload, aes_out); | ||
524 | |||
525 | bitwise_xor(aes_out, padded_buffer, chain_buffer); | ||
526 | |||
527 | NdisMoveMemory(TrailMIC, chain_buffer, 8); | ||
528 | |||
529 | /* */ | ||
530 | /* Calculate MIC */ | ||
531 | /* */ | ||
532 | |||
533 | /*Force the protected frame bit on */ | ||
534 | *(pData + 1) = *(pData + 1) | 0x40; | ||
535 | |||
536 | /* Find start of payload */ | ||
537 | /* Because the CCMP header has been removed */ | ||
538 | payload_index = HeaderLen; | ||
539 | |||
540 | construct_mic_iv(mic_iv, qc_exists, a4_exists, pData, payload_len, PN); | ||
541 | |||
542 | construct_mic_header1(mic_header1, HeaderLen, pData); | ||
543 | |||
544 | construct_mic_header2(mic_header2, pData, a4_exists, qc_exists); | ||
545 | |||
546 | aes128k128d(pWpaKey[KeyID].Key, mic_iv, aes_out); | ||
547 | bitwise_xor(aes_out, mic_header1, chain_buffer); | ||
548 | aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out); | ||
549 | bitwise_xor(aes_out, mic_header2, chain_buffer); | ||
550 | aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out); | ||
551 | |||
552 | /* iterate through each 16 byte payload block */ | ||
553 | for (i = 0; i < num_blocks; i++) { | ||
554 | bitwise_xor(aes_out, pData + payload_index, chain_buffer); | ||
555 | payload_index += 16; | ||
556 | aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out); | ||
557 | } | ||
558 | |||
559 | /* Add on the final payload block if it needs padding */ | ||
560 | if (payload_remainder > 0) { | ||
561 | NdisZeroMemory(padded_buffer, 16); | ||
562 | NdisMoveMemory(padded_buffer, pData + payload_index, | ||
563 | payload_remainder); | ||
564 | |||
565 | bitwise_xor(aes_out, padded_buffer, chain_buffer); | ||
566 | aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out); | ||
567 | } | ||
568 | /* aes_out contains padded mic, discard most significant */ | ||
569 | /* 8 bytes to generate 64 bit MIC */ | ||
570 | for (i = 0; i < 8; i++) | ||
571 | MIC[i] = aes_out[i]; | ||
572 | |||
573 | if (!NdisEqualMemory(MIC, TrailMIC, 8)) { | ||
574 | DBGPRINT(RT_DEBUG_ERROR, ("RTMPSoftDecryptAES, MIC Error !\n")); /*MIC error. */ | ||
575 | return FALSE; | ||
576 | } | ||
577 | |||
578 | return TRUE; | ||
579 | } | ||
580 | |||
581 | /* ========================= AES En/Decryption ========================== */ | ||
582 | #ifndef uint8 | ||
583 | #define uint8 unsigned char | ||
584 | #endif | ||
585 | |||
586 | #ifndef uint32 | ||
587 | #define uint32 unsigned int | ||
588 | #endif | ||
589 | |||
590 | /* forward S-box */ | ||
591 | static uint32 FSb[256] = { | ||
592 | 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, | ||
593 | 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, | ||
594 | 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, | ||
595 | 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, | ||
596 | 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, | ||
597 | 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, | ||
598 | 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, | ||
599 | 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, | ||
600 | 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, | ||
601 | 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, | ||
602 | 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, | ||
603 | 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, | ||
604 | 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, | ||
605 | 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, | ||
606 | 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, | ||
607 | 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, | ||
608 | 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, | ||
609 | 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, | ||
610 | 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, | ||
611 | 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, | ||
612 | 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, | ||
613 | 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, | ||
614 | 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, | ||
615 | 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, | ||
616 | 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, | ||
617 | 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, | ||
618 | 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, | ||
619 | 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, | ||
620 | 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, | ||
621 | 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, | ||
622 | 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, | ||
623 | 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 | ||
624 | }; | ||
625 | |||
626 | /* forward table */ | ||
627 | #define FT \ | ||
628 | \ | ||
629 | V(C6,63,63,A5), V(F8,7C,7C,84), V(EE,77,77,99), V(F6,7B,7B,8D), \ | ||
630 | V(FF,F2,F2,0D), V(D6,6B,6B,BD), V(DE,6F,6F,B1), V(91,C5,C5,54), \ | ||
631 | V(60,30,30,50), V(02,01,01,03), V(CE,67,67,A9), V(56,2B,2B,7D), \ | ||
632 | V(E7,FE,FE,19), V(B5,D7,D7,62), V(4D,AB,AB,E6), V(EC,76,76,9A), \ | ||
633 | V(8F,CA,CA,45), V(1F,82,82,9D), V(89,C9,C9,40), V(FA,7D,7D,87), \ | ||
634 | V(EF,FA,FA,15), V(B2,59,59,EB), V(8E,47,47,C9), V(FB,F0,F0,0B), \ | ||
635 | V(41,AD,AD,EC), V(B3,D4,D4,67), V(5F,A2,A2,FD), V(45,AF,AF,EA), \ | ||
636 | V(23,9C,9C,BF), V(53,A4,A4,F7), V(E4,72,72,96), V(9B,C0,C0,5B), \ | ||
637 | V(75,B7,B7,C2), V(E1,FD,FD,1C), V(3D,93,93,AE), V(4C,26,26,6A), \ | ||
638 | V(6C,36,36,5A), V(7E,3F,3F,41), V(F5,F7,F7,02), V(83,CC,CC,4F), \ | ||
639 | V(68,34,34,5C), V(51,A5,A5,F4), V(D1,E5,E5,34), V(F9,F1,F1,08), \ | ||
640 | V(E2,71,71,93), V(AB,D8,D8,73), V(62,31,31,53), V(2A,15,15,3F), \ | ||
641 | V(08,04,04,0C), V(95,C7,C7,52), V(46,23,23,65), V(9D,C3,C3,5E), \ | ||
642 | V(30,18,18,28), V(37,96,96,A1), V(0A,05,05,0F), V(2F,9A,9A,B5), \ | ||
643 | V(0E,07,07,09), V(24,12,12,36), V(1B,80,80,9B), V(DF,E2,E2,3D), \ | ||
644 | V(CD,EB,EB,26), V(4E,27,27,69), V(7F,B2,B2,CD), V(EA,75,75,9F), \ | ||
645 | V(12,09,09,1B), V(1D,83,83,9E), V(58,2C,2C,74), V(34,1A,1A,2E), \ | ||
646 | V(36,1B,1B,2D), V(DC,6E,6E,B2), V(B4,5A,5A,EE), V(5B,A0,A0,FB), \ | ||
647 | V(A4,52,52,F6), V(76,3B,3B,4D), V(B7,D6,D6,61), V(7D,B3,B3,CE), \ | ||
648 | V(52,29,29,7B), V(DD,E3,E3,3E), V(5E,2F,2F,71), V(13,84,84,97), \ | ||
649 | V(A6,53,53,F5), V(B9,D1,D1,68), V(00,00,00,00), V(C1,ED,ED,2C), \ | ||
650 | V(40,20,20,60), V(E3,FC,FC,1F), V(79,B1,B1,C8), V(B6,5B,5B,ED), \ | ||
651 | V(D4,6A,6A,BE), V(8D,CB,CB,46), V(67,BE,BE,D9), V(72,39,39,4B), \ | ||
652 | V(94,4A,4A,DE), V(98,4C,4C,D4), V(B0,58,58,E8), V(85,CF,CF,4A), \ | ||
653 | V(BB,D0,D0,6B), V(C5,EF,EF,2A), V(4F,AA,AA,E5), V(ED,FB,FB,16), \ | ||
654 | V(86,43,43,C5), V(9A,4D,4D,D7), V(66,33,33,55), V(11,85,85,94), \ | ||
655 | V(8A,45,45,CF), V(E9,F9,F9,10), V(04,02,02,06), V(FE,7F,7F,81), \ | ||
656 | V(A0,50,50,F0), V(78,3C,3C,44), V(25,9F,9F,BA), V(4B,A8,A8,E3), \ | ||
657 | V(A2,51,51,F3), V(5D,A3,A3,FE), V(80,40,40,C0), V(05,8F,8F,8A), \ | ||
658 | V(3F,92,92,AD), V(21,9D,9D,BC), V(70,38,38,48), V(F1,F5,F5,04), \ | ||
659 | V(63,BC,BC,DF), V(77,B6,B6,C1), V(AF,DA,DA,75), V(42,21,21,63), \ | ||
660 | V(20,10,10,30), V(E5,FF,FF,1A), V(FD,F3,F3,0E), V(BF,D2,D2,6D), \ | ||
661 | V(81,CD,CD,4C), V(18,0C,0C,14), V(26,13,13,35), V(C3,EC,EC,2F), \ | ||
662 | V(BE,5F,5F,E1), V(35,97,97,A2), V(88,44,44,CC), V(2E,17,17,39), \ | ||
663 | V(93,C4,C4,57), V(55,A7,A7,F2), V(FC,7E,7E,82), V(7A,3D,3D,47), \ | ||
664 | V(C8,64,64,AC), V(BA,5D,5D,E7), V(32,19,19,2B), V(E6,73,73,95), \ | ||
665 | V(C0,60,60,A0), V(19,81,81,98), V(9E,4F,4F,D1), V(A3,DC,DC,7F), \ | ||
666 | V(44,22,22,66), V(54,2A,2A,7E), V(3B,90,90,AB), V(0B,88,88,83), \ | ||
667 | V(8C,46,46,CA), V(C7,EE,EE,29), V(6B,B8,B8,D3), V(28,14,14,3C), \ | ||
668 | V(A7,DE,DE,79), V(BC,5E,5E,E2), V(16,0B,0B,1D), V(AD,DB,DB,76), \ | ||
669 | V(DB,E0,E0,3B), V(64,32,32,56), V(74,3A,3A,4E), V(14,0A,0A,1E), \ | ||
670 | V(92,49,49,DB), V(0C,06,06,0A), V(48,24,24,6C), V(B8,5C,5C,E4), \ | ||
671 | V(9F,C2,C2,5D), V(BD,D3,D3,6E), V(43,AC,AC,EF), V(C4,62,62,A6), \ | ||
672 | V(39,91,91,A8), V(31,95,95,A4), V(D3,E4,E4,37), V(F2,79,79,8B), \ | ||
673 | V(D5,E7,E7,32), V(8B,C8,C8,43), V(6E,37,37,59), V(DA,6D,6D,B7), \ | ||
674 | V(01,8D,8D,8C), V(B1,D5,D5,64), V(9C,4E,4E,D2), V(49,A9,A9,E0), \ | ||
675 | V(D8,6C,6C,B4), V(AC,56,56,FA), V(F3,F4,F4,07), V(CF,EA,EA,25), \ | ||
676 | V(CA,65,65,AF), V(F4,7A,7A,8E), V(47,AE,AE,E9), V(10,08,08,18), \ | ||
677 | V(6F,BA,BA,D5), V(F0,78,78,88), V(4A,25,25,6F), V(5C,2E,2E,72), \ | ||
678 | V(38,1C,1C,24), V(57,A6,A6,F1), V(73,B4,B4,C7), V(97,C6,C6,51), \ | ||
679 | V(CB,E8,E8,23), V(A1,DD,DD,7C), V(E8,74,74,9C), V(3E,1F,1F,21), \ | ||
680 | V(96,4B,4B,DD), V(61,BD,BD,DC), V(0D,8B,8B,86), V(0F,8A,8A,85), \ | ||
681 | V(E0,70,70,90), V(7C,3E,3E,42), V(71,B5,B5,C4), V(CC,66,66,AA), \ | ||
682 | V(90,48,48,D8), V(06,03,03,05), V(F7,F6,F6,01), V(1C,0E,0E,12), \ | ||
683 | V(C2,61,61,A3), V(6A,35,35,5F), V(AE,57,57,F9), V(69,B9,B9,D0), \ | ||
684 | V(17,86,86,91), V(99,C1,C1,58), V(3A,1D,1D,27), V(27,9E,9E,B9), \ | ||
685 | V(D9,E1,E1,38), V(EB,F8,F8,13), V(2B,98,98,B3), V(22,11,11,33), \ | ||
686 | V(D2,69,69,BB), V(A9,D9,D9,70), V(07,8E,8E,89), V(33,94,94,A7), \ | ||
687 | V(2D,9B,9B,B6), V(3C,1E,1E,22), V(15,87,87,92), V(C9,E9,E9,20), \ | ||
688 | V(87,CE,CE,49), V(AA,55,55,FF), V(50,28,28,78), V(A5,DF,DF,7A), \ | ||
689 | V(03,8C,8C,8F), V(59,A1,A1,F8), V(09,89,89,80), V(1A,0D,0D,17), \ | ||
690 | V(65,BF,BF,DA), V(D7,E6,E6,31), V(84,42,42,C6), V(D0,68,68,B8), \ | ||
691 | V(82,41,41,C3), V(29,99,99,B0), V(5A,2D,2D,77), V(1E,0F,0F,11), \ | ||
692 | V(7B,B0,B0,CB), V(A8,54,54,FC), V(6D,BB,BB,D6), V(2C,16,16,3A) | ||
693 | |||
694 | #define V(a,b,c,d) 0x##a##b##c##d | ||
695 | static uint32 FT0[256] = { FT }; | ||
696 | |||
697 | #undef V | ||
698 | |||
699 | #define V(a,b,c,d) 0x##d##a##b##c | ||
700 | static uint32 FT1[256] = { FT }; | ||
701 | |||
702 | #undef V | ||
703 | |||
704 | #define V(a,b,c,d) 0x##c##d##a##b | ||
705 | static uint32 FT2[256] = { FT }; | ||
706 | |||
707 | #undef V | ||
708 | |||
709 | #define V(a,b,c,d) 0x##b##c##d##a | ||
710 | static uint32 FT3[256] = { FT }; | ||
711 | |||
712 | #undef V | ||
713 | |||
714 | #undef FT | ||
715 | |||
716 | /* reverse S-box */ | ||
717 | |||
718 | static uint32 RSb[256] = { | ||
719 | 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, | ||
720 | 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, | ||
721 | 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, | ||
722 | 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, | ||
723 | 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, | ||
724 | 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, | ||
725 | 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, | ||
726 | 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, | ||
727 | 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, | ||
728 | 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, | ||
729 | 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, | ||
730 | 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, | ||
731 | 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, | ||
732 | 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, | ||
733 | 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, | ||
734 | 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, | ||
735 | 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, | ||
736 | 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, | ||
737 | 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, | ||
738 | 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, | ||
739 | 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, | ||
740 | 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, | ||
741 | 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, | ||
742 | 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, | ||
743 | 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, | ||
744 | 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, | ||
745 | 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, | ||
746 | 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, | ||
747 | 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, | ||
748 | 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, | ||
749 | 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, | ||
750 | 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D | ||
751 | }; | ||
752 | |||
753 | /* reverse table */ | ||
754 | |||
755 | #define RT \ | ||
756 | \ | ||
757 | V(51,F4,A7,50), V(7E,41,65,53), V(1A,17,A4,C3), V(3A,27,5E,96), \ | ||
758 | V(3B,AB,6B,CB), V(1F,9D,45,F1), V(AC,FA,58,AB), V(4B,E3,03,93), \ | ||
759 | V(20,30,FA,55), V(AD,76,6D,F6), V(88,CC,76,91), V(F5,02,4C,25), \ | ||
760 | V(4F,E5,D7,FC), V(C5,2A,CB,D7), V(26,35,44,80), V(B5,62,A3,8F), \ | ||
761 | V(DE,B1,5A,49), V(25,BA,1B,67), V(45,EA,0E,98), V(5D,FE,C0,E1), \ | ||
762 | V(C3,2F,75,02), V(81,4C,F0,12), V(8D,46,97,A3), V(6B,D3,F9,C6), \ | ||
763 | V(03,8F,5F,E7), V(15,92,9C,95), V(BF,6D,7A,EB), V(95,52,59,DA), \ | ||
764 | V(D4,BE,83,2D), V(58,74,21,D3), V(49,E0,69,29), V(8E,C9,C8,44), \ | ||
765 | V(75,C2,89,6A), V(F4,8E,79,78), V(99,58,3E,6B), V(27,B9,71,DD), \ | ||
766 | V(BE,E1,4F,B6), V(F0,88,AD,17), V(C9,20,AC,66), V(7D,CE,3A,B4), \ | ||
767 | V(63,DF,4A,18), V(E5,1A,31,82), V(97,51,33,60), V(62,53,7F,45), \ | ||
768 | V(B1,64,77,E0), V(BB,6B,AE,84), V(FE,81,A0,1C), V(F9,08,2B,94), \ | ||
769 | V(70,48,68,58), V(8F,45,FD,19), V(94,DE,6C,87), V(52,7B,F8,B7), \ | ||
770 | V(AB,73,D3,23), V(72,4B,02,E2), V(E3,1F,8F,57), V(66,55,AB,2A), \ | ||
771 | V(B2,EB,28,07), V(2F,B5,C2,03), V(86,C5,7B,9A), V(D3,37,08,A5), \ | ||
772 | V(30,28,87,F2), V(23,BF,A5,B2), V(02,03,6A,BA), V(ED,16,82,5C), \ | ||
773 | V(8A,CF,1C,2B), V(A7,79,B4,92), V(F3,07,F2,F0), V(4E,69,E2,A1), \ | ||
774 | V(65,DA,F4,CD), V(06,05,BE,D5), V(D1,34,62,1F), V(C4,A6,FE,8A), \ | ||
775 | V(34,2E,53,9D), V(A2,F3,55,A0), V(05,8A,E1,32), V(A4,F6,EB,75), \ | ||
776 | V(0B,83,EC,39), V(40,60,EF,AA), V(5E,71,9F,06), V(BD,6E,10,51), \ | ||
777 | V(3E,21,8A,F9), V(96,DD,06,3D), V(DD,3E,05,AE), V(4D,E6,BD,46), \ | ||
778 | V(91,54,8D,B5), V(71,C4,5D,05), V(04,06,D4,6F), V(60,50,15,FF), \ | ||
779 | V(19,98,FB,24), V(D6,BD,E9,97), V(89,40,43,CC), V(67,D9,9E,77), \ | ||
780 | V(B0,E8,42,BD), V(07,89,8B,88), V(E7,19,5B,38), V(79,C8,EE,DB), \ | ||
781 | V(A1,7C,0A,47), V(7C,42,0F,E9), V(F8,84,1E,C9), V(00,00,00,00), \ | ||
782 | V(09,80,86,83), V(32,2B,ED,48), V(1E,11,70,AC), V(6C,5A,72,4E), \ | ||
783 | V(FD,0E,FF,FB), V(0F,85,38,56), V(3D,AE,D5,1E), V(36,2D,39,27), \ | ||
784 | V(0A,0F,D9,64), V(68,5C,A6,21), V(9B,5B,54,D1), V(24,36,2E,3A), \ | ||
785 | V(0C,0A,67,B1), V(93,57,E7,0F), V(B4,EE,96,D2), V(1B,9B,91,9E), \ | ||
786 | V(80,C0,C5,4F), V(61,DC,20,A2), V(5A,77,4B,69), V(1C,12,1A,16), \ | ||
787 | V(E2,93,BA,0A), V(C0,A0,2A,E5), V(3C,22,E0,43), V(12,1B,17,1D), \ | ||
788 | V(0E,09,0D,0B), V(F2,8B,C7,AD), V(2D,B6,A8,B9), V(14,1E,A9,C8), \ | ||
789 | V(57,F1,19,85), V(AF,75,07,4C), V(EE,99,DD,BB), V(A3,7F,60,FD), \ | ||
790 | V(F7,01,26,9F), V(5C,72,F5,BC), V(44,66,3B,C5), V(5B,FB,7E,34), \ | ||
791 | V(8B,43,29,76), V(CB,23,C6,DC), V(B6,ED,FC,68), V(B8,E4,F1,63), \ | ||
792 | V(D7,31,DC,CA), V(42,63,85,10), V(13,97,22,40), V(84,C6,11,20), \ | ||
793 | V(85,4A,24,7D), V(D2,BB,3D,F8), V(AE,F9,32,11), V(C7,29,A1,6D), \ | ||
794 | V(1D,9E,2F,4B), V(DC,B2,30,F3), V(0D,86,52,EC), V(77,C1,E3,D0), \ | ||
795 | V(2B,B3,16,6C), V(A9,70,B9,99), V(11,94,48,FA), V(47,E9,64,22), \ | ||
796 | V(A8,FC,8C,C4), V(A0,F0,3F,1A), V(56,7D,2C,D8), V(22,33,90,EF), \ | ||
797 | V(87,49,4E,C7), V(D9,38,D1,C1), V(8C,CA,A2,FE), V(98,D4,0B,36), \ | ||
798 | V(A6,F5,81,CF), V(A5,7A,DE,28), V(DA,B7,8E,26), V(3F,AD,BF,A4), \ | ||
799 | V(2C,3A,9D,E4), V(50,78,92,0D), V(6A,5F,CC,9B), V(54,7E,46,62), \ | ||
800 | V(F6,8D,13,C2), V(90,D8,B8,E8), V(2E,39,F7,5E), V(82,C3,AF,F5), \ | ||
801 | V(9F,5D,80,BE), V(69,D0,93,7C), V(6F,D5,2D,A9), V(CF,25,12,B3), \ | ||
802 | V(C8,AC,99,3B), V(10,18,7D,A7), V(E8,9C,63,6E), V(DB,3B,BB,7B), \ | ||
803 | V(CD,26,78,09), V(6E,59,18,F4), V(EC,9A,B7,01), V(83,4F,9A,A8), \ | ||
804 | V(E6,95,6E,65), V(AA,FF,E6,7E), V(21,BC,CF,08), V(EF,15,E8,E6), \ | ||
805 | V(BA,E7,9B,D9), V(4A,6F,36,CE), V(EA,9F,09,D4), V(29,B0,7C,D6), \ | ||
806 | V(31,A4,B2,AF), V(2A,3F,23,31), V(C6,A5,94,30), V(35,A2,66,C0), \ | ||
807 | V(74,4E,BC,37), V(FC,82,CA,A6), V(E0,90,D0,B0), V(33,A7,D8,15), \ | ||
808 | V(F1,04,98,4A), V(41,EC,DA,F7), V(7F,CD,50,0E), V(17,91,F6,2F), \ | ||
809 | V(76,4D,D6,8D), V(43,EF,B0,4D), V(CC,AA,4D,54), V(E4,96,04,DF), \ | ||
810 | V(9E,D1,B5,E3), V(4C,6A,88,1B), V(C1,2C,1F,B8), V(46,65,51,7F), \ | ||
811 | V(9D,5E,EA,04), V(01,8C,35,5D), V(FA,87,74,73), V(FB,0B,41,2E), \ | ||
812 | V(B3,67,1D,5A), V(92,DB,D2,52), V(E9,10,56,33), V(6D,D6,47,13), \ | ||
813 | V(9A,D7,61,8C), V(37,A1,0C,7A), V(59,F8,14,8E), V(EB,13,3C,89), \ | ||
814 | V(CE,A9,27,EE), V(B7,61,C9,35), V(E1,1C,E5,ED), V(7A,47,B1,3C), \ | ||
815 | V(9C,D2,DF,59), V(55,F2,73,3F), V(18,14,CE,79), V(73,C7,37,BF), \ | ||
816 | V(53,F7,CD,EA), V(5F,FD,AA,5B), V(DF,3D,6F,14), V(78,44,DB,86), \ | ||
817 | V(CA,AF,F3,81), V(B9,68,C4,3E), V(38,24,34,2C), V(C2,A3,40,5F), \ | ||
818 | V(16,1D,C3,72), V(BC,E2,25,0C), V(28,3C,49,8B), V(FF,0D,95,41), \ | ||
819 | V(39,A8,01,71), V(08,0C,B3,DE), V(D8,B4,E4,9C), V(64,56,C1,90), \ | ||
820 | V(7B,CB,84,61), V(D5,32,B6,70), V(48,6C,5C,74), V(D0,B8,57,42) | ||
821 | |||
822 | #define V(a,b,c,d) 0x##a##b##c##d | ||
823 | static uint32 RT0[256] = { RT }; | ||
824 | |||
825 | #undef V | ||
826 | |||
827 | #define V(a,b,c,d) 0x##d##a##b##c | ||
828 | static uint32 RT1[256] = { RT }; | ||
829 | |||
830 | #undef V | ||
831 | |||
832 | #define V(a,b,c,d) 0x##c##d##a##b | ||
833 | static uint32 RT2[256] = { RT }; | ||
834 | |||
835 | #undef V | ||
836 | |||
837 | #define V(a,b,c,d) 0x##b##c##d##a | ||
838 | static uint32 RT3[256] = { RT }; | ||
839 | |||
840 | #undef V | ||
841 | |||
842 | #undef RT | ||
843 | |||
844 | /* round constants */ | ||
845 | |||
846 | static uint32 RCON[10] = { | ||
847 | 0x01000000, 0x02000000, 0x04000000, 0x08000000, | ||
848 | 0x10000000, 0x20000000, 0x40000000, 0x80000000, | ||
849 | 0x1B000000, 0x36000000 | ||
850 | }; | ||
851 | |||
852 | /* key schedule tables */ | ||
853 | |||
854 | static int KT_init = 1; | ||
855 | |||
856 | static uint32 KT0[256]; | ||
857 | static uint32 KT1[256]; | ||
858 | static uint32 KT2[256]; | ||
859 | static uint32 KT3[256]; | ||
860 | |||
861 | /* platform-independent 32-bit integer manipulation macros */ | ||
862 | |||
863 | #define GET_UINT32(n,b,i) \ | ||
864 | { \ | ||
865 | (n) = ( (uint32) (b)[(i) ] << 24 ) \ | ||
866 | | ( (uint32) (b)[(i) + 1] << 16 ) \ | ||
867 | | ( (uint32) (b)[(i) + 2] << 8 ) \ | ||
868 | | ( (uint32) (b)[(i) + 3] ); \ | ||
869 | } | ||
870 | |||
871 | #define PUT_UINT32(n,b,i) \ | ||
872 | { \ | ||
873 | (b)[(i) ] = (uint8) ( (n) >> 24 ); \ | ||
874 | (b)[(i) + 1] = (uint8) ( (n) >> 16 ); \ | ||
875 | (b)[(i) + 2] = (uint8) ( (n) >> 8 ); \ | ||
876 | (b)[(i) + 3] = (uint8) ( (n) ); \ | ||
877 | } | ||
878 | |||
879 | int rt_aes_set_key(struct aes_context * ctx, uint8 * key, int nbits) | ||
880 | { | ||
881 | int i; | ||
882 | uint32 *RK, *SK; | ||
883 | |||
884 | switch (nbits) { | ||
885 | case 128: | ||
886 | ctx->nr = 10; | ||
887 | break; | ||
888 | case 192: | ||
889 | ctx->nr = 12; | ||
890 | break; | ||
891 | case 256: | ||
892 | ctx->nr = 14; | ||
893 | break; | ||
894 | default: | ||
895 | return (1); | ||
896 | } | ||
897 | |||
898 | RK = (uint32 *) ctx->erk; | ||
899 | |||
900 | for (i = 0; i < (nbits >> 5); i++) { | ||
901 | GET_UINT32(RK[i], key, i * 4); | ||
902 | } | ||
903 | |||
904 | /* setup encryption round keys */ | ||
905 | |||
906 | switch (nbits) { | ||
907 | case 128: | ||
908 | |||
909 | for (i = 0; i < 10; i++, RK += 4) { | ||
910 | RK[4] = RK[0] ^ RCON[i] ^ | ||
911 | (FSb[(uint8) (RK[3] >> 16)] << 24) ^ | ||
912 | (FSb[(uint8) (RK[3] >> 8)] << 16) ^ | ||
913 | (FSb[(uint8) (RK[3])] << 8) ^ | ||
914 | (FSb[(uint8) (RK[3] >> 24)]); | ||
915 | |||
916 | RK[5] = RK[1] ^ RK[4]; | ||
917 | RK[6] = RK[2] ^ RK[5]; | ||
918 | RK[7] = RK[3] ^ RK[6]; | ||
919 | } | ||
920 | break; | ||
921 | |||
922 | case 192: | ||
923 | |||
924 | for (i = 0; i < 8; i++, RK += 6) { | ||
925 | RK[6] = RK[0] ^ RCON[i] ^ | ||
926 | (FSb[(uint8) (RK[5] >> 16)] << 24) ^ | ||
927 | (FSb[(uint8) (RK[5] >> 8)] << 16) ^ | ||
928 | (FSb[(uint8) (RK[5])] << 8) ^ | ||
929 | (FSb[(uint8) (RK[5] >> 24)]); | ||
930 | |||
931 | RK[7] = RK[1] ^ RK[6]; | ||
932 | RK[8] = RK[2] ^ RK[7]; | ||
933 | RK[9] = RK[3] ^ RK[8]; | ||
934 | RK[10] = RK[4] ^ RK[9]; | ||
935 | RK[11] = RK[5] ^ RK[10]; | ||
936 | } | ||
937 | break; | ||
938 | |||
939 | case 256: | ||
940 | |||
941 | for (i = 0; i < 7; i++, RK += 8) { | ||
942 | RK[8] = RK[0] ^ RCON[i] ^ | ||
943 | (FSb[(uint8) (RK[7] >> 16)] << 24) ^ | ||
944 | (FSb[(uint8) (RK[7] >> 8)] << 16) ^ | ||
945 | (FSb[(uint8) (RK[7])] << 8) ^ | ||
946 | (FSb[(uint8) (RK[7] >> 24)]); | ||
947 | |||
948 | RK[9] = RK[1] ^ RK[8]; | ||
949 | RK[10] = RK[2] ^ RK[9]; | ||
950 | RK[11] = RK[3] ^ RK[10]; | ||
951 | |||
952 | RK[12] = RK[4] ^ | ||
953 | (FSb[(uint8) (RK[11] >> 24)] << 24) ^ | ||
954 | (FSb[(uint8) (RK[11] >> 16)] << 16) ^ | ||
955 | (FSb[(uint8) (RK[11] >> 8)] << 8) ^ | ||
956 | (FSb[(uint8) (RK[11])]); | ||
957 | |||
958 | RK[13] = RK[5] ^ RK[12]; | ||
959 | RK[14] = RK[6] ^ RK[13]; | ||
960 | RK[15] = RK[7] ^ RK[14]; | ||
961 | } | ||
962 | break; | ||
963 | } | ||
964 | |||
965 | /* setup decryption round keys */ | ||
966 | |||
967 | if (KT_init) { | ||
968 | for (i = 0; i < 256; i++) { | ||
969 | KT0[i] = RT0[FSb[i]]; | ||
970 | KT1[i] = RT1[FSb[i]]; | ||
971 | KT2[i] = RT2[FSb[i]]; | ||
972 | KT3[i] = RT3[FSb[i]]; | ||
973 | } | ||
974 | |||
975 | KT_init = 0; | ||
976 | } | ||
977 | |||
978 | SK = (uint32 *) ctx->drk; | ||
979 | |||
980 | *SK++ = *RK++; | ||
981 | *SK++ = *RK++; | ||
982 | *SK++ = *RK++; | ||
983 | *SK++ = *RK++; | ||
984 | |||
985 | for (i = 1; i < ctx->nr; i++) { | ||
986 | RK -= 8; | ||
987 | |||
988 | *SK++ = KT0[(uint8) (*RK >> 24)] ^ | ||
989 | KT1[(uint8) (*RK >> 16)] ^ | ||
990 | KT2[(uint8) (*RK >> 8)] ^ KT3[(uint8) (*RK)]; | ||
991 | RK++; | ||
992 | |||
993 | *SK++ = KT0[(uint8) (*RK >> 24)] ^ | ||
994 | KT1[(uint8) (*RK >> 16)] ^ | ||
995 | KT2[(uint8) (*RK >> 8)] ^ KT3[(uint8) (*RK)]; | ||
996 | RK++; | ||
997 | |||
998 | *SK++ = KT0[(uint8) (*RK >> 24)] ^ | ||
999 | KT1[(uint8) (*RK >> 16)] ^ | ||
1000 | KT2[(uint8) (*RK >> 8)] ^ KT3[(uint8) (*RK)]; | ||
1001 | RK++; | ||
1002 | |||
1003 | *SK++ = KT0[(uint8) (*RK >> 24)] ^ | ||
1004 | KT1[(uint8) (*RK >> 16)] ^ | ||
1005 | KT2[(uint8) (*RK >> 8)] ^ KT3[(uint8) (*RK)]; | ||
1006 | RK++; | ||
1007 | } | ||
1008 | |||
1009 | RK -= 8; | ||
1010 | |||
1011 | *SK++ = *RK++; | ||
1012 | *SK++ = *RK++; | ||
1013 | *SK++ = *RK++; | ||
1014 | *SK++ = *RK++; | ||
1015 | |||
1016 | return (0); | ||
1017 | } | ||
1018 | |||
1019 | /* AES 128-bit block encryption routine */ | ||
1020 | |||
1021 | void rt_aes_encrypt(struct aes_context * ctx, uint8 input[16], uint8 output[16]) | ||
1022 | { | ||
1023 | uint32 *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; | ||
1024 | |||
1025 | RK = (uint32 *) ctx->erk; | ||
1026 | GET_UINT32(X0, input, 0); | ||
1027 | X0 ^= RK[0]; | ||
1028 | GET_UINT32(X1, input, 4); | ||
1029 | X1 ^= RK[1]; | ||
1030 | GET_UINT32(X2, input, 8); | ||
1031 | X2 ^= RK[2]; | ||
1032 | GET_UINT32(X3, input, 12); | ||
1033 | X3 ^= RK[3]; | ||
1034 | |||
1035 | #define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ | ||
1036 | { \ | ||
1037 | RK += 4; \ | ||
1038 | \ | ||
1039 | X0 = RK[0] ^ FT0[ (uint8) ( Y0 >> 24 ) ] ^ \ | ||
1040 | FT1[ (uint8) ( Y1 >> 16 ) ] ^ \ | ||
1041 | FT2[ (uint8) ( Y2 >> 8 ) ] ^ \ | ||
1042 | FT3[ (uint8) ( Y3 ) ]; \ | ||
1043 | \ | ||
1044 | X1 = RK[1] ^ FT0[ (uint8) ( Y1 >> 24 ) ] ^ \ | ||
1045 | FT1[ (uint8) ( Y2 >> 16 ) ] ^ \ | ||
1046 | FT2[ (uint8) ( Y3 >> 8 ) ] ^ \ | ||
1047 | FT3[ (uint8) ( Y0 ) ]; \ | ||
1048 | \ | ||
1049 | X2 = RK[2] ^ FT0[ (uint8) ( Y2 >> 24 ) ] ^ \ | ||
1050 | FT1[ (uint8) ( Y3 >> 16 ) ] ^ \ | ||
1051 | FT2[ (uint8) ( Y0 >> 8 ) ] ^ \ | ||
1052 | FT3[ (uint8) ( Y1 ) ]; \ | ||
1053 | \ | ||
1054 | X3 = RK[3] ^ FT0[ (uint8) ( Y3 >> 24 ) ] ^ \ | ||
1055 | FT1[ (uint8) ( Y0 >> 16 ) ] ^ \ | ||
1056 | FT2[ (uint8) ( Y1 >> 8 ) ] ^ \ | ||
1057 | FT3[ (uint8) ( Y2 ) ]; \ | ||
1058 | } | ||
1059 | |||
1060 | AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 1 */ | ||
1061 | AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); /* round 2 */ | ||
1062 | AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 3 */ | ||
1063 | AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); /* round 4 */ | ||
1064 | AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 5 */ | ||
1065 | AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); /* round 6 */ | ||
1066 | AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 7 */ | ||
1067 | AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); /* round 8 */ | ||
1068 | AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 9 */ | ||
1069 | |||
1070 | if (ctx->nr > 10) { | ||
1071 | AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); /* round 10 */ | ||
1072 | AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 11 */ | ||
1073 | } | ||
1074 | |||
1075 | if (ctx->nr > 12) { | ||
1076 | AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); /* round 12 */ | ||
1077 | AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 13 */ | ||
1078 | } | ||
1079 | |||
1080 | /* last round */ | ||
1081 | |||
1082 | RK += 4; | ||
1083 | |||
1084 | X0 = RK[0] ^ (FSb[(uint8) (Y0 >> 24)] << 24) ^ | ||
1085 | (FSb[(uint8) (Y1 >> 16)] << 16) ^ | ||
1086 | (FSb[(uint8) (Y2 >> 8)] << 8) ^ (FSb[(uint8) (Y3)]); | ||
1087 | |||
1088 | X1 = RK[1] ^ (FSb[(uint8) (Y1 >> 24)] << 24) ^ | ||
1089 | (FSb[(uint8) (Y2 >> 16)] << 16) ^ | ||
1090 | (FSb[(uint8) (Y3 >> 8)] << 8) ^ (FSb[(uint8) (Y0)]); | ||
1091 | |||
1092 | X2 = RK[2] ^ (FSb[(uint8) (Y2 >> 24)] << 24) ^ | ||
1093 | (FSb[(uint8) (Y3 >> 16)] << 16) ^ | ||
1094 | (FSb[(uint8) (Y0 >> 8)] << 8) ^ (FSb[(uint8) (Y1)]); | ||
1095 | |||
1096 | X3 = RK[3] ^ (FSb[(uint8) (Y3 >> 24)] << 24) ^ | ||
1097 | (FSb[(uint8) (Y0 >> 16)] << 16) ^ | ||
1098 | (FSb[(uint8) (Y1 >> 8)] << 8) ^ (FSb[(uint8) (Y2)]); | ||
1099 | |||
1100 | PUT_UINT32(X0, output, 0); | ||
1101 | PUT_UINT32(X1, output, 4); | ||
1102 | PUT_UINT32(X2, output, 8); | ||
1103 | PUT_UINT32(X3, output, 12); | ||
1104 | } | ||
1105 | |||
1106 | /* AES 128-bit block decryption routine */ | ||
1107 | |||
1108 | void rt_aes_decrypt(struct aes_context * ctx, uint8 input[16], uint8 output[16]) | ||
1109 | { | ||
1110 | uint32 *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; | ||
1111 | |||
1112 | RK = (uint32 *) ctx->drk; | ||
1113 | |||
1114 | GET_UINT32(X0, input, 0); | ||
1115 | X0 ^= RK[0]; | ||
1116 | GET_UINT32(X1, input, 4); | ||
1117 | X1 ^= RK[1]; | ||
1118 | GET_UINT32(X2, input, 8); | ||
1119 | X2 ^= RK[2]; | ||
1120 | GET_UINT32(X3, input, 12); | ||
1121 | X3 ^= RK[3]; | ||
1122 | |||
1123 | #define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ | ||
1124 | { \ | ||
1125 | RK += 4; \ | ||
1126 | \ | ||
1127 | X0 = RK[0] ^ RT0[ (uint8) ( Y0 >> 24 ) ] ^ \ | ||
1128 | RT1[ (uint8) ( Y3 >> 16 ) ] ^ \ | ||
1129 | RT2[ (uint8) ( Y2 >> 8 ) ] ^ \ | ||
1130 | RT3[ (uint8) ( Y1 ) ]; \ | ||
1131 | \ | ||
1132 | X1 = RK[1] ^ RT0[ (uint8) ( Y1 >> 24 ) ] ^ \ | ||
1133 | RT1[ (uint8) ( Y0 >> 16 ) ] ^ \ | ||
1134 | RT2[ (uint8) ( Y3 >> 8 ) ] ^ \ | ||
1135 | RT3[ (uint8) ( Y2 ) ]; \ | ||
1136 | \ | ||
1137 | X2 = RK[2] ^ RT0[ (uint8) ( Y2 >> 24 ) ] ^ \ | ||
1138 | RT1[ (uint8) ( Y1 >> 16 ) ] ^ \ | ||
1139 | RT2[ (uint8) ( Y0 >> 8 ) ] ^ \ | ||
1140 | RT3[ (uint8) ( Y3 ) ]; \ | ||
1141 | \ | ||
1142 | X3 = RK[3] ^ RT0[ (uint8) ( Y3 >> 24 ) ] ^ \ | ||
1143 | RT1[ (uint8) ( Y2 >> 16 ) ] ^ \ | ||
1144 | RT2[ (uint8) ( Y1 >> 8 ) ] ^ \ | ||
1145 | RT3[ (uint8) ( Y0 ) ]; \ | ||
1146 | } | ||
1147 | |||
1148 | AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 1 */ | ||
1149 | AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); /* round 2 */ | ||
1150 | AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 3 */ | ||
1151 | AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); /* round 4 */ | ||
1152 | AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 5 */ | ||
1153 | AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); /* round 6 */ | ||
1154 | AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 7 */ | ||
1155 | AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); /* round 8 */ | ||
1156 | AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 9 */ | ||
1157 | |||
1158 | if (ctx->nr > 10) { | ||
1159 | AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); /* round 10 */ | ||
1160 | AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 11 */ | ||
1161 | } | ||
1162 | |||
1163 | if (ctx->nr > 12) { | ||
1164 | AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); /* round 12 */ | ||
1165 | AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); /* round 13 */ | ||
1166 | } | ||
1167 | |||
1168 | /* last round */ | ||
1169 | |||
1170 | RK += 4; | ||
1171 | |||
1172 | X0 = RK[0] ^ (RSb[(uint8) (Y0 >> 24)] << 24) ^ | ||
1173 | (RSb[(uint8) (Y3 >> 16)] << 16) ^ | ||
1174 | (RSb[(uint8) (Y2 >> 8)] << 8) ^ (RSb[(uint8) (Y1)]); | ||
1175 | |||
1176 | X1 = RK[1] ^ (RSb[(uint8) (Y1 >> 24)] << 24) ^ | ||
1177 | (RSb[(uint8) (Y0 >> 16)] << 16) ^ | ||
1178 | (RSb[(uint8) (Y3 >> 8)] << 8) ^ (RSb[(uint8) (Y2)]); | ||
1179 | |||
1180 | X2 = RK[2] ^ (RSb[(uint8) (Y2 >> 24)] << 24) ^ | ||
1181 | (RSb[(uint8) (Y1 >> 16)] << 16) ^ | ||
1182 | (RSb[(uint8) (Y0 >> 8)] << 8) ^ (RSb[(uint8) (Y3)]); | ||
1183 | |||
1184 | X3 = RK[3] ^ (RSb[(uint8) (Y3 >> 24)] << 24) ^ | ||
1185 | (RSb[(uint8) (Y2 >> 16)] << 16) ^ | ||
1186 | (RSb[(uint8) (Y1 >> 8)] << 8) ^ (RSb[(uint8) (Y0)]); | ||
1187 | |||
1188 | PUT_UINT32(X0, output, 0); | ||
1189 | PUT_UINT32(X1, output, 4); | ||
1190 | PUT_UINT32(X2, output, 8); | ||
1191 | PUT_UINT32(X3, output, 12); | ||
1192 | } | ||
1193 | |||
1194 | /* | ||
1195 | ========================================================================== | ||
1196 | Description: | ||
1197 | ENCRYPT AES GTK before sending in EAPOL frame. | ||
1198 | AES GTK length = 128 bit, so fix blocks for aes-key-wrap as 2 in this function. | ||
1199 | This function references to RFC 3394 for aes key wrap algorithm. | ||
1200 | Return: | ||
1201 | ========================================================================== | ||
1202 | */ | ||
1203 | void AES_GTK_KEY_WRAP(u8 * key, | ||
1204 | u8 * plaintext, | ||
1205 | u32 p_len, u8 * ciphertext) | ||
1206 | { | ||
1207 | u8 A[8], BIN[16], BOUT[16]; | ||
1208 | u8 R[512]; | ||
1209 | int num_blocks = p_len / 8; /* unit:64bits */ | ||
1210 | int i, j; | ||
1211 | struct aes_context aesctx; | ||
1212 | u8 xor; | ||
1213 | |||
1214 | rt_aes_set_key(&aesctx, key, 128); | ||
1215 | |||
1216 | /* Init IA */ | ||
1217 | for (i = 0; i < 8; i++) | ||
1218 | A[i] = 0xa6; | ||
1219 | |||
1220 | /*Input plaintext */ | ||
1221 | for (i = 0; i < num_blocks; i++) { | ||
1222 | for (j = 0; j < 8; j++) | ||
1223 | R[8 * (i + 1) + j] = plaintext[8 * i + j]; | ||
1224 | } | ||
1225 | |||
1226 | /* Key Mix */ | ||
1227 | for (j = 0; j < 6; j++) { | ||
1228 | for (i = 1; i <= num_blocks; i++) { | ||
1229 | /*phase 1 */ | ||
1230 | NdisMoveMemory(BIN, A, 8); | ||
1231 | NdisMoveMemory(&BIN[8], &R[8 * i], 8); | ||
1232 | rt_aes_encrypt(&aesctx, BIN, BOUT); | ||
1233 | |||
1234 | NdisMoveMemory(A, &BOUT[0], 8); | ||
1235 | xor = num_blocks * j + i; | ||
1236 | A[7] = BOUT[7] ^ xor; | ||
1237 | NdisMoveMemory(&R[8 * i], &BOUT[8], 8); | ||
1238 | } | ||
1239 | } | ||
1240 | |||
1241 | /* Output ciphertext */ | ||
1242 | NdisMoveMemory(ciphertext, A, 8); | ||
1243 | |||
1244 | for (i = 1; i <= num_blocks; i++) { | ||
1245 | for (j = 0; j < 8; j++) | ||
1246 | ciphertext[8 * i + j] = R[8 * i + j]; | ||
1247 | } | ||
1248 | } | ||
1249 | |||
1250 | /* | ||
1251 | ======================================================================== | ||
1252 | |||
1253 | Routine Description: | ||
1254 | Misc function to decrypt AES body | ||
1255 | |||
1256 | Arguments: | ||
1257 | |||
1258 | Return Value: | ||
1259 | |||
1260 | Note: | ||
1261 | This function references to RFC 3394 for aes key unwrap algorithm. | ||
1262 | |||
1263 | ======================================================================== | ||
1264 | */ | ||
1265 | void AES_GTK_KEY_UNWRAP(u8 * key, | ||
1266 | u8 * plaintext, | ||
1267 | u32 c_len, u8 * ciphertext) | ||
1268 | { | ||
1269 | u8 A[8], BIN[16], BOUT[16]; | ||
1270 | u8 xor; | ||
1271 | int i, j; | ||
1272 | struct aes_context aesctx; | ||
1273 | u8 *R; | ||
1274 | int num_blocks = c_len / 8; /* unit:64bits */ | ||
1275 | |||
1276 | os_alloc_mem(NULL, (u8 **) & R, 512); | ||
1277 | |||
1278 | if (R == NULL) { | ||
1279 | DBGPRINT(RT_DEBUG_ERROR, | ||
1280 | ("AES_GTK_KEY_UNWRAP: no memory!\n")); | ||
1281 | return; | ||
1282 | } | ||
1283 | /* End of if */ | ||
1284 | /* Initialize */ | ||
1285 | NdisMoveMemory(A, ciphertext, 8); | ||
1286 | /*Input plaintext */ | ||
1287 | for (i = 0; i < (c_len - 8); i++) { | ||
1288 | R[i] = ciphertext[i + 8]; | ||
1289 | } | ||
1290 | |||
1291 | rt_aes_set_key(&aesctx, key, 128); | ||
1292 | |||
1293 | for (j = 5; j >= 0; j--) { | ||
1294 | for (i = (num_blocks - 1); i > 0; i--) { | ||
1295 | xor = (num_blocks - 1) * j + i; | ||
1296 | NdisMoveMemory(BIN, A, 8); | ||
1297 | BIN[7] = A[7] ^ xor; | ||
1298 | NdisMoveMemory(&BIN[8], &R[(i - 1) * 8], 8); | ||
1299 | rt_aes_decrypt(&aesctx, BIN, BOUT); | ||
1300 | NdisMoveMemory(A, &BOUT[0], 8); | ||
1301 | NdisMoveMemory(&R[(i - 1) * 8], &BOUT[8], 8); | ||
1302 | } | ||
1303 | } | ||
1304 | |||
1305 | /* OUTPUT */ | ||
1306 | for (i = 0; i < c_len; i++) { | ||
1307 | plaintext[i] = R[i]; | ||
1308 | } | ||
1309 | |||
1310 | os_free_mem(NULL, R); | ||
1311 | } | ||
diff --git a/drivers/staging/rt2860/common/cmm_asic.c b/drivers/staging/rt2860/common/cmm_asic.c deleted file mode 100644 index 4d77e83eb41..00000000000 --- a/drivers/staging/rt2860/common/cmm_asic.c +++ /dev/null | |||
@@ -1,2565 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | |||
27 | Module Name: | ||
28 | cmm_asic.c | ||
29 | |||
30 | Abstract: | ||
31 | Functions used to communicate with ASIC | ||
32 | |||
33 | Revision History: | ||
34 | Who When What | ||
35 | -------- ---------- ---------------------------------------------- | ||
36 | */ | ||
37 | |||
38 | #include "../rt_config.h" | ||
39 | |||
40 | /* Reset the RFIC setting to new series */ | ||
41 | struct rt_rtmp_rf_regs RF2850RegTable[] = { | ||
42 | /* ch R1 R2 R3(TX0~4=0) R4 */ | ||
43 | {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b} | ||
44 | , | ||
45 | {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f} | ||
46 | , | ||
47 | {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b} | ||
48 | , | ||
49 | {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f} | ||
50 | , | ||
51 | {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b} | ||
52 | , | ||
53 | {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f} | ||
54 | , | ||
55 | {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b} | ||
56 | , | ||
57 | {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f} | ||
58 | , | ||
59 | {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b} | ||
60 | , | ||
61 | {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f} | ||
62 | , | ||
63 | {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b} | ||
64 | , | ||
65 | {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f} | ||
66 | , | ||
67 | {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b} | ||
68 | , | ||
69 | {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193} | ||
70 | , | ||
71 | |||
72 | /* 802.11 UNI / HyperLan 2 */ | ||
73 | {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3} | ||
74 | , | ||
75 | {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193} | ||
76 | , | ||
77 | {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183} | ||
78 | , | ||
79 | {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3} | ||
80 | , | ||
81 | {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b} | ||
82 | , | ||
83 | {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b} | ||
84 | , | ||
85 | {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193} | ||
86 | , | ||
87 | {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3} | ||
88 | , | ||
89 | {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b} | ||
90 | , | ||
91 | {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183} | ||
92 | , | ||
93 | {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193} | ||
94 | , | ||
95 | {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3} | ||
96 | , /* Plugfest#4, Day4, change RFR3 left4th 9->5. */ | ||
97 | |||
98 | /* 802.11 HyperLan 2 */ | ||
99 | {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783} | ||
100 | , | ||
101 | |||
102 | /* 2008.04.30 modified */ | ||
103 | /* The system team has AN to improve the EVM value */ | ||
104 | /* for channel 102 to 108 for the RT2850/RT2750 dual band solution. */ | ||
105 | {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793} | ||
106 | , | ||
107 | {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3} | ||
108 | , | ||
109 | {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193} | ||
110 | , | ||
111 | |||
112 | {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183} | ||
113 | , | ||
114 | {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b} | ||
115 | , | ||
116 | {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3} | ||
117 | , | ||
118 | {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193} | ||
119 | , | ||
120 | {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183} | ||
121 | , | ||
122 | {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193} | ||
123 | , | ||
124 | {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b} | ||
125 | , /* 0x980ed1bb->0x980ed15b required by Rory 20070927 */ | ||
126 | {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3} | ||
127 | , | ||
128 | {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b} | ||
129 | , | ||
130 | {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193} | ||
131 | , | ||
132 | {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b} | ||
133 | , | ||
134 | {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183} | ||
135 | , | ||
136 | |||
137 | /* 802.11 UNII */ | ||
138 | {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7} | ||
139 | , | ||
140 | {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187} | ||
141 | , | ||
142 | {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f} | ||
143 | , | ||
144 | {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f} | ||
145 | , | ||
146 | {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7} | ||
147 | , | ||
148 | {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187} | ||
149 | , | ||
150 | {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197} | ||
151 | , | ||
152 | {167, 0x98402ec4, 0x984c03d2, 0x98179855, 0x9815531f} | ||
153 | , | ||
154 | {169, 0x98402ec4, 0x984c03d2, 0x98179855, 0x98155327} | ||
155 | , | ||
156 | {171, 0x98402ec4, 0x984c03d6, 0x98179855, 0x98155307} | ||
157 | , | ||
158 | {173, 0x98402ec4, 0x984c03d6, 0x98179855, 0x9815530f} | ||
159 | , | ||
160 | |||
161 | /* Japan */ | ||
162 | {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b} | ||
163 | , | ||
164 | {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13} | ||
165 | , | ||
166 | {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b} | ||
167 | , | ||
168 | {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23} | ||
169 | , | ||
170 | {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13} | ||
171 | , | ||
172 | {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b} | ||
173 | , | ||
174 | {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23} | ||
175 | , | ||
176 | |||
177 | /* still lack of MMAC(Japan) ch 34,38,42,46 */ | ||
178 | }; | ||
179 | |||
180 | u8 NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(struct rt_rtmp_rf_regs)); | ||
181 | |||
182 | struct rt_frequency_item FreqItems3020[] = { | ||
183 | /**************************************************/ | ||
184 | /* ISM : 2.4 to 2.483 GHz // */ | ||
185 | /**************************************************/ | ||
186 | /* 11g */ | ||
187 | /**************************************************/ | ||
188 | /*-CH---N-------R---K----------- */ | ||
189 | {1, 241, 2, 2} | ||
190 | , | ||
191 | {2, 241, 2, 7} | ||
192 | , | ||
193 | {3, 242, 2, 2} | ||
194 | , | ||
195 | {4, 242, 2, 7} | ||
196 | , | ||
197 | {5, 243, 2, 2} | ||
198 | , | ||
199 | {6, 243, 2, 7} | ||
200 | , | ||
201 | {7, 244, 2, 2} | ||
202 | , | ||
203 | {8, 244, 2, 7} | ||
204 | , | ||
205 | {9, 245, 2, 2} | ||
206 | , | ||
207 | {10, 245, 2, 7} | ||
208 | , | ||
209 | {11, 246, 2, 2} | ||
210 | , | ||
211 | {12, 246, 2, 7} | ||
212 | , | ||
213 | {13, 247, 2, 2} | ||
214 | , | ||
215 | {14, 248, 2, 4} | ||
216 | , | ||
217 | }; | ||
218 | |||
219 | u8 NUM_OF_3020_CHNL = (sizeof(FreqItems3020) / sizeof(struct rt_frequency_item)); | ||
220 | |||
221 | void AsicUpdateAutoFallBackTable(struct rt_rtmp_adapter *pAd, u8 *pRateTable) | ||
222 | { | ||
223 | u8 i; | ||
224 | HT_FBK_CFG0_STRUC HtCfg0; | ||
225 | HT_FBK_CFG1_STRUC HtCfg1; | ||
226 | LG_FBK_CFG0_STRUC LgCfg0; | ||
227 | LG_FBK_CFG1_STRUC LgCfg1; | ||
228 | struct rt_rtmp_tx_rate_switch *pCurrTxRate, *pNextTxRate; | ||
229 | |||
230 | /* set to initial value */ | ||
231 | HtCfg0.word = 0x65432100; | ||
232 | HtCfg1.word = 0xedcba988; | ||
233 | LgCfg0.word = 0xedcba988; | ||
234 | LgCfg1.word = 0x00002100; | ||
235 | |||
236 | pNextTxRate = (struct rt_rtmp_tx_rate_switch *) pRateTable + 1; | ||
237 | for (i = 1; i < *((u8 *)pRateTable); i++) { | ||
238 | pCurrTxRate = (struct rt_rtmp_tx_rate_switch *) pRateTable + 1 + i; | ||
239 | switch (pCurrTxRate->Mode) { | ||
240 | case 0: /*CCK */ | ||
241 | break; | ||
242 | case 1: /*OFDM */ | ||
243 | { | ||
244 | switch (pCurrTxRate->CurrMCS) { | ||
245 | case 0: | ||
246 | LgCfg0.field.OFDMMCS0FBK = | ||
247 | (pNextTxRate->Mode == | ||
248 | MODE_OFDM) ? (pNextTxRate-> | ||
249 | CurrMCS + | ||
250 | 8) : pNextTxRate-> | ||
251 | CurrMCS; | ||
252 | break; | ||
253 | case 1: | ||
254 | LgCfg0.field.OFDMMCS1FBK = | ||
255 | (pNextTxRate->Mode == | ||
256 | MODE_OFDM) ? (pNextTxRate-> | ||
257 | CurrMCS + | ||
258 | 8) : pNextTxRate-> | ||
259 | CurrMCS; | ||
260 | break; | ||
261 | case 2: | ||
262 | LgCfg0.field.OFDMMCS2FBK = | ||
263 | (pNextTxRate->Mode == | ||
264 | MODE_OFDM) ? (pNextTxRate-> | ||
265 | CurrMCS + | ||
266 | 8) : pNextTxRate-> | ||
267 | CurrMCS; | ||
268 | break; | ||
269 | case 3: | ||
270 | LgCfg0.field.OFDMMCS3FBK = | ||
271 | (pNextTxRate->Mode == | ||
272 | MODE_OFDM) ? (pNextTxRate-> | ||
273 | CurrMCS + | ||
274 | 8) : pNextTxRate-> | ||
275 | CurrMCS; | ||
276 | break; | ||
277 | case 4: | ||
278 | LgCfg0.field.OFDMMCS4FBK = | ||
279 | (pNextTxRate->Mode == | ||
280 | MODE_OFDM) ? (pNextTxRate-> | ||
281 | CurrMCS + | ||
282 | 8) : pNextTxRate-> | ||
283 | CurrMCS; | ||
284 | break; | ||
285 | case 5: | ||
286 | LgCfg0.field.OFDMMCS5FBK = | ||
287 | (pNextTxRate->Mode == | ||
288 | MODE_OFDM) ? (pNextTxRate-> | ||
289 | CurrMCS + | ||
290 | 8) : pNextTxRate-> | ||
291 | CurrMCS; | ||
292 | break; | ||
293 | case 6: | ||
294 | LgCfg0.field.OFDMMCS6FBK = | ||
295 | (pNextTxRate->Mode == | ||
296 | MODE_OFDM) ? (pNextTxRate-> | ||
297 | CurrMCS + | ||
298 | 8) : pNextTxRate-> | ||
299 | CurrMCS; | ||
300 | break; | ||
301 | case 7: | ||
302 | LgCfg0.field.OFDMMCS7FBK = | ||
303 | (pNextTxRate->Mode == | ||
304 | MODE_OFDM) ? (pNextTxRate-> | ||
305 | CurrMCS + | ||
306 | 8) : pNextTxRate-> | ||
307 | CurrMCS; | ||
308 | break; | ||
309 | } | ||
310 | } | ||
311 | break; | ||
312 | case 2: /*HT-MIX */ | ||
313 | case 3: /*HT-GF */ | ||
314 | { | ||
315 | if ((pNextTxRate->Mode >= MODE_HTMIX) | ||
316 | && (pCurrTxRate->CurrMCS != | ||
317 | pNextTxRate->CurrMCS)) { | ||
318 | switch (pCurrTxRate->CurrMCS) { | ||
319 | case 0: | ||
320 | HtCfg0.field.HTMCS0FBK = | ||
321 | pNextTxRate->CurrMCS; | ||
322 | break; | ||
323 | case 1: | ||
324 | HtCfg0.field.HTMCS1FBK = | ||
325 | pNextTxRate->CurrMCS; | ||
326 | break; | ||
327 | case 2: | ||
328 | HtCfg0.field.HTMCS2FBK = | ||
329 | pNextTxRate->CurrMCS; | ||
330 | break; | ||
331 | case 3: | ||
332 | HtCfg0.field.HTMCS3FBK = | ||
333 | pNextTxRate->CurrMCS; | ||
334 | break; | ||
335 | case 4: | ||
336 | HtCfg0.field.HTMCS4FBK = | ||
337 | pNextTxRate->CurrMCS; | ||
338 | break; | ||
339 | case 5: | ||
340 | HtCfg0.field.HTMCS5FBK = | ||
341 | pNextTxRate->CurrMCS; | ||
342 | break; | ||
343 | case 6: | ||
344 | HtCfg0.field.HTMCS6FBK = | ||
345 | pNextTxRate->CurrMCS; | ||
346 | break; | ||
347 | case 7: | ||
348 | HtCfg0.field.HTMCS7FBK = | ||
349 | pNextTxRate->CurrMCS; | ||
350 | break; | ||
351 | case 8: | ||
352 | HtCfg1.field.HTMCS8FBK = | ||
353 | pNextTxRate->CurrMCS; | ||
354 | break; | ||
355 | case 9: | ||
356 | HtCfg1.field.HTMCS9FBK = | ||
357 | pNextTxRate->CurrMCS; | ||
358 | break; | ||
359 | case 10: | ||
360 | HtCfg1.field.HTMCS10FBK = | ||
361 | pNextTxRate->CurrMCS; | ||
362 | break; | ||
363 | case 11: | ||
364 | HtCfg1.field.HTMCS11FBK = | ||
365 | pNextTxRate->CurrMCS; | ||
366 | break; | ||
367 | case 12: | ||
368 | HtCfg1.field.HTMCS12FBK = | ||
369 | pNextTxRate->CurrMCS; | ||
370 | break; | ||
371 | case 13: | ||
372 | HtCfg1.field.HTMCS13FBK = | ||
373 | pNextTxRate->CurrMCS; | ||
374 | break; | ||
375 | case 14: | ||
376 | HtCfg1.field.HTMCS14FBK = | ||
377 | pNextTxRate->CurrMCS; | ||
378 | break; | ||
379 | case 15: | ||
380 | HtCfg1.field.HTMCS15FBK = | ||
381 | pNextTxRate->CurrMCS; | ||
382 | break; | ||
383 | default: | ||
384 | DBGPRINT(RT_DEBUG_ERROR, | ||
385 | ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", | ||
386 | pCurrTxRate-> | ||
387 | CurrMCS)); | ||
388 | } | ||
389 | } | ||
390 | } | ||
391 | break; | ||
392 | } | ||
393 | |||
394 | pNextTxRate = pCurrTxRate; | ||
395 | } | ||
396 | |||
397 | RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word); | ||
398 | RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word); | ||
399 | RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word); | ||
400 | RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word); | ||
401 | } | ||
402 | |||
403 | /* | ||
404 | ======================================================================== | ||
405 | |||
406 | Routine Description: | ||
407 | Set MAC register value according operation mode. | ||
408 | OperationMode AND bNonGFExist are for MM and GF Proteciton. | ||
409 | If MM or GF mask is not set, those passing argument doesn't not take effect. | ||
410 | |||
411 | Operation mode meaning: | ||
412 | = 0 : Pure HT, no preotection. | ||
413 | = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS. | ||
414 | = 0x10: No Transmission in 40M is protected. | ||
415 | = 0x11: Transmission in both 40M and 20M shall be protected | ||
416 | if (bNonGFExist) | ||
417 | we should choose not to use GF. But still set correct ASIC registers. | ||
418 | ======================================================================== | ||
419 | */ | ||
420 | void AsicUpdateProtect(struct rt_rtmp_adapter *pAd, | ||
421 | u16 OperationMode, | ||
422 | u8 SetMask, | ||
423 | IN BOOLEAN bDisableBGProtect, IN BOOLEAN bNonGFExist) | ||
424 | { | ||
425 | PROT_CFG_STRUC ProtCfg, ProtCfg4; | ||
426 | u32 Protect[6]; | ||
427 | u16 offset; | ||
428 | u8 i; | ||
429 | u32 MacReg = 0; | ||
430 | |||
431 | if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8)) { | ||
432 | return; | ||
433 | } | ||
434 | |||
435 | if (pAd->BATable.numDoneOriginator) { | ||
436 | /* */ | ||
437 | /* enable the RTS/CTS to avoid channel collision */ | ||
438 | /* */ | ||
439 | SetMask = ALLN_SETPROTECT; | ||
440 | OperationMode = 8; | ||
441 | } | ||
442 | /* Config ASIC RTS threshold register */ | ||
443 | RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg); | ||
444 | MacReg &= 0xFF0000FF; | ||
445 | /* If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096 */ | ||
446 | if (((pAd->CommonCfg.BACapability.field.AmsduEnable) || | ||
447 | (pAd->CommonCfg.bAggregationCapable == TRUE)) | ||
448 | && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD) { | ||
449 | MacReg |= (0x1000 << 8); | ||
450 | } else { | ||
451 | MacReg |= (pAd->CommonCfg.RtsThreshold << 8); | ||
452 | } | ||
453 | |||
454 | RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg); | ||
455 | |||
456 | /* Initial common protection settings */ | ||
457 | RTMPZeroMemory(Protect, sizeof(Protect)); | ||
458 | ProtCfg4.word = 0; | ||
459 | ProtCfg.word = 0; | ||
460 | ProtCfg.field.TxopAllowGF40 = 1; | ||
461 | ProtCfg.field.TxopAllowGF20 = 1; | ||
462 | ProtCfg.field.TxopAllowMM40 = 1; | ||
463 | ProtCfg.field.TxopAllowMM20 = 1; | ||
464 | ProtCfg.field.TxopAllowOfdm = 1; | ||
465 | ProtCfg.field.TxopAllowCck = 1; | ||
466 | ProtCfg.field.RTSThEn = 1; | ||
467 | ProtCfg.field.ProtectNav = ASIC_SHORTNAV; | ||
468 | |||
469 | /* update PHY mode and rate */ | ||
470 | if (pAd->CommonCfg.Channel > 14) | ||
471 | ProtCfg.field.ProtectRate = 0x4000; | ||
472 | ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate; | ||
473 | |||
474 | /* Handle legacy(B/G) protection */ | ||
475 | if (bDisableBGProtect) { | ||
476 | /*ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate; */ | ||
477 | ProtCfg.field.ProtectCtrl = 0; | ||
478 | Protect[0] = ProtCfg.word; | ||
479 | Protect[1] = ProtCfg.word; | ||
480 | pAd->FlgCtsEnabled = 0; /* CTS-self is not used */ | ||
481 | } else { | ||
482 | /*ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate; */ | ||
483 | ProtCfg.field.ProtectCtrl = 0; /* CCK do not need to be protected */ | ||
484 | Protect[0] = ProtCfg.word; | ||
485 | ProtCfg.field.ProtectCtrl = ASIC_CTS; /* OFDM needs using CCK to protect */ | ||
486 | Protect[1] = ProtCfg.word; | ||
487 | pAd->FlgCtsEnabled = 1; /* CTS-self is used */ | ||
488 | } | ||
489 | |||
490 | /* Decide HT frame protection. */ | ||
491 | if ((SetMask & ALLN_SETPROTECT) != 0) { | ||
492 | switch (OperationMode) { | ||
493 | case 0x0: | ||
494 | /* NO PROTECT */ | ||
495 | /* 1.All STAs in the BSS are 20/40 MHz HT */ | ||
496 | /* 2. in ai 20/40MHz BSS */ | ||
497 | /* 3. all STAs are 20MHz in a 20MHz BSS */ | ||
498 | /* Pure HT. no protection. */ | ||
499 | |||
500 | /* MM20_PROT_CFG */ | ||
501 | /* Reserved (31:27) */ | ||
502 | /* PROT_TXOP(25:20) -- 010111 */ | ||
503 | /* PROT_NAV(19:18) -- 01 (Short NAV protection) */ | ||
504 | /* PROT_CTRL(17:16) -- 00 (None) */ | ||
505 | /* PROT_RATE(15:0) -- 0x4004 (OFDM 24M) */ | ||
506 | Protect[2] = 0x01744004; | ||
507 | |||
508 | /* MM40_PROT_CFG */ | ||
509 | /* Reserved (31:27) */ | ||
510 | /* PROT_TXOP(25:20) -- 111111 */ | ||
511 | /* PROT_NAV(19:18) -- 01 (Short NAV protection) */ | ||
512 | /* PROT_CTRL(17:16) -- 00 (None) */ | ||
513 | /* PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M) */ | ||
514 | Protect[3] = 0x03f44084; | ||
515 | |||
516 | /* CF20_PROT_CFG */ | ||
517 | /* Reserved (31:27) */ | ||
518 | /* PROT_TXOP(25:20) -- 010111 */ | ||
519 | /* PROT_NAV(19:18) -- 01 (Short NAV protection) */ | ||
520 | /* PROT_CTRL(17:16) -- 00 (None) */ | ||
521 | /* PROT_RATE(15:0) -- 0x4004 (OFDM 24M) */ | ||
522 | Protect[4] = 0x01744004; | ||
523 | |||
524 | /* CF40_PROT_CFG */ | ||
525 | /* Reserved (31:27) */ | ||
526 | /* PROT_TXOP(25:20) -- 111111 */ | ||
527 | /* PROT_NAV(19:18) -- 01 (Short NAV protection) */ | ||
528 | /* PROT_CTRL(17:16) -- 00 (None) */ | ||
529 | /* PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M) */ | ||
530 | Protect[5] = 0x03f44084; | ||
531 | |||
532 | if (bNonGFExist) { | ||
533 | /* PROT_NAV(19:18) -- 01 (Short NAV protectiion) */ | ||
534 | /* PROT_CTRL(17:16) -- 01 (RTS/CTS) */ | ||
535 | Protect[4] = 0x01754004; | ||
536 | Protect[5] = 0x03f54084; | ||
537 | } | ||
538 | pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; | ||
539 | break; | ||
540 | |||
541 | case 1: | ||
542 | /* This is "HT non-member protection mode." */ | ||
543 | /* If there may be non-HT STAs my BSS */ | ||
544 | ProtCfg.word = 0x01744004; /* PROT_CTRL(17:16) : 0 (None) */ | ||
545 | ProtCfg4.word = 0x03f44084; /* duplicaet legacy 24M. BW set 1. */ | ||
546 | if (OPSTATUS_TEST_FLAG | ||
547 | (pAd, fOP_STATUS_BG_PROTECTION_INUSED)) { | ||
548 | ProtCfg.word = 0x01740003; /*ERP use Protection bit is set, use protection rate at Clause 18.. */ | ||
549 | ProtCfg4.word = 0x03f40003; /* Don't duplicate RTS/CTS in CCK mode. 0x03f40083; */ | ||
550 | } | ||
551 | /*Assign Protection method for 20&40 MHz packets */ | ||
552 | ProtCfg.field.ProtectCtrl = ASIC_RTS; | ||
553 | ProtCfg.field.ProtectNav = ASIC_SHORTNAV; | ||
554 | ProtCfg4.field.ProtectCtrl = ASIC_RTS; | ||
555 | ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; | ||
556 | Protect[2] = ProtCfg.word; | ||
557 | Protect[3] = ProtCfg4.word; | ||
558 | Protect[4] = ProtCfg.word; | ||
559 | Protect[5] = ProtCfg4.word; | ||
560 | pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; | ||
561 | break; | ||
562 | |||
563 | case 2: | ||
564 | /* If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets */ | ||
565 | ProtCfg.word = 0x01744004; /* PROT_CTRL(17:16) : 0 (None) */ | ||
566 | ProtCfg4.word = 0x03f44084; /* duplicaet legacy 24M. BW set 1. */ | ||
567 | |||
568 | /*Assign Protection method for 40MHz packets */ | ||
569 | ProtCfg4.field.ProtectCtrl = ASIC_RTS; | ||
570 | ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; | ||
571 | Protect[2] = ProtCfg.word; | ||
572 | Protect[3] = ProtCfg4.word; | ||
573 | if (bNonGFExist) { | ||
574 | ProtCfg.field.ProtectCtrl = ASIC_RTS; | ||
575 | ProtCfg.field.ProtectNav = ASIC_SHORTNAV; | ||
576 | } | ||
577 | Protect[4] = ProtCfg.word; | ||
578 | Protect[5] = ProtCfg4.word; | ||
579 | |||
580 | pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; | ||
581 | break; | ||
582 | |||
583 | case 3: | ||
584 | /* HT mixed mode. PROTECT ALL! */ | ||
585 | /* Assign Rate */ | ||
586 | ProtCfg.word = 0x01744004; /*duplicaet legacy 24M. BW set 1. */ | ||
587 | ProtCfg4.word = 0x03f44084; | ||
588 | /* both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the */ | ||
589 | if (OPSTATUS_TEST_FLAG | ||
590 | (pAd, fOP_STATUS_BG_PROTECTION_INUSED)) { | ||
591 | ProtCfg.word = 0x01740003; /*ERP use Protection bit is set, use protection rate at Clause 18.. */ | ||
592 | ProtCfg4.word = 0x03f40003; /* Don't duplicate RTS/CTS in CCK mode. 0x03f40083 */ | ||
593 | } | ||
594 | /*Assign Protection method for 20&40 MHz packets */ | ||
595 | ProtCfg.field.ProtectCtrl = ASIC_RTS; | ||
596 | ProtCfg.field.ProtectNav = ASIC_SHORTNAV; | ||
597 | ProtCfg4.field.ProtectCtrl = ASIC_RTS; | ||
598 | ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; | ||
599 | Protect[2] = ProtCfg.word; | ||
600 | Protect[3] = ProtCfg4.word; | ||
601 | Protect[4] = ProtCfg.word; | ||
602 | Protect[5] = ProtCfg4.word; | ||
603 | pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; | ||
604 | break; | ||
605 | |||
606 | case 8: | ||
607 | /* Special on for Atheros problem n chip. */ | ||
608 | Protect[2] = 0x01754004; | ||
609 | Protect[3] = 0x03f54084; | ||
610 | Protect[4] = 0x01754004; | ||
611 | Protect[5] = 0x03f54084; | ||
612 | pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; | ||
613 | break; | ||
614 | } | ||
615 | } | ||
616 | |||
617 | offset = CCK_PROT_CFG; | ||
618 | for (i = 0; i < 6; i++) { | ||
619 | if ((SetMask & (1 << i))) { | ||
620 | RTMP_IO_WRITE32(pAd, offset + i * 4, Protect[i]); | ||
621 | } | ||
622 | } | ||
623 | } | ||
624 | |||
625 | /* | ||
626 | ========================================================================== | ||
627 | Description: | ||
628 | |||
629 | IRQL = PASSIVE_LEVEL | ||
630 | IRQL = DISPATCH_LEVEL | ||
631 | |||
632 | ========================================================================== | ||
633 | */ | ||
634 | void AsicSwitchChannel(struct rt_rtmp_adapter *pAd, u8 Channel, IN BOOLEAN bScan) | ||
635 | { | ||
636 | unsigned long R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0; | ||
637 | char TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; /*Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER; */ | ||
638 | u8 index; | ||
639 | u32 Value = 0; /*BbpReg, Value; */ | ||
640 | struct rt_rtmp_rf_regs *RFRegTable; | ||
641 | u8 RFValue; | ||
642 | |||
643 | RFValue = 0; | ||
644 | /* Search Tx power value */ | ||
645 | /* We can't use ChannelList to search channel, since some central channl's txpowr doesn't list */ | ||
646 | /* in ChannelList, so use TxPower array instead. */ | ||
647 | /* */ | ||
648 | for (index = 0; index < MAX_NUM_OF_CHANNELS; index++) { | ||
649 | if (Channel == pAd->TxPower[index].Channel) { | ||
650 | TxPwer = pAd->TxPower[index].Power; | ||
651 | TxPwer2 = pAd->TxPower[index].Power2; | ||
652 | break; | ||
653 | } | ||
654 | } | ||
655 | |||
656 | if (index == MAX_NUM_OF_CHANNELS) { | ||
657 | DBGPRINT(RT_DEBUG_ERROR, | ||
658 | ("AsicSwitchChannel: Can't find the Channel#%d \n", | ||
659 | Channel)); | ||
660 | } | ||
661 | #ifdef RT30xx | ||
662 | /* The RF programming sequence is difference between 3xxx and 2xxx */ | ||
663 | if ((IS_RT3070(pAd) || IS_RT3090(pAd) || IS_RT3390(pAd)) | ||
664 | && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020) | ||
665 | || (pAd->RfIcType == RFIC_3021) | ||
666 | || (pAd->RfIcType == RFIC_3022))) { | ||
667 | /* modify by WY for Read RF Reg. error */ | ||
668 | |||
669 | for (index = 0; index < NUM_OF_3020_CHNL; index++) { | ||
670 | if (Channel == FreqItems3020[index].Channel) { | ||
671 | /* Programming channel parameters */ | ||
672 | RT30xxWriteRFRegister(pAd, RF_R02, | ||
673 | FreqItems3020[index].N); | ||
674 | RT30xxWriteRFRegister(pAd, RF_R03, | ||
675 | FreqItems3020[index].K); | ||
676 | RT30xxReadRFRegister(pAd, RF_R06, &RFValue); | ||
677 | RFValue = | ||
678 | (RFValue & 0xFC) | FreqItems3020[index].R; | ||
679 | RT30xxWriteRFRegister(pAd, RF_R06, RFValue); | ||
680 | |||
681 | /* Set Tx0 Power */ | ||
682 | RT30xxReadRFRegister(pAd, RF_R12, &RFValue); | ||
683 | RFValue = (RFValue & 0xE0) | TxPwer; | ||
684 | RT30xxWriteRFRegister(pAd, RF_R12, RFValue); | ||
685 | |||
686 | /* Set Tx1 Power */ | ||
687 | RT30xxReadRFRegister(pAd, RF_R13, &RFValue); | ||
688 | RFValue = (RFValue & 0xE0) | TxPwer2; | ||
689 | RT30xxWriteRFRegister(pAd, RF_R13, RFValue); | ||
690 | |||
691 | /* Tx/Rx Stream setting */ | ||
692 | RT30xxReadRFRegister(pAd, RF_R01, &RFValue); | ||
693 | /*if (IS_RT3090(pAd)) */ | ||
694 | /* RFValue |= 0x01; // Enable RF block. */ | ||
695 | RFValue &= 0x03; /*clear bit[7~2] */ | ||
696 | if (pAd->Antenna.field.TxPath == 1) | ||
697 | RFValue |= 0xA0; | ||
698 | else if (pAd->Antenna.field.TxPath == 2) | ||
699 | RFValue |= 0x80; | ||
700 | if (pAd->Antenna.field.RxPath == 1) | ||
701 | RFValue |= 0x50; | ||
702 | else if (pAd->Antenna.field.RxPath == 2) | ||
703 | RFValue |= 0x40; | ||
704 | RT30xxWriteRFRegister(pAd, RF_R01, RFValue); | ||
705 | |||
706 | /* Set RF offset */ | ||
707 | RT30xxReadRFRegister(pAd, RF_R23, &RFValue); | ||
708 | RFValue = (RFValue & 0x80) | pAd->RfFreqOffset; | ||
709 | RT30xxWriteRFRegister(pAd, RF_R23, RFValue); | ||
710 | |||
711 | /* Set BW */ | ||
712 | if (!bScan | ||
713 | && (pAd->CommonCfg.BBPCurrentBW == BW_40)) { | ||
714 | RFValue = pAd->Mlme.CaliBW40RfR24; | ||
715 | /*DISABLE_11N_CHECK(pAd); */ | ||
716 | } else { | ||
717 | RFValue = pAd->Mlme.CaliBW20RfR24; | ||
718 | } | ||
719 | RT30xxWriteRFRegister(pAd, RF_R24, RFValue); | ||
720 | RT30xxWriteRFRegister(pAd, RF_R31, RFValue); | ||
721 | |||
722 | /* Enable RF tuning */ | ||
723 | RT30xxReadRFRegister(pAd, RF_R07, &RFValue); | ||
724 | RFValue = RFValue | 0x1; | ||
725 | RT30xxWriteRFRegister(pAd, RF_R07, RFValue); | ||
726 | |||
727 | /* latch channel for future usage. */ | ||
728 | pAd->LatchRfRegs.Channel = Channel; | ||
729 | |||
730 | DBGPRINT(RT_DEBUG_TRACE, | ||
731 | ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n", | ||
732 | Channel, pAd->RfIcType, TxPwer, | ||
733 | TxPwer2, pAd->Antenna.field.TxPath, | ||
734 | FreqItems3020[index].N, | ||
735 | FreqItems3020[index].K, | ||
736 | FreqItems3020[index].R)); | ||
737 | |||
738 | break; | ||
739 | } | ||
740 | } | ||
741 | } else | ||
742 | #endif /* RT30xx // */ | ||
743 | { | ||
744 | RFRegTable = RF2850RegTable; | ||
745 | switch (pAd->RfIcType) { | ||
746 | case RFIC_2820: | ||
747 | case RFIC_2850: | ||
748 | case RFIC_2720: | ||
749 | case RFIC_2750: | ||
750 | |||
751 | for (index = 0; index < NUM_OF_2850_CHNL; index++) { | ||
752 | if (Channel == RFRegTable[index].Channel) { | ||
753 | R2 = RFRegTable[index].R2; | ||
754 | if (pAd->Antenna.field.TxPath == 1) { | ||
755 | R2 |= 0x4000; /* If TXpath is 1, bit 14 = 1; */ | ||
756 | } | ||
757 | |||
758 | if (pAd->Antenna.field.RxPath == 2) { | ||
759 | R2 |= 0x40; /* write 1 to off Rxpath. */ | ||
760 | } else if (pAd->Antenna.field.RxPath == | ||
761 | 1) { | ||
762 | R2 |= 0x20040; /* write 1 to off RxPath */ | ||
763 | } | ||
764 | |||
765 | if (Channel > 14) { | ||
766 | /* initialize R3, R4 */ | ||
767 | R3 = (RFRegTable[index]. | ||
768 | R3 & 0xffffc1ff); | ||
769 | R4 = (RFRegTable[index]. | ||
770 | R4 & (~0x001f87c0)) | | ||
771 | (pAd->RfFreqOffset << 15); | ||
772 | |||
773 | /* 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB */ | ||
774 | /* R3 */ | ||
775 | if ((TxPwer >= -7) | ||
776 | && (TxPwer < 0)) { | ||
777 | TxPwer = (7 + TxPwer); | ||
778 | TxPwer = | ||
779 | (TxPwer > | ||
780 | 0xF) ? (0xF) | ||
781 | : (TxPwer); | ||
782 | R3 |= (TxPwer << 10); | ||
783 | DBGPRINT(RT_DEBUG_ERROR, | ||
784 | ("AsicSwitchChannel: TxPwer=%d \n", | ||
785 | TxPwer)); | ||
786 | } else { | ||
787 | TxPwer = | ||
788 | (TxPwer > | ||
789 | 0xF) ? (0xF) | ||
790 | : (TxPwer); | ||
791 | R3 |= | ||
792 | (TxPwer << 10) | (1 | ||
793 | << | ||
794 | 9); | ||
795 | } | ||
796 | |||
797 | /* R4 */ | ||
798 | if ((TxPwer2 >= -7) | ||
799 | && (TxPwer2 < 0)) { | ||
800 | TxPwer2 = (7 + TxPwer2); | ||
801 | TxPwer2 = | ||
802 | (TxPwer2 > | ||
803 | 0xF) ? (0xF) | ||
804 | : (TxPwer2); | ||
805 | R4 |= (TxPwer2 << 7); | ||
806 | DBGPRINT(RT_DEBUG_ERROR, | ||
807 | ("AsicSwitchChannel: TxPwer2=%d \n", | ||
808 | TxPwer2)); | ||
809 | } else { | ||
810 | TxPwer2 = | ||
811 | (TxPwer2 > | ||
812 | 0xF) ? (0xF) | ||
813 | : (TxPwer2); | ||
814 | R4 |= | ||
815 | (TxPwer2 << 7) | (1 | ||
816 | << | ||
817 | 6); | ||
818 | } | ||
819 | } else { | ||
820 | R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); /* set TX power0 */ | ||
821 | R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 << 6); /* Set freq Offset & TxPwr1 */ | ||
822 | } | ||
823 | |||
824 | /* Based on BBP current mode before changing RF channel. */ | ||
825 | if (!bScan | ||
826 | && (pAd->CommonCfg.BBPCurrentBW == | ||
827 | BW_40)) { | ||
828 | R4 |= 0x200000; | ||
829 | } | ||
830 | /* Update variables */ | ||
831 | pAd->LatchRfRegs.Channel = Channel; | ||
832 | pAd->LatchRfRegs.R1 = | ||
833 | RFRegTable[index].R1; | ||
834 | pAd->LatchRfRegs.R2 = R2; | ||
835 | pAd->LatchRfRegs.R3 = R3; | ||
836 | pAd->LatchRfRegs.R4 = R4; | ||
837 | |||
838 | /* Set RF value 1's set R3[bit2] = [0] */ | ||
839 | RTMP_RF_IO_WRITE32(pAd, | ||
840 | pAd->LatchRfRegs.R1); | ||
841 | RTMP_RF_IO_WRITE32(pAd, | ||
842 | pAd->LatchRfRegs.R2); | ||
843 | RTMP_RF_IO_WRITE32(pAd, | ||
844 | (pAd->LatchRfRegs. | ||
845 | R3 & (~0x04))); | ||
846 | RTMP_RF_IO_WRITE32(pAd, | ||
847 | pAd->LatchRfRegs.R4); | ||
848 | |||
849 | RTMPusecDelay(200); | ||
850 | |||
851 | /* Set RF value 2's set R3[bit2] = [1] */ | ||
852 | RTMP_RF_IO_WRITE32(pAd, | ||
853 | pAd->LatchRfRegs.R1); | ||
854 | RTMP_RF_IO_WRITE32(pAd, | ||
855 | pAd->LatchRfRegs.R2); | ||
856 | RTMP_RF_IO_WRITE32(pAd, | ||
857 | (pAd->LatchRfRegs. | ||
858 | R3 | 0x04)); | ||
859 | RTMP_RF_IO_WRITE32(pAd, | ||
860 | pAd->LatchRfRegs.R4); | ||
861 | |||
862 | RTMPusecDelay(200); | ||
863 | |||
864 | /* Set RF value 3's set R3[bit2] = [0] */ | ||
865 | RTMP_RF_IO_WRITE32(pAd, | ||
866 | pAd->LatchRfRegs.R1); | ||
867 | RTMP_RF_IO_WRITE32(pAd, | ||
868 | pAd->LatchRfRegs.R2); | ||
869 | RTMP_RF_IO_WRITE32(pAd, | ||
870 | (pAd->LatchRfRegs. | ||
871 | R3 & (~0x04))); | ||
872 | RTMP_RF_IO_WRITE32(pAd, | ||
873 | pAd->LatchRfRegs.R4); | ||
874 | |||
875 | break; | ||
876 | } | ||
877 | } | ||
878 | break; | ||
879 | |||
880 | default: | ||
881 | break; | ||
882 | } | ||
883 | |||
884 | DBGPRINT(RT_DEBUG_TRACE, | ||
885 | ("SwitchChannel#%d(RF=%d, Pwr0=%lu, Pwr1=%lu, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n", | ||
886 | Channel, pAd->RfIcType, (R3 & 0x00003e00) >> 9, | ||
887 | (R4 & 0x000007c0) >> 6, pAd->Antenna.field.TxPath, | ||
888 | pAd->LatchRfRegs.R1, pAd->LatchRfRegs.R2, | ||
889 | pAd->LatchRfRegs.R3, pAd->LatchRfRegs.R4)); | ||
890 | } | ||
891 | |||
892 | /* Change BBP setting during siwtch from a->g, g->a */ | ||
893 | if (Channel <= 14) { | ||
894 | unsigned long TxPinCfg = 0x00050F0A; /*Gary 2007/08/09 0x050A0A */ | ||
895 | |||
896 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, | ||
897 | (0x37 - GET_LNA_GAIN(pAd))); | ||
898 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, | ||
899 | (0x37 - GET_LNA_GAIN(pAd))); | ||
900 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, | ||
901 | (0x37 - GET_LNA_GAIN(pAd))); | ||
902 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0); /*(0x44 - GET_LNA_GAIN(pAd))); // According the Rory's suggestion to solve the middle range issue. */ | ||
903 | /*RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); */ | ||
904 | |||
905 | /* Rx High power VGA offset for LNA select */ | ||
906 | if (pAd->NicConfig2.field.ExternalLNAForG) { | ||
907 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); | ||
908 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); | ||
909 | } else { | ||
910 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); | ||
911 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); | ||
912 | } | ||
913 | |||
914 | /* 5G band selection PIN, bit1 and bit2 are complement */ | ||
915 | RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); | ||
916 | Value &= (~0x6); | ||
917 | Value |= (0x04); | ||
918 | RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); | ||
919 | |||
920 | /* Turn off unused PA or LNA when only 1T or 1R */ | ||
921 | if (pAd->Antenna.field.TxPath == 1) { | ||
922 | TxPinCfg &= 0xFFFFFFF3; | ||
923 | } | ||
924 | if (pAd->Antenna.field.RxPath == 1) { | ||
925 | TxPinCfg &= 0xFFFFF3FF; | ||
926 | } | ||
927 | |||
928 | RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); | ||
929 | |||
930 | #if defined(RT3090) || defined(RT3390) | ||
931 | /* PCIe PHY Transmit attenuation adjustment */ | ||
932 | if (IS_RT3090A(pAd) || IS_RT3390(pAd)) { | ||
933 | TX_ATTENUATION_CTRL_STRUC TxAttenuationCtrl = { | ||
934 | .word = 0}; | ||
935 | |||
936 | RTMP_IO_READ32(pAd, PCIE_PHY_TX_ATTENUATION_CTRL, | ||
937 | &TxAttenuationCtrl.word); | ||
938 | |||
939 | if (Channel == 14) /* Channel #14 */ | ||
940 | { | ||
941 | TxAttenuationCtrl.field.PCIE_PHY_TX_ATTEN_EN = 1; /* Enable PCIe PHY Tx attenuation */ | ||
942 | TxAttenuationCtrl.field.PCIE_PHY_TX_ATTEN_VALUE = 4; /* 9/16 full drive level */ | ||
943 | } else /* Channel #1~#13 */ | ||
944 | { | ||
945 | TxAttenuationCtrl.field.PCIE_PHY_TX_ATTEN_EN = 0; /* Disable PCIe PHY Tx attenuation */ | ||
946 | TxAttenuationCtrl.field.PCIE_PHY_TX_ATTEN_VALUE = 0; /* n/a */ | ||
947 | } | ||
948 | |||
949 | RTMP_IO_WRITE32(pAd, PCIE_PHY_TX_ATTENUATION_CTRL, | ||
950 | TxAttenuationCtrl.word); | ||
951 | } | ||
952 | #endif | ||
953 | } else { | ||
954 | unsigned long TxPinCfg = 0x00050F05; /*Gary 2007/8/9 0x050505 */ | ||
955 | |||
956 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, | ||
957 | (0x37 - GET_LNA_GAIN(pAd))); | ||
958 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, | ||
959 | (0x37 - GET_LNA_GAIN(pAd))); | ||
960 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, | ||
961 | (0x37 - GET_LNA_GAIN(pAd))); | ||
962 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0); /*(0x44 - GET_LNA_GAIN(pAd))); // According the Rory's suggestion to solve the middle range issue. */ | ||
963 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2); | ||
964 | |||
965 | /* Rx High power VGA offset for LNA select */ | ||
966 | if (pAd->NicConfig2.field.ExternalLNAForA) { | ||
967 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); | ||
968 | } else { | ||
969 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); | ||
970 | } | ||
971 | |||
972 | /* 5G band selection PIN, bit1 and bit2 are complement */ | ||
973 | RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); | ||
974 | Value &= (~0x6); | ||
975 | Value |= (0x02); | ||
976 | RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); | ||
977 | |||
978 | /* Turn off unused PA or LNA when only 1T or 1R */ | ||
979 | if (pAd->Antenna.field.TxPath == 1) { | ||
980 | TxPinCfg &= 0xFFFFFFF3; | ||
981 | } | ||
982 | if (pAd->Antenna.field.RxPath == 1) { | ||
983 | TxPinCfg &= 0xFFFFF3FF; | ||
984 | } | ||
985 | |||
986 | RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); | ||
987 | |||
988 | } | ||
989 | |||
990 | /* R66 should be set according to Channel and use 20MHz when scanning */ | ||
991 | /*RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd))); */ | ||
992 | if (bScan) | ||
993 | RTMPSetAGCInitValue(pAd, BW_20); | ||
994 | else | ||
995 | RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW); | ||
996 | |||
997 | /* */ | ||
998 | /* On 11A, We should delay and wait RF/BBP to be stable */ | ||
999 | /* and the appropriate time should be 1000 micro seconds */ | ||
1000 | /* 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL. */ | ||
1001 | /* */ | ||
1002 | RTMPusecDelay(1000); | ||
1003 | } | ||
1004 | |||
1005 | void AsicResetBBPAgent(struct rt_rtmp_adapter *pAd) | ||
1006 | { | ||
1007 | BBP_CSR_CFG_STRUC BbpCsr; | ||
1008 | DBGPRINT(RT_DEBUG_ERROR, ("Reset BBP Agent busy bit!\n")); | ||
1009 | /* Still need to find why BBP agent keeps busy, but in fact, hardware still function ok. Now clear busy first. */ | ||
1010 | RTMP_IO_READ32(pAd, H2M_BBP_AGENT, &BbpCsr.word); | ||
1011 | BbpCsr.field.Busy = 0; | ||
1012 | RTMP_IO_WRITE32(pAd, H2M_BBP_AGENT, BbpCsr.word); | ||
1013 | } | ||
1014 | |||
1015 | /* | ||
1016 | ========================================================================== | ||
1017 | Description: | ||
1018 | This function is required for 2421 only, and should not be used during | ||
1019 | site survey. It's only required after NIC decided to stay at a channel | ||
1020 | for a longer period. | ||
1021 | When this function is called, it's always after AsicSwitchChannel(). | ||
1022 | |||
1023 | IRQL = PASSIVE_LEVEL | ||
1024 | IRQL = DISPATCH_LEVEL | ||
1025 | |||
1026 | ========================================================================== | ||
1027 | */ | ||
1028 | void AsicLockChannel(struct rt_rtmp_adapter *pAd, u8 Channel) | ||
1029 | { | ||
1030 | } | ||
1031 | |||
1032 | void AsicRfTuningExec(void *SystemSpecific1, | ||
1033 | void *FunctionContext, | ||
1034 | void *SystemSpecific2, void *SystemSpecific3) | ||
1035 | { | ||
1036 | } | ||
1037 | |||
1038 | /* | ||
1039 | ========================================================================== | ||
1040 | Description: | ||
1041 | Gives CCK TX rate 2 more dB TX power. | ||
1042 | This routine works only in LINK UP in INFRASTRUCTURE mode. | ||
1043 | |||
1044 | calculate desired Tx power in RF R3.Tx0~5, should consider - | ||
1045 | 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment) | ||
1046 | 1. TxPowerPercentage | ||
1047 | 2. auto calibration based on TSSI feedback | ||
1048 | 3. extra 2 db for CCK | ||
1049 | 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP | ||
1050 | |||
1051 | NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment), | ||
1052 | it should be called AFTER MlmeDynamicTxRatSwitching() | ||
1053 | ========================================================================== | ||
1054 | */ | ||
1055 | void AsicAdjustTxPower(struct rt_rtmp_adapter *pAd) | ||
1056 | { | ||
1057 | int i, j; | ||
1058 | char DeltaPwr = 0; | ||
1059 | BOOLEAN bAutoTxAgc = FALSE; | ||
1060 | u8 TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep; | ||
1061 | u8 BbpR1 = 0, BbpR49 = 0, idx; | ||
1062 | char *pTxAgcCompensate; | ||
1063 | unsigned long TxPwr[5]; | ||
1064 | char Value; | ||
1065 | char Rssi = -127; | ||
1066 | |||
1067 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) || | ||
1068 | #ifdef RTMP_MAC_PCI | ||
1069 | (pAd->bPCIclkOff == TRUE) || | ||
1070 | #endif /* RTMP_MAC_PCI // */ | ||
1071 | RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF) || | ||
1072 | RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) | ||
1073 | return; | ||
1074 | |||
1075 | Rssi = RTMPMaxRssi(pAd, | ||
1076 | pAd->StaCfg.RssiSample.AvgRssi0, | ||
1077 | pAd->StaCfg.RssiSample.AvgRssi1, | ||
1078 | pAd->StaCfg.RssiSample.AvgRssi2); | ||
1079 | |||
1080 | if (pAd->CommonCfg.BBPCurrentBW == BW_40) { | ||
1081 | if (pAd->CommonCfg.CentralChannel > 14) { | ||
1082 | TxPwr[0] = pAd->Tx40MPwrCfgABand[0]; | ||
1083 | TxPwr[1] = pAd->Tx40MPwrCfgABand[1]; | ||
1084 | TxPwr[2] = pAd->Tx40MPwrCfgABand[2]; | ||
1085 | TxPwr[3] = pAd->Tx40MPwrCfgABand[3]; | ||
1086 | TxPwr[4] = pAd->Tx40MPwrCfgABand[4]; | ||
1087 | } else { | ||
1088 | TxPwr[0] = pAd->Tx40MPwrCfgGBand[0]; | ||
1089 | TxPwr[1] = pAd->Tx40MPwrCfgGBand[1]; | ||
1090 | TxPwr[2] = pAd->Tx40MPwrCfgGBand[2]; | ||
1091 | TxPwr[3] = pAd->Tx40MPwrCfgGBand[3]; | ||
1092 | TxPwr[4] = pAd->Tx40MPwrCfgGBand[4]; | ||
1093 | } | ||
1094 | } else { | ||
1095 | if (pAd->CommonCfg.Channel > 14) { | ||
1096 | TxPwr[0] = pAd->Tx20MPwrCfgABand[0]; | ||
1097 | TxPwr[1] = pAd->Tx20MPwrCfgABand[1]; | ||
1098 | TxPwr[2] = pAd->Tx20MPwrCfgABand[2]; | ||
1099 | TxPwr[3] = pAd->Tx20MPwrCfgABand[3]; | ||
1100 | TxPwr[4] = pAd->Tx20MPwrCfgABand[4]; | ||
1101 | } else { | ||
1102 | TxPwr[0] = pAd->Tx20MPwrCfgGBand[0]; | ||
1103 | TxPwr[1] = pAd->Tx20MPwrCfgGBand[1]; | ||
1104 | TxPwr[2] = pAd->Tx20MPwrCfgGBand[2]; | ||
1105 | TxPwr[3] = pAd->Tx20MPwrCfgGBand[3]; | ||
1106 | TxPwr[4] = pAd->Tx20MPwrCfgGBand[4]; | ||
1107 | } | ||
1108 | } | ||
1109 | |||
1110 | /* TX power compensation for temperature variation based on TSSI. try every 4 second */ | ||
1111 | if (pAd->Mlme.OneSecPeriodicRound % 4 == 0) { | ||
1112 | if (pAd->CommonCfg.Channel <= 14) { | ||
1113 | /* bg channel */ | ||
1114 | bAutoTxAgc = pAd->bAutoTxAgcG; | ||
1115 | TssiRef = pAd->TssiRefG; | ||
1116 | pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0]; | ||
1117 | pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0]; | ||
1118 | TxAgcStep = pAd->TxAgcStepG; | ||
1119 | pTxAgcCompensate = &pAd->TxAgcCompensateG; | ||
1120 | } else { | ||
1121 | /* a channel */ | ||
1122 | bAutoTxAgc = pAd->bAutoTxAgcA; | ||
1123 | TssiRef = pAd->TssiRefA; | ||
1124 | pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0]; | ||
1125 | pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0]; | ||
1126 | TxAgcStep = pAd->TxAgcStepA; | ||
1127 | pTxAgcCompensate = &pAd->TxAgcCompensateA; | ||
1128 | } | ||
1129 | |||
1130 | if (bAutoTxAgc) { | ||
1131 | /* BbpR1 is unsigned char */ | ||
1132 | RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49); | ||
1133 | |||
1134 | /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */ | ||
1135 | /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */ | ||
1136 | /* step value is defined in pAd->TxAgcStepG for tx power value */ | ||
1137 | |||
1138 | /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */ | ||
1139 | /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0 | ||
1140 | above value are examined in mass factory production */ | ||
1141 | /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */ | ||
1142 | |||
1143 | /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */ | ||
1144 | /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */ | ||
1145 | /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */ | ||
1146 | |||
1147 | if (BbpR49 > pTssiMinusBoundary[1]) { | ||
1148 | /* Reading is larger than the reference value */ | ||
1149 | /* check for how large we need to decrease the Tx power */ | ||
1150 | for (idx = 1; idx < 5; idx++) { | ||
1151 | if (BbpR49 <= pTssiMinusBoundary[idx]) /* Found the range */ | ||
1152 | break; | ||
1153 | } | ||
1154 | /* The index is the step we should decrease, idx = 0 means there is nothing to compensate */ | ||
1155 | /* if (R3 > (unsigned long)(TxAgcStep * (idx-1))) */ | ||
1156 | *pTxAgcCompensate = -(TxAgcStep * (idx - 1)); | ||
1157 | /* else */ | ||
1158 | /* *pTxAgcCompensate = -((u8)R3); */ | ||
1159 | |||
1160 | DeltaPwr += (*pTxAgcCompensate); | ||
1161 | DBGPRINT(RT_DEBUG_TRACE, | ||
1162 | ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n", | ||
1163 | BbpR49, TssiRef, TxAgcStep, idx - 1)); | ||
1164 | } else if (BbpR49 < pTssiPlusBoundary[1]) { | ||
1165 | /* Reading is smaller than the reference value */ | ||
1166 | /* check for how large we need to increase the Tx power */ | ||
1167 | for (idx = 1; idx < 5; idx++) { | ||
1168 | if (BbpR49 >= pTssiPlusBoundary[idx]) /* Found the range */ | ||
1169 | break; | ||
1170 | } | ||
1171 | /* The index is the step we should increase, idx = 0 means there is nothing to compensate */ | ||
1172 | *pTxAgcCompensate = TxAgcStep * (idx - 1); | ||
1173 | DeltaPwr += (*pTxAgcCompensate); | ||
1174 | DBGPRINT(RT_DEBUG_TRACE, | ||
1175 | ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", | ||
1176 | BbpR49, TssiRef, TxAgcStep, idx - 1)); | ||
1177 | } else { | ||
1178 | *pTxAgcCompensate = 0; | ||
1179 | DBGPRINT(RT_DEBUG_TRACE, | ||
1180 | (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", | ||
1181 | BbpR49, TssiRef, TxAgcStep, 0)); | ||
1182 | } | ||
1183 | } | ||
1184 | } else { | ||
1185 | if (pAd->CommonCfg.Channel <= 14) { | ||
1186 | bAutoTxAgc = pAd->bAutoTxAgcG; | ||
1187 | pTxAgcCompensate = &pAd->TxAgcCompensateG; | ||
1188 | } else { | ||
1189 | bAutoTxAgc = pAd->bAutoTxAgcA; | ||
1190 | pTxAgcCompensate = &pAd->TxAgcCompensateA; | ||
1191 | } | ||
1192 | |||
1193 | if (bAutoTxAgc) | ||
1194 | DeltaPwr += (*pTxAgcCompensate); | ||
1195 | } | ||
1196 | |||
1197 | RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1); | ||
1198 | BbpR1 &= 0xFC; | ||
1199 | |||
1200 | /* calculate delta power based on the percentage specified from UI */ | ||
1201 | /* E2PROM setting is calibrated for maximum TX power (i.e. 100%) */ | ||
1202 | /* We lower TX power here according to the percentage specified from UI */ | ||
1203 | if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) /* AUTO TX POWER control */ | ||
1204 | { | ||
1205 | { | ||
1206 | /* to patch high power issue with some APs, like Belkin N1. */ | ||
1207 | if (Rssi > -35) { | ||
1208 | BbpR1 |= 0x02; /* DeltaPwr -= 12; */ | ||
1209 | } else if (Rssi > -40) { | ||
1210 | BbpR1 |= 0x01; /* DeltaPwr -= 6; */ | ||
1211 | } else; | ||
1212 | } | ||
1213 | } else if (pAd->CommonCfg.TxPowerPercentage > 90) /* 91 ~ 100% & AUTO, treat as 100% in terms of mW */ | ||
1214 | ; | ||
1215 | else if (pAd->CommonCfg.TxPowerPercentage > 60) /* 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1; */ | ||
1216 | { | ||
1217 | DeltaPwr -= 1; | ||
1218 | } else if (pAd->CommonCfg.TxPowerPercentage > 30) /* 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3; */ | ||
1219 | { | ||
1220 | DeltaPwr -= 3; | ||
1221 | } else if (pAd->CommonCfg.TxPowerPercentage > 15) /* 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6; */ | ||
1222 | { | ||
1223 | BbpR1 |= 0x01; | ||
1224 | } else if (pAd->CommonCfg.TxPowerPercentage > 9) /* 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9; */ | ||
1225 | { | ||
1226 | BbpR1 |= 0x01; | ||
1227 | DeltaPwr -= 3; | ||
1228 | } else /* 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12; */ | ||
1229 | { | ||
1230 | BbpR1 |= 0x02; | ||
1231 | } | ||
1232 | |||
1233 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1); | ||
1234 | |||
1235 | /* reset different new tx power for different TX rate */ | ||
1236 | for (i = 0; i < 5; i++) { | ||
1237 | if (TxPwr[i] != 0xffffffff) { | ||
1238 | for (j = 0; j < 8; j++) { | ||
1239 | Value = (char)((TxPwr[i] >> j * 4) & 0x0F); /* 0 ~ 15 */ | ||
1240 | |||
1241 | if ((Value + DeltaPwr) < 0) { | ||
1242 | Value = 0; /* min */ | ||
1243 | } else if ((Value + DeltaPwr) > 0xF) { | ||
1244 | Value = 0xF; /* max */ | ||
1245 | } else { | ||
1246 | Value += DeltaPwr; /* temperature compensation */ | ||
1247 | } | ||
1248 | |||
1249 | /* fill new value to CSR offset */ | ||
1250 | TxPwr[i] = | ||
1251 | (TxPwr[i] & ~(0x0000000F << j * 4)) | (Value | ||
1252 | << j | ||
1253 | * 4); | ||
1254 | } | ||
1255 | |||
1256 | /* write tx power value to CSR */ | ||
1257 | /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M | ||
1258 | TX power for OFDM 6M/9M | ||
1259 | TX power for CCK5.5M/11M | ||
1260 | TX power for CCK1M/2M */ | ||
1261 | /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */ | ||
1262 | RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i * 4, TxPwr[i]); | ||
1263 | } | ||
1264 | } | ||
1265 | |||
1266 | } | ||
1267 | |||
1268 | /* | ||
1269 | ========================================================================== | ||
1270 | Description: | ||
1271 | put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup | ||
1272 | automatically. Instead, MCU will issue a TwakeUpInterrupt to host after | ||
1273 | the wakeup timer timeout. Driver has to issue a separate command to wake | ||
1274 | PHY up. | ||
1275 | |||
1276 | IRQL = DISPATCH_LEVEL | ||
1277 | |||
1278 | ========================================================================== | ||
1279 | */ | ||
1280 | void AsicSleepThenAutoWakeup(struct rt_rtmp_adapter *pAd, | ||
1281 | u16 TbttNumToNextWakeUp) | ||
1282 | { | ||
1283 | RTMP_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp); | ||
1284 | } | ||
1285 | |||
1286 | /* | ||
1287 | ========================================================================== | ||
1288 | Description: | ||
1289 | AsicForceWakeup() is used whenever manual wakeup is required | ||
1290 | AsicForceSleep() should only be used when not in INFRA BSS. When | ||
1291 | in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead. | ||
1292 | ========================================================================== | ||
1293 | */ | ||
1294 | void AsicForceSleep(struct rt_rtmp_adapter *pAd) | ||
1295 | { | ||
1296 | |||
1297 | } | ||
1298 | |||
1299 | /* | ||
1300 | ========================================================================== | ||
1301 | Description: | ||
1302 | AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup) | ||
1303 | expired. | ||
1304 | |||
1305 | IRQL = PASSIVE_LEVEL | ||
1306 | IRQL = DISPATCH_LEVEL | ||
1307 | ========================================================================== | ||
1308 | */ | ||
1309 | void AsicForceWakeup(struct rt_rtmp_adapter *pAd, IN BOOLEAN bFromTx) | ||
1310 | { | ||
1311 | DBGPRINT(RT_DEBUG_INFO, ("--> AsicForceWakeup \n")); | ||
1312 | RTMP_STA_FORCE_WAKEUP(pAd, bFromTx); | ||
1313 | } | ||
1314 | |||
1315 | /* | ||
1316 | ========================================================================== | ||
1317 | Description: | ||
1318 | Set My BSSID | ||
1319 | |||
1320 | IRQL = DISPATCH_LEVEL | ||
1321 | |||
1322 | ========================================================================== | ||
1323 | */ | ||
1324 | void AsicSetBssid(struct rt_rtmp_adapter *pAd, u8 *pBssid) | ||
1325 | { | ||
1326 | unsigned long Addr4; | ||
1327 | DBGPRINT(RT_DEBUG_TRACE, | ||
1328 | ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n", pBssid[0], | ||
1329 | pBssid[1], pBssid[2], pBssid[3], pBssid[4], pBssid[5])); | ||
1330 | |||
1331 | Addr4 = (unsigned long)(pBssid[0]) | | ||
1332 | (unsigned long)(pBssid[1] << 8) | | ||
1333 | (unsigned long)(pBssid[2] << 16) | (unsigned long)(pBssid[3] << 24); | ||
1334 | RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4); | ||
1335 | |||
1336 | Addr4 = 0; | ||
1337 | /* always one BSSID in STA mode */ | ||
1338 | Addr4 = (unsigned long)(pBssid[4]) | (unsigned long)(pBssid[5] << 8); | ||
1339 | |||
1340 | RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4); | ||
1341 | } | ||
1342 | |||
1343 | void AsicSetMcastWC(struct rt_rtmp_adapter *pAd) | ||
1344 | { | ||
1345 | struct rt_mac_table_entry *pEntry = &pAd->MacTab.Content[MCAST_WCID]; | ||
1346 | u16 offset; | ||
1347 | |||
1348 | pEntry->Sst = SST_ASSOC; | ||
1349 | pEntry->Aid = MCAST_WCID; /* Softap supports 1 BSSID and use WCID=0 as multicast Wcid index */ | ||
1350 | pEntry->PsMode = PWR_ACTIVE; | ||
1351 | pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate; | ||
1352 | offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE; | ||
1353 | } | ||
1354 | |||
1355 | /* | ||
1356 | ========================================================================== | ||
1357 | Description: | ||
1358 | |||
1359 | IRQL = DISPATCH_LEVEL | ||
1360 | |||
1361 | ========================================================================== | ||
1362 | */ | ||
1363 | void AsicDelWcidTab(struct rt_rtmp_adapter *pAd, u8 Wcid) | ||
1364 | { | ||
1365 | unsigned long Addr0 = 0x0, Addr1 = 0x0; | ||
1366 | unsigned long offset; | ||
1367 | |||
1368 | DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n", Wcid)); | ||
1369 | offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE; | ||
1370 | RTMP_IO_WRITE32(pAd, offset, Addr0); | ||
1371 | offset += 4; | ||
1372 | RTMP_IO_WRITE32(pAd, offset, Addr1); | ||
1373 | } | ||
1374 | |||
1375 | /* | ||
1376 | ========================================================================== | ||
1377 | Description: | ||
1378 | |||
1379 | IRQL = DISPATCH_LEVEL | ||
1380 | |||
1381 | ========================================================================== | ||
1382 | */ | ||
1383 | void AsicEnableRDG(struct rt_rtmp_adapter *pAd) | ||
1384 | { | ||
1385 | TX_LINK_CFG_STRUC TxLinkCfg; | ||
1386 | u32 Data = 0; | ||
1387 | |||
1388 | RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); | ||
1389 | TxLinkCfg.field.TxRDGEn = 1; | ||
1390 | RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); | ||
1391 | |||
1392 | RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); | ||
1393 | Data &= 0xFFFFFF00; | ||
1394 | Data |= 0x80; | ||
1395 | RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); | ||
1396 | |||
1397 | /*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); */ | ||
1398 | } | ||
1399 | |||
1400 | /* | ||
1401 | ========================================================================== | ||
1402 | Description: | ||
1403 | |||
1404 | IRQL = DISPATCH_LEVEL | ||
1405 | |||
1406 | ========================================================================== | ||
1407 | */ | ||
1408 | void AsicDisableRDG(struct rt_rtmp_adapter *pAd) | ||
1409 | { | ||
1410 | TX_LINK_CFG_STRUC TxLinkCfg; | ||
1411 | u32 Data = 0; | ||
1412 | |||
1413 | RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); | ||
1414 | TxLinkCfg.field.TxRDGEn = 0; | ||
1415 | RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); | ||
1416 | |||
1417 | RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); | ||
1418 | |||
1419 | Data &= 0xFFFFFF00; | ||
1420 | /*Data |= 0x20; */ | ||
1421 | #ifndef WIFI_TEST | ||
1422 | /*if ( pAd->CommonCfg.bEnableTxBurst ) */ | ||
1423 | /* Data |= 0x60; // for performance issue not set the TXOP to 0 */ | ||
1424 | #endif | ||
1425 | if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE) | ||
1426 | && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE) | ||
1427 | ) { | ||
1428 | /* For CWC test, change txop from 0x30 to 0x20 in TxBurst mode */ | ||
1429 | if (pAd->CommonCfg.bEnableTxBurst) | ||
1430 | Data |= 0x20; | ||
1431 | } | ||
1432 | RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); | ||
1433 | } | ||
1434 | |||
1435 | /* | ||
1436 | ========================================================================== | ||
1437 | Description: | ||
1438 | |||
1439 | IRQL = PASSIVE_LEVEL | ||
1440 | IRQL = DISPATCH_LEVEL | ||
1441 | |||
1442 | ========================================================================== | ||
1443 | */ | ||
1444 | void AsicDisableSync(struct rt_rtmp_adapter *pAd) | ||
1445 | { | ||
1446 | BCN_TIME_CFG_STRUC csr; | ||
1447 | |||
1448 | DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n")); | ||
1449 | |||
1450 | /* 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect */ | ||
1451 | /* that NIC will never wakes up because TSF stops and no more */ | ||
1452 | /* TBTT interrupts */ | ||
1453 | pAd->TbttTickCount = 0; | ||
1454 | RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); | ||
1455 | csr.field.bBeaconGen = 0; | ||
1456 | csr.field.bTBTTEnable = 0; | ||
1457 | csr.field.TsfSyncMode = 0; | ||
1458 | csr.field.bTsfTicking = 0; | ||
1459 | RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); | ||
1460 | |||
1461 | } | ||
1462 | |||
1463 | /* | ||
1464 | ========================================================================== | ||
1465 | Description: | ||
1466 | |||
1467 | IRQL = DISPATCH_LEVEL | ||
1468 | |||
1469 | ========================================================================== | ||
1470 | */ | ||
1471 | void AsicEnableBssSync(struct rt_rtmp_adapter *pAd) | ||
1472 | { | ||
1473 | BCN_TIME_CFG_STRUC csr; | ||
1474 | |||
1475 | DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n")); | ||
1476 | |||
1477 | RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); | ||
1478 | /* RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, 0x00000000); */ | ||
1479 | { | ||
1480 | csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; /* ASIC register in units of 1/16 TU */ | ||
1481 | csr.field.bTsfTicking = 1; | ||
1482 | csr.field.TsfSyncMode = 1; /* sync TSF in INFRASTRUCTURE mode */ | ||
1483 | csr.field.bBeaconGen = 0; /* do NOT generate BEACON */ | ||
1484 | csr.field.bTBTTEnable = 1; | ||
1485 | } | ||
1486 | RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); | ||
1487 | } | ||
1488 | |||
1489 | /* | ||
1490 | ========================================================================== | ||
1491 | Description: | ||
1492 | Note: | ||
1493 | BEACON frame in shared memory should be built ok before this routine | ||
1494 | can be called. Otherwise, a garbage frame maybe transmitted out every | ||
1495 | Beacon period. | ||
1496 | |||
1497 | IRQL = DISPATCH_LEVEL | ||
1498 | |||
1499 | ========================================================================== | ||
1500 | */ | ||
1501 | void AsicEnableIbssSync(struct rt_rtmp_adapter *pAd) | ||
1502 | { | ||
1503 | BCN_TIME_CFG_STRUC csr9; | ||
1504 | u8 *ptr; | ||
1505 | u32 i; | ||
1506 | |||
1507 | DBGPRINT(RT_DEBUG_TRACE, | ||
1508 | ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", | ||
1509 | pAd->BeaconTxWI.MPDUtotalByteCount)); | ||
1510 | |||
1511 | RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word); | ||
1512 | csr9.field.bBeaconGen = 0; | ||
1513 | csr9.field.bTBTTEnable = 0; | ||
1514 | csr9.field.bTsfTicking = 0; | ||
1515 | RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word); | ||
1516 | |||
1517 | #ifdef RTMP_MAC_PCI | ||
1518 | /* move BEACON TXD and frame content to on-chip memory */ | ||
1519 | ptr = (u8 *)& pAd->BeaconTxWI; | ||
1520 | for (i = 0; i < TXWI_SIZE; i += 4) /* 16-byte TXWI field */ | ||
1521 | { | ||
1522 | u32 longptr = | ||
1523 | *ptr + (*(ptr + 1) << 8) + (*(ptr + 2) << 16) + | ||
1524 | (*(ptr + 3) << 24); | ||
1525 | RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr); | ||
1526 | ptr += 4; | ||
1527 | } | ||
1528 | |||
1529 | /* start right after the 16-byte TXWI field */ | ||
1530 | ptr = pAd->BeaconBuf; | ||
1531 | for (i = 0; i < pAd->BeaconTxWI.MPDUtotalByteCount; i += 4) { | ||
1532 | u32 longptr = | ||
1533 | *ptr + (*(ptr + 1) << 8) + (*(ptr + 2) << 16) + | ||
1534 | (*(ptr + 3) << 24); | ||
1535 | RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr); | ||
1536 | ptr += 4; | ||
1537 | } | ||
1538 | #endif /* RTMP_MAC_PCI // */ | ||
1539 | #ifdef RTMP_MAC_USB | ||
1540 | /* move BEACON TXD and frame content to on-chip memory */ | ||
1541 | ptr = (u8 *)& pAd->BeaconTxWI; | ||
1542 | for (i = 0; i < TXWI_SIZE; i += 2) /* 16-byte TXWI field */ | ||
1543 | { | ||
1544 | /*u32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); */ | ||
1545 | /*RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr); */ | ||
1546 | RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2); | ||
1547 | ptr += 2; | ||
1548 | } | ||
1549 | |||
1550 | /* start right after the 16-byte TXWI field */ | ||
1551 | ptr = pAd->BeaconBuf; | ||
1552 | for (i = 0; i < pAd->BeaconTxWI.MPDUtotalByteCount; i += 2) { | ||
1553 | /*u32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); */ | ||
1554 | /*RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr); */ | ||
1555 | RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2); | ||
1556 | ptr += 2; | ||
1557 | } | ||
1558 | #endif /* RTMP_MAC_USB // */ | ||
1559 | |||
1560 | /* */ | ||
1561 | /* For Wi-Fi faily generated beacons between participating stations. */ | ||
1562 | /* Set TBTT phase adaptive adjustment step to 8us (default 16us) */ | ||
1563 | /* don't change settings 2006-5- by Jerry */ | ||
1564 | /*RTMP_IO_WRITE32(pAd, TBTT_SYNC_CFG, 0x00001010); */ | ||
1565 | |||
1566 | /* start sending BEACON */ | ||
1567 | csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; /* ASIC register in units of 1/16 TU */ | ||
1568 | csr9.field.bTsfTicking = 1; | ||
1569 | csr9.field.TsfSyncMode = 2; /* sync TSF in IBSS mode */ | ||
1570 | csr9.field.bTBTTEnable = 1; | ||
1571 | csr9.field.bBeaconGen = 1; | ||
1572 | RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word); | ||
1573 | } | ||
1574 | |||
1575 | /* | ||
1576 | ========================================================================== | ||
1577 | Description: | ||
1578 | |||
1579 | IRQL = PASSIVE_LEVEL | ||
1580 | IRQL = DISPATCH_LEVEL | ||
1581 | |||
1582 | ========================================================================== | ||
1583 | */ | ||
1584 | void AsicSetEdcaParm(struct rt_rtmp_adapter *pAd, struct rt_edca_parm *pEdcaParm) | ||
1585 | { | ||
1586 | EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg; | ||
1587 | AC_TXOP_CSR0_STRUC csr0; | ||
1588 | AC_TXOP_CSR1_STRUC csr1; | ||
1589 | AIFSN_CSR_STRUC AifsnCsr; | ||
1590 | CWMIN_CSR_STRUC CwminCsr; | ||
1591 | CWMAX_CSR_STRUC CwmaxCsr; | ||
1592 | int i; | ||
1593 | |||
1594 | Ac0Cfg.word = 0; | ||
1595 | Ac1Cfg.word = 0; | ||
1596 | Ac2Cfg.word = 0; | ||
1597 | Ac3Cfg.word = 0; | ||
1598 | if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE)) { | ||
1599 | DBGPRINT(RT_DEBUG_TRACE, ("AsicSetEdcaParm\n")); | ||
1600 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED); | ||
1601 | for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) { | ||
1602 | if (pAd->MacTab.Content[i].ValidAsCLI | ||
1603 | || pAd->MacTab.Content[i].ValidAsApCli) | ||
1604 | CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab. | ||
1605 | Content[i], | ||
1606 | fCLIENT_STATUS_WMM_CAPABLE); | ||
1607 | } | ||
1608 | |||
1609 | /*======================================================== */ | ||
1610 | /* MAC Register has a copy . */ | ||
1611 | /*======================================================== */ | ||
1612 | /*#ifndef WIFI_TEST */ | ||
1613 | if (pAd->CommonCfg.bEnableTxBurst) { | ||
1614 | /* For CWC test, change txop from 0x30 to 0x20 in TxBurst mode */ | ||
1615 | Ac0Cfg.field.AcTxop = 0x20; /* Suggest by John for TxBurst in HT Mode */ | ||
1616 | } else | ||
1617 | Ac0Cfg.field.AcTxop = 0; /* QID_AC_BE */ | ||
1618 | /*#else */ | ||
1619 | /* Ac0Cfg.field.AcTxop = 0; // QID_AC_BE */ | ||
1620 | /*#endif */ | ||
1621 | Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS; | ||
1622 | Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS; | ||
1623 | Ac0Cfg.field.Aifsn = 2; | ||
1624 | RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word); | ||
1625 | |||
1626 | Ac1Cfg.field.AcTxop = 0; /* QID_AC_BK */ | ||
1627 | Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS; | ||
1628 | Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS; | ||
1629 | Ac1Cfg.field.Aifsn = 2; | ||
1630 | RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word); | ||
1631 | |||
1632 | if (pAd->CommonCfg.PhyMode == PHY_11B) { | ||
1633 | Ac2Cfg.field.AcTxop = 192; /* AC_VI: 192*32us ~= 6ms */ | ||
1634 | Ac3Cfg.field.AcTxop = 96; /* AC_VO: 96*32us ~= 3ms */ | ||
1635 | } else { | ||
1636 | Ac2Cfg.field.AcTxop = 96; /* AC_VI: 96*32us ~= 3ms */ | ||
1637 | Ac3Cfg.field.AcTxop = 48; /* AC_VO: 48*32us ~= 1.5ms */ | ||
1638 | } | ||
1639 | Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS; | ||
1640 | Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS; | ||
1641 | Ac2Cfg.field.Aifsn = 2; | ||
1642 | RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word); | ||
1643 | Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS; | ||
1644 | Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS; | ||
1645 | Ac3Cfg.field.Aifsn = 2; | ||
1646 | RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word); | ||
1647 | |||
1648 | /*======================================================== */ | ||
1649 | /* DMA Register has a copy too. */ | ||
1650 | /*======================================================== */ | ||
1651 | csr0.field.Ac0Txop = 0; /* QID_AC_BE */ | ||
1652 | csr0.field.Ac1Txop = 0; /* QID_AC_BK */ | ||
1653 | RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); | ||
1654 | if (pAd->CommonCfg.PhyMode == PHY_11B) { | ||
1655 | csr1.field.Ac2Txop = 192; /* AC_VI: 192*32us ~= 6ms */ | ||
1656 | csr1.field.Ac3Txop = 96; /* AC_VO: 96*32us ~= 3ms */ | ||
1657 | } else { | ||
1658 | csr1.field.Ac2Txop = 96; /* AC_VI: 96*32us ~= 3ms */ | ||
1659 | csr1.field.Ac3Txop = 48; /* AC_VO: 48*32us ~= 1.5ms */ | ||
1660 | } | ||
1661 | RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word); | ||
1662 | |||
1663 | CwminCsr.word = 0; | ||
1664 | CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS; | ||
1665 | CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS; | ||
1666 | CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS; | ||
1667 | CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS; | ||
1668 | RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word); | ||
1669 | |||
1670 | CwmaxCsr.word = 0; | ||
1671 | CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS; | ||
1672 | CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS; | ||
1673 | CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS; | ||
1674 | CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS; | ||
1675 | RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word); | ||
1676 | |||
1677 | RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222); | ||
1678 | |||
1679 | NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(struct rt_edca_parm)); | ||
1680 | } else { | ||
1681 | OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED); | ||
1682 | /*======================================================== */ | ||
1683 | /* MAC Register has a copy. */ | ||
1684 | /*======================================================== */ | ||
1685 | /* */ | ||
1686 | /* Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27 */ | ||
1687 | /* To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue. */ | ||
1688 | /* */ | ||
1689 | /*pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this */ | ||
1690 | |||
1691 | Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE]; | ||
1692 | Ac0Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BE]; | ||
1693 | Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE]; | ||
1694 | Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; /*+1; */ | ||
1695 | |||
1696 | Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK]; | ||
1697 | Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; /*+2; */ | ||
1698 | Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK]; | ||
1699 | Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; /*+1; */ | ||
1700 | |||
1701 | Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10; | ||
1702 | if (pAd->Antenna.field.TxPath == 1) { | ||
1703 | Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI] + 1; | ||
1704 | Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI] + 1; | ||
1705 | } else { | ||
1706 | Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI]; | ||
1707 | Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI]; | ||
1708 | } | ||
1709 | Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI] + 1; | ||
1710 | #ifdef RTMP_MAC_USB | ||
1711 | Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI] + 3; | ||
1712 | #endif /* RTMP_MAC_USB // */ | ||
1713 | |||
1714 | { | ||
1715 | /* Tuning for Wi-Fi WMM S06 */ | ||
1716 | if (pAd->CommonCfg.bWiFiTest && | ||
1717 | pEdcaParm->Aifsn[QID_AC_VI] == 10) | ||
1718 | Ac2Cfg.field.Aifsn -= 1; | ||
1719 | |||
1720 | /* Tuning for TGn Wi-Fi 5.2.32 */ | ||
1721 | /* STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta */ | ||
1722 | if (STA_TGN_WIFI_ON(pAd) && | ||
1723 | pEdcaParm->Aifsn[QID_AC_VI] == 10) { | ||
1724 | Ac0Cfg.field.Aifsn = 3; | ||
1725 | Ac2Cfg.field.AcTxop = 5; | ||
1726 | } | ||
1727 | #ifdef RT30xx | ||
1728 | if (pAd->RfIcType == RFIC_3020 | ||
1729 | || pAd->RfIcType == RFIC_2020) { | ||
1730 | /* Tuning for WiFi WMM S3-T07: connexant legacy sta ==> broadcom 11n sta. */ | ||
1731 | Ac2Cfg.field.Aifsn = 5; | ||
1732 | } | ||
1733 | #endif /* RT30xx // */ | ||
1734 | } | ||
1735 | |||
1736 | Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO]; | ||
1737 | Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO]; | ||
1738 | Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO]; | ||
1739 | Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO]; | ||
1740 | |||
1741 | /*#ifdef WIFI_TEST */ | ||
1742 | if (pAd->CommonCfg.bWiFiTest) { | ||
1743 | if (Ac3Cfg.field.AcTxop == 102) { | ||
1744 | Ac0Cfg.field.AcTxop = | ||
1745 | pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm-> | ||
1746 | Txop[QID_AC_BE] : 10; | ||
1747 | Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE] - 1; /* AIFSN must >= 1 */ | ||
1748 | Ac1Cfg.field.AcTxop = | ||
1749 | pEdcaParm->Txop[QID_AC_BK]; | ||
1750 | Ac1Cfg.field.Aifsn = | ||
1751 | pEdcaParm->Aifsn[QID_AC_BK]; | ||
1752 | Ac2Cfg.field.AcTxop = | ||
1753 | pEdcaParm->Txop[QID_AC_VI]; | ||
1754 | } /* End of if */ | ||
1755 | } | ||
1756 | /*#endif // WIFI_TEST // */ | ||
1757 | |||
1758 | RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word); | ||
1759 | RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word); | ||
1760 | RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word); | ||
1761 | RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word); | ||
1762 | |||
1763 | /*======================================================== */ | ||
1764 | /* DMA Register has a copy too. */ | ||
1765 | /*======================================================== */ | ||
1766 | csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop; | ||
1767 | csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop; | ||
1768 | RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); | ||
1769 | |||
1770 | csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop; | ||
1771 | csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop; | ||
1772 | RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word); | ||
1773 | |||
1774 | CwminCsr.word = 0; | ||
1775 | CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE]; | ||
1776 | CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK]; | ||
1777 | CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI]; | ||
1778 | CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; /*for TGn wifi test */ | ||
1779 | RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word); | ||
1780 | |||
1781 | CwmaxCsr.word = 0; | ||
1782 | CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE]; | ||
1783 | CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK]; | ||
1784 | CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI]; | ||
1785 | CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO]; | ||
1786 | RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word); | ||
1787 | |||
1788 | AifsnCsr.word = 0; | ||
1789 | AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; /*pEdcaParm->Aifsn[QID_AC_BE]; */ | ||
1790 | AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; /*pEdcaParm->Aifsn[QID_AC_BK]; */ | ||
1791 | AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; /*pEdcaParm->Aifsn[QID_AC_VI]; */ | ||
1792 | |||
1793 | { | ||
1794 | /* Tuning for Wi-Fi WMM S06 */ | ||
1795 | if (pAd->CommonCfg.bWiFiTest && | ||
1796 | pEdcaParm->Aifsn[QID_AC_VI] == 10) | ||
1797 | AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4; | ||
1798 | |||
1799 | /* Tuning for TGn Wi-Fi 5.2.32 */ | ||
1800 | /* STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta */ | ||
1801 | if (STA_TGN_WIFI_ON(pAd) && | ||
1802 | pEdcaParm->Aifsn[QID_AC_VI] == 10) { | ||
1803 | AifsnCsr.field.Aifsn0 = 3; | ||
1804 | AifsnCsr.field.Aifsn2 = 7; | ||
1805 | } | ||
1806 | |||
1807 | if (INFRA_ON(pAd)) | ||
1808 | CLIENT_STATUS_SET_FLAG(&pAd->MacTab. | ||
1809 | Content[BSSID_WCID], | ||
1810 | fCLIENT_STATUS_WMM_CAPABLE); | ||
1811 | } | ||
1812 | |||
1813 | { | ||
1814 | AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; /*pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test */ | ||
1815 | #ifdef RT30xx | ||
1816 | /* TODO: Shiang, this modification also suitable for RT3052/RT3050 ??? */ | ||
1817 | if (pAd->RfIcType == RFIC_3020 | ||
1818 | || pAd->RfIcType == RFIC_2020) { | ||
1819 | AifsnCsr.field.Aifsn2 = 0x2; /*pEdcaParm->Aifsn[QID_AC_VI]; //for WiFi WMM S4-T04. */ | ||
1820 | } | ||
1821 | #endif /* RT30xx // */ | ||
1822 | } | ||
1823 | RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word); | ||
1824 | |||
1825 | NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, | ||
1826 | sizeof(struct rt_edca_parm)); | ||
1827 | if (!ADHOC_ON(pAd)) { | ||
1828 | DBGPRINT(RT_DEBUG_TRACE, | ||
1829 | ("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", | ||
1830 | pEdcaParm->EdcaUpdateCount)); | ||
1831 | DBGPRINT(RT_DEBUG_TRACE, | ||
1832 | (" AC_BE %2d %2d %2d %4d %d\n", | ||
1833 | pEdcaParm->Aifsn[0], pEdcaParm->Cwmin[0], | ||
1834 | pEdcaParm->Cwmax[0], pEdcaParm->Txop[0] << 5, | ||
1835 | pEdcaParm->bACM[0])); | ||
1836 | DBGPRINT(RT_DEBUG_TRACE, | ||
1837 | (" AC_BK %2d %2d %2d %4d %d\n", | ||
1838 | pEdcaParm->Aifsn[1], pEdcaParm->Cwmin[1], | ||
1839 | pEdcaParm->Cwmax[1], pEdcaParm->Txop[1] << 5, | ||
1840 | pEdcaParm->bACM[1])); | ||
1841 | DBGPRINT(RT_DEBUG_TRACE, | ||
1842 | (" AC_VI %2d %2d %2d %4d %d\n", | ||
1843 | pEdcaParm->Aifsn[2], pEdcaParm->Cwmin[2], | ||
1844 | pEdcaParm->Cwmax[2], pEdcaParm->Txop[2] << 5, | ||
1845 | pEdcaParm->bACM[2])); | ||
1846 | DBGPRINT(RT_DEBUG_TRACE, | ||
1847 | (" AC_VO %2d %2d %2d %4d %d\n", | ||
1848 | pEdcaParm->Aifsn[3], pEdcaParm->Cwmin[3], | ||
1849 | pEdcaParm->Cwmax[3], pEdcaParm->Txop[3] << 5, | ||
1850 | pEdcaParm->bACM[3])); | ||
1851 | } | ||
1852 | } | ||
1853 | |||
1854 | } | ||
1855 | |||
1856 | /* | ||
1857 | ========================================================================== | ||
1858 | Description: | ||
1859 | |||
1860 | IRQL = PASSIVE_LEVEL | ||
1861 | IRQL = DISPATCH_LEVEL | ||
1862 | |||
1863 | ========================================================================== | ||
1864 | */ | ||
1865 | void AsicSetSlotTime(struct rt_rtmp_adapter *pAd, IN BOOLEAN bUseShortSlotTime) | ||
1866 | { | ||
1867 | unsigned long SlotTime; | ||
1868 | u32 RegValue = 0; | ||
1869 | |||
1870 | if (pAd->CommonCfg.Channel > 14) | ||
1871 | bUseShortSlotTime = TRUE; | ||
1872 | |||
1873 | if (bUseShortSlotTime | ||
1874 | && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED)) | ||
1875 | return; | ||
1876 | else if ((!bUseShortSlotTime) | ||
1877 | && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED))) | ||
1878 | return; | ||
1879 | |||
1880 | if (bUseShortSlotTime) | ||
1881 | OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); | ||
1882 | else | ||
1883 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); | ||
1884 | |||
1885 | SlotTime = (bUseShortSlotTime) ? 9 : 20; | ||
1886 | |||
1887 | { | ||
1888 | /* force using short SLOT time for FAE to demo performance when TxBurst is ON */ | ||
1889 | if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) | ||
1890 | && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))) | ||
1891 | || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) | ||
1892 | && (pAd->CommonCfg.BACapability.field.Policy == | ||
1893 | BA_NOTUSE)) | ||
1894 | ) { | ||
1895 | /* In this case, we will think it is doing Wi-Fi test */ | ||
1896 | /* And we will not set to short slot when bEnableTxBurst is TRUE. */ | ||
1897 | } else if (pAd->CommonCfg.bEnableTxBurst) { | ||
1898 | OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); | ||
1899 | SlotTime = 9; | ||
1900 | } | ||
1901 | } | ||
1902 | |||
1903 | /* */ | ||
1904 | /* For some reasons, always set it to short slot time. */ | ||
1905 | /* */ | ||
1906 | /* ToDo: Should consider capability with 11B */ | ||
1907 | /* */ | ||
1908 | { | ||
1909 | if (pAd->StaCfg.BssType == BSS_ADHOC) { | ||
1910 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); | ||
1911 | SlotTime = 20; | ||
1912 | } | ||
1913 | } | ||
1914 | |||
1915 | RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue); | ||
1916 | RegValue = RegValue & 0xFFFFFF00; | ||
1917 | |||
1918 | RegValue |= SlotTime; | ||
1919 | |||
1920 | RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue); | ||
1921 | } | ||
1922 | |||
1923 | /* | ||
1924 | ======================================================================== | ||
1925 | Description: | ||
1926 | Add Shared key information into ASIC. | ||
1927 | Update shared key, TxMic and RxMic to Asic Shared key table | ||
1928 | Update its cipherAlg to Asic Shared key Mode. | ||
1929 | |||
1930 | Return: | ||
1931 | ======================================================================== | ||
1932 | */ | ||
1933 | void AsicAddSharedKeyEntry(struct rt_rtmp_adapter *pAd, | ||
1934 | u8 BssIndex, | ||
1935 | u8 KeyIdx, | ||
1936 | u8 CipherAlg, | ||
1937 | u8 *pKey, u8 *pTxMic, u8 *pRxMic) | ||
1938 | { | ||
1939 | unsigned long offset; /*, csr0; */ | ||
1940 | SHAREDKEY_MODE_STRUC csr1; | ||
1941 | #ifdef RTMP_MAC_PCI | ||
1942 | int i; | ||
1943 | #endif /* RTMP_MAC_PCI // */ | ||
1944 | |||
1945 | DBGPRINT(RT_DEBUG_TRACE, | ||
1946 | ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex, | ||
1947 | KeyIdx)); | ||
1948 | /*============================================================================================ */ | ||
1949 | |||
1950 | DBGPRINT(RT_DEBUG_TRACE, | ||
1951 | ("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], | ||
1952 | BssIndex * 4 + KeyIdx)); | ||
1953 | DBGPRINT_RAW(RT_DEBUG_TRACE, | ||
1954 | (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", | ||
1955 | pKey[0], pKey[1], pKey[2], pKey[3], pKey[4], | ||
1956 | pKey[5], pKey[6], pKey[7], pKey[8], pKey[9], | ||
1957 | pKey[10], pKey[11], pKey[12], pKey[13], pKey[14], | ||
1958 | pKey[15])); | ||
1959 | if (pRxMic) { | ||
1960 | DBGPRINT_RAW(RT_DEBUG_TRACE, | ||
1961 | (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", | ||
1962 | pRxMic[0], pRxMic[1], pRxMic[2], pRxMic[3], | ||
1963 | pRxMic[4], pRxMic[5], pRxMic[6], pRxMic[7])); | ||
1964 | } | ||
1965 | if (pTxMic) { | ||
1966 | DBGPRINT_RAW(RT_DEBUG_TRACE, | ||
1967 | (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", | ||
1968 | pTxMic[0], pTxMic[1], pTxMic[2], pTxMic[3], | ||
1969 | pTxMic[4], pTxMic[5], pTxMic[6], pTxMic[7])); | ||
1970 | } | ||
1971 | /*============================================================================================ */ | ||
1972 | /* */ | ||
1973 | /* fill key material - key + TX MIC + RX MIC */ | ||
1974 | /* */ | ||
1975 | #ifdef RTMP_MAC_PCI | ||
1976 | offset = | ||
1977 | SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE; | ||
1978 | for (i = 0; i < MAX_LEN_OF_SHARE_KEY; i++) { | ||
1979 | RTMP_IO_WRITE8(pAd, offset + i, pKey[i]); | ||
1980 | } | ||
1981 | |||
1982 | offset += MAX_LEN_OF_SHARE_KEY; | ||
1983 | if (pTxMic) { | ||
1984 | for (i = 0; i < 8; i++) { | ||
1985 | RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]); | ||
1986 | } | ||
1987 | } | ||
1988 | |||
1989 | offset += 8; | ||
1990 | if (pRxMic) { | ||
1991 | for (i = 0; i < 8; i++) { | ||
1992 | RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]); | ||
1993 | } | ||
1994 | } | ||
1995 | #endif /* RTMP_MAC_PCI // */ | ||
1996 | #ifdef RTMP_MAC_USB | ||
1997 | { | ||
1998 | offset = | ||
1999 | SHARED_KEY_TABLE_BASE + (4 * BssIndex + | ||
2000 | KeyIdx) * HW_KEY_ENTRY_SIZE; | ||
2001 | RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY); | ||
2002 | |||
2003 | offset += MAX_LEN_OF_SHARE_KEY; | ||
2004 | if (pTxMic) { | ||
2005 | RTUSBMultiWrite(pAd, offset, pTxMic, 8); | ||
2006 | } | ||
2007 | |||
2008 | offset += 8; | ||
2009 | if (pRxMic) { | ||
2010 | RTUSBMultiWrite(pAd, offset, pRxMic, 8); | ||
2011 | } | ||
2012 | } | ||
2013 | #endif /* RTMP_MAC_USB // */ | ||
2014 | |||
2015 | /* */ | ||
2016 | /* Update cipher algorithm. WSTA always use BSS0 */ | ||
2017 | /* */ | ||
2018 | RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), | ||
2019 | &csr1.word); | ||
2020 | DBGPRINT(RT_DEBUG_TRACE, | ||
2021 | ("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", | ||
2022 | BssIndex, KeyIdx, csr1.word)); | ||
2023 | if ((BssIndex % 2) == 0) { | ||
2024 | if (KeyIdx == 0) | ||
2025 | csr1.field.Bss0Key0CipherAlg = CipherAlg; | ||
2026 | else if (KeyIdx == 1) | ||
2027 | csr1.field.Bss0Key1CipherAlg = CipherAlg; | ||
2028 | else if (KeyIdx == 2) | ||
2029 | csr1.field.Bss0Key2CipherAlg = CipherAlg; | ||
2030 | else | ||
2031 | csr1.field.Bss0Key3CipherAlg = CipherAlg; | ||
2032 | } else { | ||
2033 | if (KeyIdx == 0) | ||
2034 | csr1.field.Bss1Key0CipherAlg = CipherAlg; | ||
2035 | else if (KeyIdx == 1) | ||
2036 | csr1.field.Bss1Key1CipherAlg = CipherAlg; | ||
2037 | else if (KeyIdx == 2) | ||
2038 | csr1.field.Bss1Key2CipherAlg = CipherAlg; | ||
2039 | else | ||
2040 | csr1.field.Bss1Key3CipherAlg = CipherAlg; | ||
2041 | } | ||
2042 | DBGPRINT(RT_DEBUG_TRACE, | ||
2043 | ("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", | ||
2044 | BssIndex, csr1.word)); | ||
2045 | RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), | ||
2046 | csr1.word); | ||
2047 | |||
2048 | } | ||
2049 | |||
2050 | /* IRQL = DISPATCH_LEVEL */ | ||
2051 | void AsicRemoveSharedKeyEntry(struct rt_rtmp_adapter *pAd, | ||
2052 | u8 BssIndex, u8 KeyIdx) | ||
2053 | { | ||
2054 | /*unsigned long SecCsr0; */ | ||
2055 | SHAREDKEY_MODE_STRUC csr1; | ||
2056 | |||
2057 | DBGPRINT(RT_DEBUG_TRACE, | ||
2058 | ("AsicRemoveSharedKeyEntry: #%d \n", BssIndex * 4 + KeyIdx)); | ||
2059 | |||
2060 | RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), | ||
2061 | &csr1.word); | ||
2062 | if ((BssIndex % 2) == 0) { | ||
2063 | if (KeyIdx == 0) | ||
2064 | csr1.field.Bss0Key0CipherAlg = 0; | ||
2065 | else if (KeyIdx == 1) | ||
2066 | csr1.field.Bss0Key1CipherAlg = 0; | ||
2067 | else if (KeyIdx == 2) | ||
2068 | csr1.field.Bss0Key2CipherAlg = 0; | ||
2069 | else | ||
2070 | csr1.field.Bss0Key3CipherAlg = 0; | ||
2071 | } else { | ||
2072 | if (KeyIdx == 0) | ||
2073 | csr1.field.Bss1Key0CipherAlg = 0; | ||
2074 | else if (KeyIdx == 1) | ||
2075 | csr1.field.Bss1Key1CipherAlg = 0; | ||
2076 | else if (KeyIdx == 2) | ||
2077 | csr1.field.Bss1Key2CipherAlg = 0; | ||
2078 | else | ||
2079 | csr1.field.Bss1Key3CipherAlg = 0; | ||
2080 | } | ||
2081 | DBGPRINT(RT_DEBUG_TRACE, | ||
2082 | ("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", | ||
2083 | BssIndex, csr1.word)); | ||
2084 | RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), | ||
2085 | csr1.word); | ||
2086 | ASSERT(BssIndex < 4); | ||
2087 | ASSERT(KeyIdx < 4); | ||
2088 | |||
2089 | } | ||
2090 | |||
2091 | void AsicUpdateWCIDAttribute(struct rt_rtmp_adapter *pAd, | ||
2092 | u16 WCID, | ||
2093 | u8 BssIndex, | ||
2094 | u8 CipherAlg, | ||
2095 | IN BOOLEAN bUsePairewiseKeyTable) | ||
2096 | { | ||
2097 | unsigned long WCIDAttri = 0, offset; | ||
2098 | |||
2099 | /* */ | ||
2100 | /* Update WCID attribute. */ | ||
2101 | /* Only TxKey could update WCID attribute. */ | ||
2102 | /* */ | ||
2103 | offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE); | ||
2104 | WCIDAttri = | ||
2105 | (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable); | ||
2106 | RTMP_IO_WRITE32(pAd, offset, WCIDAttri); | ||
2107 | } | ||
2108 | |||
2109 | void AsicUpdateWCIDIVEIV(struct rt_rtmp_adapter *pAd, | ||
2110 | u16 WCID, unsigned long uIV, unsigned long uEIV) | ||
2111 | { | ||
2112 | unsigned long offset; | ||
2113 | |||
2114 | offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE); | ||
2115 | |||
2116 | RTMP_IO_WRITE32(pAd, offset, uIV); | ||
2117 | RTMP_IO_WRITE32(pAd, offset + 4, uEIV); | ||
2118 | } | ||
2119 | |||
2120 | void AsicUpdateRxWCIDTable(struct rt_rtmp_adapter *pAd, | ||
2121 | u16 WCID, u8 *pAddr) | ||
2122 | { | ||
2123 | unsigned long offset; | ||
2124 | unsigned long Addr; | ||
2125 | |||
2126 | offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE); | ||
2127 | Addr = pAddr[0] + (pAddr[1] << 8) + (pAddr[2] << 16) + (pAddr[3] << 24); | ||
2128 | RTMP_IO_WRITE32(pAd, offset, Addr); | ||
2129 | Addr = pAddr[4] + (pAddr[5] << 8); | ||
2130 | RTMP_IO_WRITE32(pAd, offset + 4, Addr); | ||
2131 | } | ||
2132 | |||
2133 | /* | ||
2134 | ======================================================================== | ||
2135 | |||
2136 | Routine Description: | ||
2137 | Set Cipher Key, Cipher algorithm, IV/EIV to Asic | ||
2138 | |||
2139 | Arguments: | ||
2140 | pAd Pointer to our adapter | ||
2141 | WCID WCID Entry number. | ||
2142 | BssIndex BSSID index, station or none multiple BSSID support | ||
2143 | this value should be 0. | ||
2144 | KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled | ||
2145 | pCipherKey Pointer to Cipher Key. | ||
2146 | bUsePairewiseKeyTable TRUE means saved the key in SharedKey table, | ||
2147 | otherwise PairewiseKey table | ||
2148 | bTxKey This is the transmit key if enabled. | ||
2149 | |||
2150 | Return Value: | ||
2151 | None | ||
2152 | |||
2153 | Note: | ||
2154 | This routine will set the relative key stuff to Asic including WCID attribute, | ||
2155 | Cipher Key, Cipher algorithm and IV/EIV. | ||
2156 | |||
2157 | IV/EIV will be update if this CipherKey is the transmission key because | ||
2158 | ASIC will base on IV's KeyID value to select Cipher Key. | ||
2159 | |||
2160 | If bTxKey sets to FALSE, this is not the TX key, but it could be | ||
2161 | RX key | ||
2162 | |||
2163 | For AP mode bTxKey must be always set to TRUE. | ||
2164 | ======================================================================== | ||
2165 | */ | ||
2166 | void AsicAddKeyEntry(struct rt_rtmp_adapter *pAd, | ||
2167 | u16 WCID, | ||
2168 | u8 BssIndex, | ||
2169 | u8 KeyIdx, | ||
2170 | struct rt_cipher_key *pCipherKey, | ||
2171 | IN BOOLEAN bUsePairewiseKeyTable, IN BOOLEAN bTxKey) | ||
2172 | { | ||
2173 | unsigned long offset; | ||
2174 | /* unsigned long WCIDAttri = 0; */ | ||
2175 | u8 IV4 = 0; | ||
2176 | u8 *pKey = pCipherKey->Key; | ||
2177 | /* unsigned long KeyLen = pCipherKey->KeyLen; */ | ||
2178 | u8 *pTxMic = pCipherKey->TxMic; | ||
2179 | u8 *pRxMic = pCipherKey->RxMic; | ||
2180 | u8 *pTxtsc = pCipherKey->TxTsc; | ||
2181 | u8 CipherAlg = pCipherKey->CipherAlg; | ||
2182 | SHAREDKEY_MODE_STRUC csr1; | ||
2183 | #ifdef RTMP_MAC_PCI | ||
2184 | u8 i; | ||
2185 | #endif /* RTMP_MAC_PCI // */ | ||
2186 | |||
2187 | /* ASSERT(KeyLen <= MAX_LEN_OF_PEER_KEY); */ | ||
2188 | |||
2189 | DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n")); | ||
2190 | /* */ | ||
2191 | /* 1.) decide key table offset */ | ||
2192 | /* */ | ||
2193 | if (bUsePairewiseKeyTable) | ||
2194 | offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE); | ||
2195 | else | ||
2196 | offset = | ||
2197 | SHARED_KEY_TABLE_BASE + (4 * BssIndex + | ||
2198 | KeyIdx) * HW_KEY_ENTRY_SIZE; | ||
2199 | |||
2200 | /* */ | ||
2201 | /* 2.) Set Key to Asic */ | ||
2202 | /* */ | ||
2203 | /*for (i = 0; i < KeyLen; i++) */ | ||
2204 | #ifdef RTMP_MAC_PCI | ||
2205 | for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++) { | ||
2206 | RTMP_IO_WRITE8(pAd, offset + i, pKey[i]); | ||
2207 | } | ||
2208 | offset += MAX_LEN_OF_PEER_KEY; | ||
2209 | |||
2210 | /* */ | ||
2211 | /* 3.) Set MIC key if available */ | ||
2212 | /* */ | ||
2213 | if (pTxMic) { | ||
2214 | for (i = 0; i < 8; i++) { | ||
2215 | RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]); | ||
2216 | } | ||
2217 | } | ||
2218 | offset += LEN_TKIP_TXMICK; | ||
2219 | |||
2220 | if (pRxMic) { | ||
2221 | for (i = 0; i < 8; i++) { | ||
2222 | RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]); | ||
2223 | } | ||
2224 | } | ||
2225 | #endif /* RTMP_MAC_PCI // */ | ||
2226 | #ifdef RTMP_MAC_USB | ||
2227 | RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY); | ||
2228 | offset += MAX_LEN_OF_PEER_KEY; | ||
2229 | |||
2230 | /* */ | ||
2231 | /* 3.) Set MIC key if available */ | ||
2232 | /* */ | ||
2233 | if (pTxMic) { | ||
2234 | RTUSBMultiWrite(pAd, offset, pTxMic, 8); | ||
2235 | } | ||
2236 | offset += LEN_TKIP_TXMICK; | ||
2237 | |||
2238 | if (pRxMic) { | ||
2239 | RTUSBMultiWrite(pAd, offset, pRxMic, 8); | ||
2240 | } | ||
2241 | #endif /* RTMP_MAC_USB // */ | ||
2242 | |||
2243 | /* */ | ||
2244 | /* 4.) Modify IV/EIV if needs */ | ||
2245 | /* This will force Asic to use this key ID by setting IV. */ | ||
2246 | /* */ | ||
2247 | if (bTxKey) { | ||
2248 | #ifdef RTMP_MAC_PCI | ||
2249 | offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE); | ||
2250 | /* */ | ||
2251 | /* Write IV */ | ||
2252 | /* */ | ||
2253 | RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]); | ||
2254 | RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f)); | ||
2255 | RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]); | ||
2256 | |||
2257 | IV4 = (KeyIdx << 6); | ||
2258 | if ((CipherAlg == CIPHER_TKIP) | ||
2259 | || (CipherAlg == CIPHER_TKIP_NO_MIC) | ||
2260 | || (CipherAlg == CIPHER_AES)) | ||
2261 | IV4 |= 0x20; /* turn on extension bit means EIV existence */ | ||
2262 | |||
2263 | RTMP_IO_WRITE8(pAd, offset + 3, IV4); | ||
2264 | |||
2265 | /* */ | ||
2266 | /* Write EIV */ | ||
2267 | /* */ | ||
2268 | offset += 4; | ||
2269 | for (i = 0; i < 4; i++) { | ||
2270 | RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]); | ||
2271 | } | ||
2272 | #endif /* RTMP_MAC_PCI // */ | ||
2273 | #ifdef RTMP_MAC_USB | ||
2274 | u32 tmpVal; | ||
2275 | |||
2276 | /* */ | ||
2277 | /* Write IV */ | ||
2278 | /* */ | ||
2279 | IV4 = (KeyIdx << 6); | ||
2280 | if ((CipherAlg == CIPHER_TKIP) | ||
2281 | || (CipherAlg == CIPHER_TKIP_NO_MIC) | ||
2282 | || (CipherAlg == CIPHER_AES)) | ||
2283 | IV4 |= 0x20; /* turn on extension bit means EIV existence */ | ||
2284 | |||
2285 | tmpVal = | ||
2286 | pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + | ||
2287 | (pTxtsc[0] << 16) + (IV4 << 24); | ||
2288 | RTMP_IO_WRITE32(pAd, offset, tmpVal); | ||
2289 | |||
2290 | /* */ | ||
2291 | /* Write EIV */ | ||
2292 | /* */ | ||
2293 | offset += 4; | ||
2294 | RTMP_IO_WRITE32(pAd, offset, *(u32 *)& pCipherKey->TxTsc[2]); | ||
2295 | #endif /* RTMP_MAC_USB // */ | ||
2296 | |||
2297 | AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, | ||
2298 | bUsePairewiseKeyTable); | ||
2299 | } | ||
2300 | |||
2301 | if (!bUsePairewiseKeyTable) { | ||
2302 | /* */ | ||
2303 | /* Only update the shared key security mode */ | ||
2304 | /* */ | ||
2305 | RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), | ||
2306 | &csr1.word); | ||
2307 | if ((BssIndex % 2) == 0) { | ||
2308 | if (KeyIdx == 0) | ||
2309 | csr1.field.Bss0Key0CipherAlg = CipherAlg; | ||
2310 | else if (KeyIdx == 1) | ||
2311 | csr1.field.Bss0Key1CipherAlg = CipherAlg; | ||
2312 | else if (KeyIdx == 2) | ||
2313 | csr1.field.Bss0Key2CipherAlg = CipherAlg; | ||
2314 | else | ||
2315 | csr1.field.Bss0Key3CipherAlg = CipherAlg; | ||
2316 | } else { | ||
2317 | if (KeyIdx == 0) | ||
2318 | csr1.field.Bss1Key0CipherAlg = CipherAlg; | ||
2319 | else if (KeyIdx == 1) | ||
2320 | csr1.field.Bss1Key1CipherAlg = CipherAlg; | ||
2321 | else if (KeyIdx == 2) | ||
2322 | csr1.field.Bss1Key2CipherAlg = CipherAlg; | ||
2323 | else | ||
2324 | csr1.field.Bss1Key3CipherAlg = CipherAlg; | ||
2325 | } | ||
2326 | RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), | ||
2327 | csr1.word); | ||
2328 | } | ||
2329 | |||
2330 | DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n")); | ||
2331 | } | ||
2332 | |||
2333 | /* | ||
2334 | ======================================================================== | ||
2335 | Description: | ||
2336 | Add Pair-wise key material into ASIC. | ||
2337 | Update pairwise key, TxMic and RxMic to Asic Pair-wise key table | ||
2338 | |||
2339 | Return: | ||
2340 | ======================================================================== | ||
2341 | */ | ||
2342 | void AsicAddPairwiseKeyEntry(struct rt_rtmp_adapter *pAd, | ||
2343 | u8 *pAddr, | ||
2344 | u8 WCID, struct rt_cipher_key *pCipherKey) | ||
2345 | { | ||
2346 | int i; | ||
2347 | unsigned long offset; | ||
2348 | u8 *pKey = pCipherKey->Key; | ||
2349 | u8 *pTxMic = pCipherKey->TxMic; | ||
2350 | u8 *pRxMic = pCipherKey->RxMic; | ||
2351 | #ifdef DBG | ||
2352 | u8 CipherAlg = pCipherKey->CipherAlg; | ||
2353 | #endif /* DBG // */ | ||
2354 | |||
2355 | /* EKEY */ | ||
2356 | offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE); | ||
2357 | #ifdef RTMP_MAC_PCI | ||
2358 | for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++) { | ||
2359 | RTMP_IO_WRITE8(pAd, offset + i, pKey[i]); | ||
2360 | } | ||
2361 | #endif /* RTMP_MAC_PCI // */ | ||
2362 | #ifdef RTMP_MAC_USB | ||
2363 | RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY); | ||
2364 | #endif /* RTMP_MAC_USB // */ | ||
2365 | for (i = 0; i < MAX_LEN_OF_PEER_KEY; i += 4) { | ||
2366 | u32 Value; | ||
2367 | RTMP_IO_READ32(pAd, offset + i, &Value); | ||
2368 | } | ||
2369 | |||
2370 | offset += MAX_LEN_OF_PEER_KEY; | ||
2371 | |||
2372 | /* MIC KEY */ | ||
2373 | if (pTxMic) { | ||
2374 | #ifdef RTMP_MAC_PCI | ||
2375 | for (i = 0; i < 8; i++) { | ||
2376 | RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]); | ||
2377 | } | ||
2378 | #endif /* RTMP_MAC_PCI // */ | ||
2379 | #ifdef RTMP_MAC_USB | ||
2380 | RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8); | ||
2381 | #endif /* RTMP_MAC_USB // */ | ||
2382 | } | ||
2383 | offset += 8; | ||
2384 | if (pRxMic) { | ||
2385 | #ifdef RTMP_MAC_PCI | ||
2386 | for (i = 0; i < 8; i++) { | ||
2387 | RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]); | ||
2388 | } | ||
2389 | #endif /* RTMP_MAC_PCI // */ | ||
2390 | #ifdef RTMP_MAC_USB | ||
2391 | RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8); | ||
2392 | #endif /* RTMP_MAC_USB // */ | ||
2393 | } | ||
2394 | |||
2395 | DBGPRINT(RT_DEBUG_TRACE, | ||
2396 | ("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n", WCID, | ||
2397 | CipherName[CipherAlg])); | ||
2398 | DBGPRINT(RT_DEBUG_TRACE, | ||
2399 | (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", | ||
2400 | pKey[0], pKey[1], pKey[2], pKey[3], pKey[4], pKey[5], | ||
2401 | pKey[6], pKey[7], pKey[8], pKey[9], pKey[10], pKey[11], | ||
2402 | pKey[12], pKey[13], pKey[14], pKey[15])); | ||
2403 | if (pRxMic) { | ||
2404 | DBGPRINT(RT_DEBUG_TRACE, | ||
2405 | (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", | ||
2406 | pRxMic[0], pRxMic[1], pRxMic[2], pRxMic[3], | ||
2407 | pRxMic[4], pRxMic[5], pRxMic[6], pRxMic[7])); | ||
2408 | } | ||
2409 | if (pTxMic) { | ||
2410 | DBGPRINT(RT_DEBUG_TRACE, | ||
2411 | (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", | ||
2412 | pTxMic[0], pTxMic[1], pTxMic[2], pTxMic[3], | ||
2413 | pTxMic[4], pTxMic[5], pTxMic[6], pTxMic[7])); | ||
2414 | } | ||
2415 | } | ||
2416 | |||
2417 | /* | ||
2418 | ======================================================================== | ||
2419 | Description: | ||
2420 | Remove Pair-wise key material from ASIC. | ||
2421 | |||
2422 | Return: | ||
2423 | ======================================================================== | ||
2424 | */ | ||
2425 | void AsicRemovePairwiseKeyEntry(struct rt_rtmp_adapter *pAd, | ||
2426 | u8 BssIdx, u8 Wcid) | ||
2427 | { | ||
2428 | unsigned long WCIDAttri; | ||
2429 | u16 offset; | ||
2430 | |||
2431 | /* re-set the entry's WCID attribute as OPEN-NONE. */ | ||
2432 | offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE); | ||
2433 | WCIDAttri = (BssIdx << 4) | PAIRWISEKEYTABLE; | ||
2434 | RTMP_IO_WRITE32(pAd, offset, WCIDAttri); | ||
2435 | } | ||
2436 | |||
2437 | BOOLEAN AsicSendCommandToMcu(struct rt_rtmp_adapter *pAd, | ||
2438 | u8 Command, | ||
2439 | u8 Token, u8 Arg0, u8 Arg1) | ||
2440 | { | ||
2441 | |||
2442 | if (pAd->chipOps.sendCommandToMcu) | ||
2443 | pAd->chipOps.sendCommandToMcu(pAd, Command, Token, Arg0, Arg1); | ||
2444 | |||
2445 | return TRUE; | ||
2446 | } | ||
2447 | |||
2448 | void AsicSetRxAnt(struct rt_rtmp_adapter *pAd, u8 Ant) | ||
2449 | { | ||
2450 | #ifdef RT30xx | ||
2451 | /* RT3572 ATE need not to do this. */ | ||
2452 | RT30xxSetRxAnt(pAd, Ant); | ||
2453 | #endif /* RT30xx // */ | ||
2454 | } | ||
2455 | |||
2456 | void AsicTurnOffRFClk(struct rt_rtmp_adapter *pAd, u8 Channel) | ||
2457 | { | ||
2458 | if (pAd->chipOps.AsicRfTurnOff) { | ||
2459 | pAd->chipOps.AsicRfTurnOff(pAd); | ||
2460 | } else { | ||
2461 | /* RF R2 bit 18 = 0 */ | ||
2462 | u32 R1 = 0, R2 = 0, R3 = 0; | ||
2463 | u8 index; | ||
2464 | struct rt_rtmp_rf_regs *RFRegTable; | ||
2465 | |||
2466 | RFRegTable = RF2850RegTable; | ||
2467 | |||
2468 | switch (pAd->RfIcType) { | ||
2469 | case RFIC_2820: | ||
2470 | case RFIC_2850: | ||
2471 | case RFIC_2720: | ||
2472 | case RFIC_2750: | ||
2473 | |||
2474 | for (index = 0; index < NUM_OF_2850_CHNL; index++) { | ||
2475 | if (Channel == RFRegTable[index].Channel) { | ||
2476 | R1 = RFRegTable[index].R1 & 0xffffdfff; | ||
2477 | R2 = RFRegTable[index].R2 & 0xfffbffff; | ||
2478 | R3 = RFRegTable[index].R3 & 0xfff3ffff; | ||
2479 | |||
2480 | RTMP_RF_IO_WRITE32(pAd, R1); | ||
2481 | RTMP_RF_IO_WRITE32(pAd, R2); | ||
2482 | |||
2483 | /* Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0. */ | ||
2484 | /* Set RF R2 bit18=0, R3 bit[18:19]=0 */ | ||
2485 | /*if (pAd->StaCfg.bRadio == FALSE) */ | ||
2486 | if (1) { | ||
2487 | RTMP_RF_IO_WRITE32(pAd, R3); | ||
2488 | |||
2489 | DBGPRINT(RT_DEBUG_TRACE, | ||
2490 | ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n", | ||
2491 | Channel, | ||
2492 | pAd->RfIcType, R2, | ||
2493 | R3)); | ||
2494 | } else | ||
2495 | DBGPRINT(RT_DEBUG_TRACE, | ||
2496 | ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n", | ||
2497 | Channel, | ||
2498 | pAd->RfIcType, R2)); | ||
2499 | break; | ||
2500 | } | ||
2501 | } | ||
2502 | break; | ||
2503 | |||
2504 | default: | ||
2505 | break; | ||
2506 | } | ||
2507 | } | ||
2508 | } | ||
2509 | |||
2510 | void AsicTurnOnRFClk(struct rt_rtmp_adapter *pAd, u8 Channel) | ||
2511 | { | ||
2512 | /* RF R2 bit 18 = 0 */ | ||
2513 | u32 R1 = 0, R2 = 0, R3 = 0; | ||
2514 | u8 index; | ||
2515 | struct rt_rtmp_rf_regs *RFRegTable; | ||
2516 | |||
2517 | #ifdef PCIE_PS_SUPPORT | ||
2518 | /* The RF programming sequence is difference between 3xxx and 2xxx */ | ||
2519 | if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))) { | ||
2520 | return; | ||
2521 | } | ||
2522 | #endif /* PCIE_PS_SUPPORT // */ | ||
2523 | |||
2524 | RFRegTable = RF2850RegTable; | ||
2525 | |||
2526 | switch (pAd->RfIcType) { | ||
2527 | case RFIC_2820: | ||
2528 | case RFIC_2850: | ||
2529 | case RFIC_2720: | ||
2530 | case RFIC_2750: | ||
2531 | |||
2532 | for (index = 0; index < NUM_OF_2850_CHNL; index++) { | ||
2533 | if (Channel == RFRegTable[index].Channel) { | ||
2534 | R3 = pAd->LatchRfRegs.R3; | ||
2535 | R3 &= 0xfff3ffff; | ||
2536 | R3 |= 0x00080000; | ||
2537 | RTMP_RF_IO_WRITE32(pAd, R3); | ||
2538 | |||
2539 | R1 = RFRegTable[index].R1; | ||
2540 | RTMP_RF_IO_WRITE32(pAd, R1); | ||
2541 | |||
2542 | R2 = RFRegTable[index].R2; | ||
2543 | if (pAd->Antenna.field.TxPath == 1) { | ||
2544 | R2 |= 0x4000; /* If TXpath is 1, bit 14 = 1; */ | ||
2545 | } | ||
2546 | |||
2547 | if (pAd->Antenna.field.RxPath == 2) { | ||
2548 | R2 |= 0x40; /* write 1 to off Rxpath. */ | ||
2549 | } else if (pAd->Antenna.field.RxPath == 1) { | ||
2550 | R2 |= 0x20040; /* write 1 to off RxPath */ | ||
2551 | } | ||
2552 | RTMP_RF_IO_WRITE32(pAd, R2); | ||
2553 | |||
2554 | break; | ||
2555 | } | ||
2556 | } | ||
2557 | break; | ||
2558 | |||
2559 | default: | ||
2560 | break; | ||
2561 | } | ||
2562 | |||
2563 | DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n", | ||
2564 | Channel, pAd->RfIcType, R2)); | ||
2565 | } | ||
diff --git a/drivers/staging/rt2860/common/cmm_cfg.c b/drivers/staging/rt2860/common/cmm_cfg.c deleted file mode 100644 index 727f7992925..00000000000 --- a/drivers/staging/rt2860/common/cmm_cfg.c +++ /dev/null | |||
@@ -1,258 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | |||
27 | Module Name: | ||
28 | cmm_cfg.c | ||
29 | |||
30 | Abstract: | ||
31 | Ralink WiFi Driver configuration related subroutines | ||
32 | |||
33 | Revision History: | ||
34 | Who When What | ||
35 | --------- ---------- ---------------------------------------------- | ||
36 | */ | ||
37 | |||
38 | #include "../rt_config.h" | ||
39 | |||
40 | char *GetPhyMode(int Mode) | ||
41 | { | ||
42 | switch (Mode) { | ||
43 | case MODE_CCK: | ||
44 | return "CCK"; | ||
45 | |||
46 | case MODE_OFDM: | ||
47 | return "OFDM"; | ||
48 | case MODE_HTMIX: | ||
49 | return "HTMIX"; | ||
50 | |||
51 | case MODE_HTGREENFIELD: | ||
52 | return "GREEN"; | ||
53 | default: | ||
54 | return "N/A"; | ||
55 | } | ||
56 | } | ||
57 | |||
58 | char *GetBW(int BW) | ||
59 | { | ||
60 | switch (BW) { | ||
61 | case BW_10: | ||
62 | return "10M"; | ||
63 | |||
64 | case BW_20: | ||
65 | return "20M"; | ||
66 | case BW_40: | ||
67 | return "40M"; | ||
68 | default: | ||
69 | return "N/A"; | ||
70 | } | ||
71 | } | ||
72 | |||
73 | /* | ||
74 | ========================================================================== | ||
75 | Description: | ||
76 | Set Country Region to pAd->CommonCfg.CountryRegion. | ||
77 | This command will not work, if the field of CountryRegion in eeprom is programmed. | ||
78 | |||
79 | Return: | ||
80 | TRUE if all parameters are OK, FALSE otherwise | ||
81 | ========================================================================== | ||
82 | */ | ||
83 | int RT_CfgSetCountryRegion(struct rt_rtmp_adapter *pAd, char *arg, int band) | ||
84 | { | ||
85 | long region, regionMax; | ||
86 | u8 *pCountryRegion; | ||
87 | |||
88 | region = simple_strtol(arg, 0, 10); | ||
89 | |||
90 | if (band == BAND_24G) { | ||
91 | pCountryRegion = &pAd->CommonCfg.CountryRegion; | ||
92 | regionMax = REGION_MAXIMUM_BG_BAND; | ||
93 | } else { | ||
94 | pCountryRegion = &pAd->CommonCfg.CountryRegionForABand; | ||
95 | regionMax = REGION_MAXIMUM_A_BAND; | ||
96 | } | ||
97 | |||
98 | /* TODO: Is it neccesay for following check??? */ | ||
99 | /* Country can be set only when EEPROM not programmed */ | ||
100 | if (*pCountryRegion & 0x80) { | ||
101 | DBGPRINT(RT_DEBUG_ERROR, | ||
102 | ("CfgSetCountryRegion():CountryRegion in eeprom was programmed\n")); | ||
103 | return FALSE; | ||
104 | } | ||
105 | |||
106 | if ((region >= 0) && (region <= REGION_MAXIMUM_BG_BAND)) { | ||
107 | *pCountryRegion = (u8)region; | ||
108 | } else if ((region == REGION_31_BG_BAND) && (band == BAND_24G)) { | ||
109 | *pCountryRegion = (u8)region; | ||
110 | } else { | ||
111 | DBGPRINT(RT_DEBUG_ERROR, | ||
112 | ("CfgSetCountryRegion():region(%ld) out of range!\n", | ||
113 | region)); | ||
114 | return FALSE; | ||
115 | } | ||
116 | |||
117 | return TRUE; | ||
118 | |||
119 | } | ||
120 | |||
121 | /* | ||
122 | ========================================================================== | ||
123 | Description: | ||
124 | Set Wireless Mode | ||
125 | Return: | ||
126 | TRUE if all parameters are OK, FALSE otherwise | ||
127 | ========================================================================== | ||
128 | */ | ||
129 | int RT_CfgSetWirelessMode(struct rt_rtmp_adapter *pAd, char *arg) | ||
130 | { | ||
131 | int MaxPhyMode = PHY_11G; | ||
132 | long WirelessMode; | ||
133 | |||
134 | MaxPhyMode = PHY_11N_5G; | ||
135 | |||
136 | WirelessMode = simple_strtol(arg, 0, 10); | ||
137 | if (WirelessMode <= MaxPhyMode) { | ||
138 | pAd->CommonCfg.PhyMode = WirelessMode; | ||
139 | return TRUE; | ||
140 | } | ||
141 | |||
142 | return FALSE; | ||
143 | |||
144 | } | ||
145 | |||
146 | int RT_CfgSetShortSlot(struct rt_rtmp_adapter *pAd, char *arg) | ||
147 | { | ||
148 | long ShortSlot; | ||
149 | |||
150 | ShortSlot = simple_strtol(arg, 0, 10); | ||
151 | |||
152 | if (ShortSlot == 1) | ||
153 | pAd->CommonCfg.bUseShortSlotTime = TRUE; | ||
154 | else if (ShortSlot == 0) | ||
155 | pAd->CommonCfg.bUseShortSlotTime = FALSE; | ||
156 | else | ||
157 | return FALSE; /*Invalid argument */ | ||
158 | |||
159 | return TRUE; | ||
160 | } | ||
161 | |||
162 | /* | ||
163 | ========================================================================== | ||
164 | Description: | ||
165 | Set WEP KEY base on KeyIdx | ||
166 | Return: | ||
167 | TRUE if all parameters are OK, FALSE otherwise | ||
168 | ========================================================================== | ||
169 | */ | ||
170 | int RT_CfgSetWepKey(struct rt_rtmp_adapter *pAd, | ||
171 | char *keyString, | ||
172 | struct rt_cipher_key *pSharedKey, int keyIdx) | ||
173 | { | ||
174 | int KeyLen; | ||
175 | int i; | ||
176 | u8 CipherAlg = CIPHER_NONE; | ||
177 | BOOLEAN bKeyIsHex = FALSE; | ||
178 | |||
179 | /* TODO: Shall we do memset for the original key info?? */ | ||
180 | memset(pSharedKey, 0, sizeof(struct rt_cipher_key)); | ||
181 | KeyLen = strlen(keyString); | ||
182 | switch (KeyLen) { | ||
183 | case 5: /*wep 40 Ascii type */ | ||
184 | case 13: /*wep 104 Ascii type */ | ||
185 | bKeyIsHex = FALSE; | ||
186 | pSharedKey->KeyLen = KeyLen; | ||
187 | NdisMoveMemory(pSharedKey->Key, keyString, KeyLen); | ||
188 | break; | ||
189 | |||
190 | case 10: /*wep 40 Hex type */ | ||
191 | case 26: /*wep 104 Hex type */ | ||
192 | for (i = 0; i < KeyLen; i++) { | ||
193 | if (!isxdigit(*(keyString + i))) | ||
194 | return FALSE; /*Not Hex value; */ | ||
195 | } | ||
196 | bKeyIsHex = TRUE; | ||
197 | pSharedKey->KeyLen = KeyLen / 2; | ||
198 | AtoH(keyString, pSharedKey->Key, pSharedKey->KeyLen); | ||
199 | break; | ||
200 | |||
201 | default: /*Invalid argument */ | ||
202 | DBGPRINT(RT_DEBUG_TRACE, | ||
203 | ("RT_CfgSetWepKey(keyIdx=%d):Invalid argument (arg=%s)\n", | ||
204 | keyIdx, keyString)); | ||
205 | return FALSE; | ||
206 | } | ||
207 | |||
208 | pSharedKey->CipherAlg = ((KeyLen % 5) ? CIPHER_WEP128 : CIPHER_WEP64); | ||
209 | DBGPRINT(RT_DEBUG_TRACE, | ||
210 | ("RT_CfgSetWepKey:(KeyIdx=%d,type=%s, Alg=%s)\n", keyIdx, | ||
211 | (bKeyIsHex == FALSE ? "Ascii" : "Hex"), | ||
212 | CipherName[CipherAlg])); | ||
213 | |||
214 | return TRUE; | ||
215 | } | ||
216 | |||
217 | /* | ||
218 | ========================================================================== | ||
219 | Description: | ||
220 | Set WPA PSK key | ||
221 | |||
222 | Arguments: | ||
223 | pAdapter Pointer to our adapter | ||
224 | keyString WPA pre-shared key string | ||
225 | pHashStr String used for password hash function | ||
226 | hashStrLen Length of the hash string | ||
227 | pPMKBuf Output buffer of WPAPSK key | ||
228 | |||
229 | Return: | ||
230 | TRUE if all parameters are OK, FALSE otherwise | ||
231 | ========================================================================== | ||
232 | */ | ||
233 | int RT_CfgSetWPAPSKKey(struct rt_rtmp_adapter *pAd, | ||
234 | char *keyString, | ||
235 | u8 * pHashStr, | ||
236 | int hashStrLen, u8 *pPMKBuf) | ||
237 | { | ||
238 | int keyLen; | ||
239 | u8 keyMaterial[40]; | ||
240 | |||
241 | keyLen = strlen(keyString); | ||
242 | if ((keyLen < 8) || (keyLen > 64)) { | ||
243 | DBGPRINT(RT_DEBUG_TRACE, | ||
244 | ("WPAPSK Key length(%d) error, required 8 ~ 64 characters!(keyStr=%s)\n", | ||
245 | keyLen, keyString)); | ||
246 | return FALSE; | ||
247 | } | ||
248 | |||
249 | memset(pPMKBuf, 0, 32); | ||
250 | if (keyLen == 64) { | ||
251 | AtoH(keyString, pPMKBuf, 32); | ||
252 | } else { | ||
253 | PasswordHash(keyString, pHashStr, hashStrLen, keyMaterial); | ||
254 | NdisMoveMemory(pPMKBuf, keyMaterial, 32); | ||
255 | } | ||
256 | |||
257 | return TRUE; | ||
258 | } | ||
diff --git a/drivers/staging/rt2860/common/cmm_data.c b/drivers/staging/rt2860/common/cmm_data.c deleted file mode 100644 index 33799e1449a..00000000000 --- a/drivers/staging/rt2860/common/cmm_data.c +++ /dev/null | |||
@@ -1,2361 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | */ | ||
27 | |||
28 | #include "../rt_config.h" | ||
29 | |||
30 | u8 SNAP_802_1H[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; | ||
31 | u8 SNAP_BRIDGE_TUNNEL[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; | ||
32 | |||
33 | /* Add Cisco Aironet SNAP heade for CCX2 support */ | ||
34 | u8 SNAP_AIRONET[] = { 0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00 }; | ||
35 | u8 CKIP_LLC_SNAP[] = { 0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02 }; | ||
36 | u8 EAPOL_LLC_SNAP[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e }; | ||
37 | u8 EAPOL[] = { 0x88, 0x8e }; | ||
38 | u8 TPID[] = { 0x81, 0x00 }; /* VLAN related */ | ||
39 | |||
40 | u8 IPX[] = { 0x81, 0x37 }; | ||
41 | u8 APPLE_TALK[] = { 0x80, 0xf3 }; | ||
42 | |||
43 | u8 RateIdToPlcpSignal[12] = { | ||
44 | 0, /* RATE_1 */ 1, /* RATE_2 */ 2, /* RATE_5_5 */ 3, /* RATE_11 *//* see BBP spec */ | ||
45 | 11, /* RATE_6 */ 15, /* RATE_9 */ 10, /* RATE_12 */ 14, /* RATE_18 *//* see IEEE802.11a-1999 p.14 */ | ||
46 | 9, /* RATE_24 */ 13, /* RATE_36 */ 8, /* RATE_48 */ 12 /* RATE_54 */ | ||
47 | }; /* see IEEE802.11a-1999 p.14 */ | ||
48 | |||
49 | u8 OfdmSignalToRateId[16] = { | ||
50 | RATE_54, RATE_54, RATE_54, RATE_54, /* OFDM PLCP Signal = 0, 1, 2, 3 respectively */ | ||
51 | RATE_54, RATE_54, RATE_54, RATE_54, /* OFDM PLCP Signal = 4, 5, 6, 7 respectively */ | ||
52 | RATE_48, RATE_24, RATE_12, RATE_6, /* OFDM PLCP Signal = 8, 9, 10, 11 respectively */ | ||
53 | RATE_54, RATE_36, RATE_18, RATE_9, /* OFDM PLCP Signal = 12, 13, 14, 15 respectively */ | ||
54 | }; | ||
55 | |||
56 | u8 OfdmRateToRxwiMCS[12] = { | ||
57 | 0, 0, 0, 0, | ||
58 | 0, 1, 2, 3, /* OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 */ | ||
59 | 4, 5, 6, 7, /* OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 */ | ||
60 | }; | ||
61 | |||
62 | u8 RxwiMCSToOfdmRate[12] = { | ||
63 | RATE_6, RATE_9, RATE_12, RATE_18, | ||
64 | RATE_24, RATE_36, RATE_48, RATE_54, /* OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 */ | ||
65 | 4, 5, 6, 7, /* OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 */ | ||
66 | }; | ||
67 | |||
68 | char *MCSToMbps[] = | ||
69 | { "1Mbps", "2Mbps", "5.5Mbps", "11Mbps", "06Mbps", "09Mbps", "12Mbps", | ||
70 | "18Mbps", "24Mbps", "36Mbps", "48Mbps", "54Mbps", "MM-0", "MM-1", "MM-2", "MM-3", | ||
71 | "MM-4", "MM-5", "MM-6", "MM-7", "MM-8", "MM-9", "MM-10", "MM-11", "MM-12", "MM-13", | ||
72 | "MM-14", "MM-15", "MM-32", "ee1", "ee2", "ee3" }; | ||
73 | |||
74 | u8 default_cwmin[] = | ||
75 | { CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS - 1, CW_MIN_IN_BITS - 2 }; | ||
76 | /*u8 default_cwmax[]={CW_MAX_IN_BITS, CW_MAX_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1}; */ | ||
77 | u8 default_sta_aifsn[] = { 3, 7, 2, 2 }; | ||
78 | |||
79 | u8 MapUserPriorityToAccessCategory[8] = | ||
80 | { QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI, | ||
81 | QID_AC_VO, QID_AC_VO }; | ||
82 | |||
83 | /* | ||
84 | ======================================================================== | ||
85 | |||
86 | Routine Description: | ||
87 | API for MLME to transmit management frame to AP (BSS Mode) | ||
88 | or station (IBSS Mode) | ||
89 | |||
90 | Arguments: | ||
91 | pAd Pointer to our adapter | ||
92 | pData Pointer to the outgoing 802.11 frame | ||
93 | Length Size of outgoing management frame | ||
94 | |||
95 | Return Value: | ||
96 | NDIS_STATUS_FAILURE | ||
97 | NDIS_STATUS_PENDING | ||
98 | NDIS_STATUS_SUCCESS | ||
99 | |||
100 | IRQL = PASSIVE_LEVEL | ||
101 | IRQL = DISPATCH_LEVEL | ||
102 | |||
103 | Note: | ||
104 | |||
105 | ======================================================================== | ||
106 | */ | ||
107 | int MiniportMMRequest(struct rt_rtmp_adapter *pAd, | ||
108 | u8 QueIdx, u8 *pData, u32 Length) | ||
109 | { | ||
110 | void *pPacket; | ||
111 | int Status = NDIS_STATUS_SUCCESS; | ||
112 | unsigned long FreeNum; | ||
113 | u8 rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; /*RTMP_HW_HDR_LEN]; */ | ||
114 | #ifdef RTMP_MAC_PCI | ||
115 | unsigned long IrqFlags = 0; | ||
116 | u8 IrqState; | ||
117 | #endif /* RTMP_MAC_PCI // */ | ||
118 | BOOLEAN bUseDataQ = FALSE; | ||
119 | int retryCnt = 0; | ||
120 | |||
121 | ASSERT(Length <= MGMT_DMA_BUFFER_SIZE); | ||
122 | |||
123 | if ((QueIdx & MGMT_USE_QUEUE_FLAG) == MGMT_USE_QUEUE_FLAG) { | ||
124 | bUseDataQ = TRUE; | ||
125 | QueIdx &= (~MGMT_USE_QUEUE_FLAG); | ||
126 | } | ||
127 | #ifdef RTMP_MAC_PCI | ||
128 | /* 2860C use Tx Ring */ | ||
129 | IrqState = pAd->irq_disabled; | ||
130 | if (pAd->MACVersion == 0x28600100) { | ||
131 | QueIdx = (bUseDataQ == TRUE ? QueIdx : 3); | ||
132 | bUseDataQ = TRUE; | ||
133 | } | ||
134 | if (bUseDataQ && (!IrqState)) | ||
135 | RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); | ||
136 | #endif /* RTMP_MAC_PCI // */ | ||
137 | |||
138 | do { | ||
139 | /* Reset is in progress, stop immediately */ | ||
140 | if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || | ||
141 | RTMP_TEST_FLAG(pAd, | ||
142 | fRTMP_ADAPTER_HALT_IN_PROGRESS | | ||
143 | fRTMP_ADAPTER_NIC_NOT_EXIST) | ||
144 | || !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) { | ||
145 | Status = NDIS_STATUS_FAILURE; | ||
146 | break; | ||
147 | } | ||
148 | /* Check Free priority queue */ | ||
149 | /* Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing. */ | ||
150 | #ifdef RTMP_MAC_PCI | ||
151 | if (bUseDataQ) { | ||
152 | retryCnt = MAX_DATAMM_RETRY; | ||
153 | /* free Tx(QueIdx) resources */ | ||
154 | RTMPFreeTXDUponTxDmaDone(pAd, QueIdx); | ||
155 | FreeNum = GET_TXRING_FREENO(pAd, QueIdx); | ||
156 | } else | ||
157 | #endif /* RTMP_MAC_PCI // */ | ||
158 | { | ||
159 | FreeNum = GET_MGMTRING_FREENO(pAd); | ||
160 | } | ||
161 | |||
162 | if ((FreeNum > 0)) { | ||
163 | /* We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870 */ | ||
164 | NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE)); | ||
165 | Status = | ||
166 | RTMPAllocateNdisPacket(pAd, &pPacket, | ||
167 | (u8 *)& rtmpHwHdr, | ||
168 | (TXINFO_SIZE + TXWI_SIZE), | ||
169 | pData, Length); | ||
170 | if (Status != NDIS_STATUS_SUCCESS) { | ||
171 | DBGPRINT(RT_DEBUG_WARN, | ||
172 | ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n")); | ||
173 | break; | ||
174 | } | ||
175 | /*pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; */ | ||
176 | /*pAd->CommonCfg.MlmeRate = RATE_2; */ | ||
177 | |||
178 | #ifdef RTMP_MAC_PCI | ||
179 | if (bUseDataQ) { | ||
180 | Status = | ||
181 | MlmeDataHardTransmit(pAd, QueIdx, pPacket); | ||
182 | retryCnt--; | ||
183 | } else | ||
184 | #endif /* RTMP_MAC_PCI // */ | ||
185 | Status = MlmeHardTransmit(pAd, QueIdx, pPacket); | ||
186 | if (Status == NDIS_STATUS_SUCCESS) | ||
187 | retryCnt = 0; | ||
188 | else | ||
189 | RTMPFreeNdisPacket(pAd, pPacket); | ||
190 | } else { | ||
191 | pAd->RalinkCounters.MgmtRingFullCount++; | ||
192 | #ifdef RTMP_MAC_PCI | ||
193 | if (bUseDataQ) { | ||
194 | retryCnt--; | ||
195 | DBGPRINT(RT_DEBUG_TRACE, | ||
196 | ("retryCnt %d\n", retryCnt)); | ||
197 | if (retryCnt == 0) { | ||
198 | DBGPRINT(RT_DEBUG_ERROR, | ||
199 | ("Qidx(%d), not enough space in DataRing, MgmtRingFullCount=%ld!\n", | ||
200 | QueIdx, | ||
201 | pAd->RalinkCounters. | ||
202 | MgmtRingFullCount)); | ||
203 | } | ||
204 | } | ||
205 | #endif /* RTMP_MAC_PCI // */ | ||
206 | DBGPRINT(RT_DEBUG_ERROR, | ||
207 | ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n", | ||
208 | QueIdx, | ||
209 | pAd->RalinkCounters.MgmtRingFullCount)); | ||
210 | } | ||
211 | } while (retryCnt > 0); | ||
212 | |||
213 | #ifdef RTMP_MAC_PCI | ||
214 | if (bUseDataQ && (!IrqState)) | ||
215 | RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); | ||
216 | #endif /* RTMP_MAC_PCI // */ | ||
217 | |||
218 | return Status; | ||
219 | } | ||
220 | |||
221 | /* | ||
222 | ======================================================================== | ||
223 | |||
224 | Routine Description: | ||
225 | Copy frame from waiting queue into relative ring buffer and set | ||
226 | appropriate ASIC register to kick hardware transmit function | ||
227 | |||
228 | Arguments: | ||
229 | pAd Pointer to our adapter | ||
230 | pBuffer Pointer to memory of outgoing frame | ||
231 | Length Size of outgoing management frame | ||
232 | |||
233 | Return Value: | ||
234 | NDIS_STATUS_FAILURE | ||
235 | NDIS_STATUS_PENDING | ||
236 | NDIS_STATUS_SUCCESS | ||
237 | |||
238 | IRQL = PASSIVE_LEVEL | ||
239 | IRQL = DISPATCH_LEVEL | ||
240 | |||
241 | Note: | ||
242 | |||
243 | ======================================================================== | ||
244 | */ | ||
245 | int MlmeHardTransmit(struct rt_rtmp_adapter *pAd, | ||
246 | u8 QueIdx, void *pPacket) | ||
247 | { | ||
248 | struct rt_packet_info PacketInfo; | ||
249 | u8 *pSrcBufVA; | ||
250 | u32 SrcBufLen; | ||
251 | struct rt_header_802_11 * pHeader_802_11; | ||
252 | |||
253 | if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) | ||
254 | ) { | ||
255 | return NDIS_STATUS_FAILURE; | ||
256 | } | ||
257 | |||
258 | RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); | ||
259 | if (pSrcBufVA == NULL) | ||
260 | return NDIS_STATUS_FAILURE; | ||
261 | |||
262 | pHeader_802_11 = (struct rt_header_802_11 *) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); | ||
263 | |||
264 | #ifdef RTMP_MAC_PCI | ||
265 | if (pAd->MACVersion == 0x28600100) | ||
266 | return MlmeHardTransmitTxRing(pAd, QueIdx, pPacket); | ||
267 | else | ||
268 | #endif /* RTMP_MAC_PCI // */ | ||
269 | return MlmeHardTransmitMgmtRing(pAd, QueIdx, pPacket); | ||
270 | |||
271 | } | ||
272 | |||
273 | int MlmeHardTransmitMgmtRing(struct rt_rtmp_adapter *pAd, | ||
274 | u8 QueIdx, void *pPacket) | ||
275 | { | ||
276 | struct rt_packet_info PacketInfo; | ||
277 | u8 *pSrcBufVA; | ||
278 | u32 SrcBufLen; | ||
279 | struct rt_header_802_11 * pHeader_802_11; | ||
280 | BOOLEAN bAckRequired, bInsertTimestamp; | ||
281 | u8 MlmeRate; | ||
282 | struct rt_txwi * pFirstTxWI; | ||
283 | struct rt_mac_table_entry *pMacEntry = NULL; | ||
284 | u8 PID; | ||
285 | |||
286 | RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); | ||
287 | |||
288 | /* Make sure MGMT ring resource won't be used by other threads */ | ||
289 | RTMP_SEM_LOCK(&pAd->MgmtRingLock); | ||
290 | if (pSrcBufVA == NULL) { | ||
291 | /* The buffer shouldn't be NULL */ | ||
292 | RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); | ||
293 | return NDIS_STATUS_FAILURE; | ||
294 | } | ||
295 | |||
296 | { | ||
297 | /* outgoing frame always wakeup PHY to prevent frame lost */ | ||
298 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) | ||
299 | AsicForceWakeup(pAd, TRUE); | ||
300 | } | ||
301 | |||
302 | pFirstTxWI = (struct rt_txwi *) (pSrcBufVA + TXINFO_SIZE); | ||
303 | pHeader_802_11 = (struct rt_header_802_11 *) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); /*TXWI_SIZE); */ | ||
304 | |||
305 | if (pHeader_802_11->Addr1[0] & 0x01) { | ||
306 | MlmeRate = pAd->CommonCfg.BasicMlmeRate; | ||
307 | } else { | ||
308 | MlmeRate = pAd->CommonCfg.MlmeRate; | ||
309 | } | ||
310 | |||
311 | /* Verify Mlme rate for a / g bands. */ | ||
312 | if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) /* 11A band */ | ||
313 | MlmeRate = RATE_6; | ||
314 | |||
315 | if ((pHeader_802_11->FC.Type == BTYPE_DATA) && | ||
316 | (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) { | ||
317 | pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); | ||
318 | } | ||
319 | |||
320 | { | ||
321 | /* Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode. */ | ||
322 | if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED | ||
323 | || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) { | ||
324 | if (pAd->LatchRfRegs.Channel > 14) | ||
325 | pAd->CommonCfg.MlmeTransmit.field.MODE = 1; | ||
326 | else | ||
327 | pAd->CommonCfg.MlmeTransmit.field.MODE = 0; | ||
328 | } | ||
329 | } | ||
330 | |||
331 | /* */ | ||
332 | /* Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE) */ | ||
333 | /* Snice it's been set to 0 while on MgtMacHeaderInit */ | ||
334 | /* By the way this will cause frame to be send on PWR_SAVE failed. */ | ||
335 | /* */ | ||
336 | pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; /* (pAd->StaCfg.Psm == PWR_SAVE); */ | ||
337 | |||
338 | /* */ | ||
339 | /* In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame */ | ||
340 | /* Data-Null packets also pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD */ | ||
341 | /* if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL)) */ | ||
342 | { | ||
343 | if ((pHeader_802_11->FC.SubType == SUBTYPE_ACTION) || | ||
344 | ((pHeader_802_11->FC.Type == BTYPE_DATA) && | ||
345 | ((pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL) || | ||
346 | (pHeader_802_11->FC.SubType == SUBTYPE_NULL_FUNC)))) { | ||
347 | if (pAd->StaCfg.Psm == PWR_SAVE) | ||
348 | pHeader_802_11->FC.PwrMgmt = PWR_SAVE; | ||
349 | else | ||
350 | pHeader_802_11->FC.PwrMgmt = | ||
351 | pAd->CommonCfg.bAPSDForcePowerSave; | ||
352 | } | ||
353 | } | ||
354 | |||
355 | bInsertTimestamp = FALSE; | ||
356 | if (pHeader_802_11->FC.Type == BTYPE_CNTL) /* must be PS-POLL */ | ||
357 | { | ||
358 | /*Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue. */ | ||
359 | if ((pAd->OpMode == OPMODE_STA) | ||
360 | && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL)) { | ||
361 | pHeader_802_11->FC.PwrMgmt = PWR_SAVE; | ||
362 | } | ||
363 | bAckRequired = FALSE; | ||
364 | } else /* BTYPE_MGMT or BTYPE_DATA(must be NULL frame) */ | ||
365 | { | ||
366 | /*pAd->Sequence++; */ | ||
367 | /*pHeader_802_11->Sequence = pAd->Sequence; */ | ||
368 | |||
369 | if (pHeader_802_11->Addr1[0] & 0x01) /* MULTICAST, BROADCAST */ | ||
370 | { | ||
371 | bAckRequired = FALSE; | ||
372 | pHeader_802_11->Duration = 0; | ||
373 | } else { | ||
374 | bAckRequired = TRUE; | ||
375 | pHeader_802_11->Duration = | ||
376 | RTMPCalcDuration(pAd, MlmeRate, 14); | ||
377 | if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP) | ||
378 | && (pHeader_802_11->FC.Type == BTYPE_MGMT)) { | ||
379 | bInsertTimestamp = TRUE; | ||
380 | bAckRequired = FALSE; /* Disable ACK to prevent retry 0x1f for Probe Response */ | ||
381 | } else | ||
382 | if ((pHeader_802_11->FC.SubType == | ||
383 | SUBTYPE_PROBE_REQ) | ||
384 | && (pHeader_802_11->FC.Type == BTYPE_MGMT)) { | ||
385 | bAckRequired = FALSE; /* Disable ACK to prevent retry 0x1f for Probe Request */ | ||
386 | } | ||
387 | } | ||
388 | } | ||
389 | |||
390 | pHeader_802_11->Sequence = pAd->Sequence++; | ||
391 | if (pAd->Sequence > 0xfff) | ||
392 | pAd->Sequence = 0; | ||
393 | |||
394 | /* Before radar detection done, mgmt frame can not be sent but probe req */ | ||
395 | /* Because we need to use probe req to trigger driver to send probe req in passive scan */ | ||
396 | if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ) | ||
397 | && (pAd->CommonCfg.bIEEE80211H == 1) | ||
398 | && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)) { | ||
399 | DBGPRINT(RT_DEBUG_ERROR, | ||
400 | ("MlmeHardTransmit --> radar detect not in normal mode!\n")); | ||
401 | /* if (!IrqState) */ | ||
402 | RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); | ||
403 | return (NDIS_STATUS_FAILURE); | ||
404 | } | ||
405 | |||
406 | /* */ | ||
407 | /* fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET */ | ||
408 | /* should always has only one physical buffer, and the whole frame size equals */ | ||
409 | /* to the first scatter buffer size */ | ||
410 | /* */ | ||
411 | |||
412 | /* Initialize TX Descriptor */ | ||
413 | /* For inter-frame gap, the number is for this frame and next frame */ | ||
414 | /* For MLME rate, we will fix as 2Mb to match other vendor's implement */ | ||
415 | /* pAd->CommonCfg.MlmeTransmit.field.MODE = 1; */ | ||
416 | |||
417 | /* management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not. */ | ||
418 | PID = PID_MGMT; | ||
419 | |||
420 | if (pMacEntry == NULL) { | ||
421 | RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, | ||
422 | FALSE, bAckRequired, FALSE, 0, RESERVED_WCID, | ||
423 | (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID, 0, | ||
424 | (u8)pAd->CommonCfg.MlmeTransmit.field.MCS, | ||
425 | IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit); | ||
426 | } else { | ||
427 | /* dont use low rate to send QoS Null data frame */ | ||
428 | RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, | ||
429 | bInsertTimestamp, FALSE, bAckRequired, FALSE, | ||
430 | 0, pMacEntry->Aid, | ||
431 | (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), | ||
432 | pMacEntry->MaxHTPhyMode.field.MCS, 0, | ||
433 | (u8)pMacEntry->MaxHTPhyMode.field.MCS, | ||
434 | IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode); | ||
435 | } | ||
436 | |||
437 | /* Now do hardware-depened kick out. */ | ||
438 | HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen); | ||
439 | |||
440 | /* Make sure to release MGMT ring resource */ | ||
441 | /* if (!IrqState) */ | ||
442 | RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); | ||
443 | return NDIS_STATUS_SUCCESS; | ||
444 | } | ||
445 | |||
446 | /******************************************************************************** | ||
447 | |||
448 | New DeQueue Procedures. | ||
449 | |||
450 | ********************************************************************************/ | ||
451 | |||
452 | #define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \ | ||
453 | do{ \ | ||
454 | if (bIntContext == FALSE) \ | ||
455 | RTMP_IRQ_LOCK((lock), IrqFlags); \ | ||
456 | }while(0) | ||
457 | |||
458 | #define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \ | ||
459 | do{ \ | ||
460 | if (bIntContext == FALSE) \ | ||
461 | RTMP_IRQ_UNLOCK((lock), IrqFlags); \ | ||
462 | }while(0) | ||
463 | |||
464 | /* | ||
465 | ======================================================================== | ||
466 | Tx Path design algorithm: | ||
467 | Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal), | ||
468 | Specific Packet Type. Following show the classification rule and policy for each kinds of packets. | ||
469 | Classification Rule=> | ||
470 | Multicast: (*addr1 & 0x01) == 0x01 | ||
471 | Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc. | ||
472 | 11N Rate : If peer support HT | ||
473 | (1).AMPDU -- If TXBA is negotiated. | ||
474 | (2).AMSDU -- If AMSDU is capable for both peer and ourself. | ||
475 | *). AMSDU can embedded in a AMPDU, but now we didn't support it. | ||
476 | (3).Normal -- Other packets which send as 11n rate. | ||
477 | |||
478 | B/G Rate : If peer is b/g only. | ||
479 | (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6 | ||
480 | (2).Normal -- Other packets which send as b/g rate. | ||
481 | Fragment: | ||
482 | The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment. | ||
483 | |||
484 | Classified Packet Handle Rule=> | ||
485 | Multicast: | ||
486 | No ACK, //pTxBlk->bAckRequired = FALSE; | ||
487 | No WMM, //pTxBlk->bWMM = FALSE; | ||
488 | No piggyback, //pTxBlk->bPiggyBack = FALSE; | ||
489 | Force LowRate, //pTxBlk->bForceLowRate = TRUE; | ||
490 | Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use | ||
491 | the same policy to handle it. | ||
492 | Force LowRate, //pTxBlk->bForceLowRate = TRUE; | ||
493 | |||
494 | 11N Rate : | ||
495 | No piggyback, //pTxBlk->bPiggyBack = FALSE; | ||
496 | |||
497 | (1).AMSDU | ||
498 | pTxBlk->bWMM = TRUE; | ||
499 | (2).AMPDU | ||
500 | pTxBlk->bWMM = TRUE; | ||
501 | (3).Normal | ||
502 | |||
503 | B/G Rate : | ||
504 | (1).ARALINK | ||
505 | |||
506 | (2).Normal | ||
507 | ======================================================================== | ||
508 | */ | ||
509 | static u8 TxPktClassification(struct rt_rtmp_adapter *pAd, void *pPacket) | ||
510 | { | ||
511 | u8 TxFrameType = TX_UNKOWN_FRAME; | ||
512 | u8 Wcid; | ||
513 | struct rt_mac_table_entry *pMacEntry = NULL; | ||
514 | BOOLEAN bHTRate = FALSE; | ||
515 | |||
516 | Wcid = RTMP_GET_PACKET_WCID(pPacket); | ||
517 | if (Wcid == MCAST_WCID) { /* Handle for RA is Broadcast/Multicast Address. */ | ||
518 | return TX_MCAST_FRAME; | ||
519 | } | ||
520 | /* Handle for unicast packets */ | ||
521 | pMacEntry = &pAd->MacTab.Content[Wcid]; | ||
522 | if (RTMP_GET_PACKET_LOWRATE(pPacket)) { /* It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame */ | ||
523 | TxFrameType = TX_LEGACY_FRAME; | ||
524 | } else if (IS_HT_RATE(pMacEntry)) { /* it's a 11n capable packet */ | ||
525 | |||
526 | /* Depends on HTPhyMode to check if the peer support the HTRate transmission. */ | ||
527 | /* Currently didn't support A-MSDU embedded in A-MPDU */ | ||
528 | bHTRate = TRUE; | ||
529 | if (RTMP_GET_PACKET_MOREDATA(pPacket) | ||
530 | || (pMacEntry->PsMode == PWR_SAVE)) | ||
531 | TxFrameType = TX_LEGACY_FRAME; | ||
532 | else if ((pMacEntry-> | ||
533 | TXBAbitmap & (1 << (RTMP_GET_PACKET_UP(pPacket)))) != | ||
534 | 0) | ||
535 | return TX_AMPDU_FRAME; | ||
536 | else if (CLIENT_STATUS_TEST_FLAG | ||
537 | (pMacEntry, fCLIENT_STATUS_AMSDU_INUSED)) | ||
538 | return TX_AMSDU_FRAME; | ||
539 | else | ||
540 | TxFrameType = TX_LEGACY_FRAME; | ||
541 | } else { /* it's a legacy b/g packet. */ | ||
542 | if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) && (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)))) { /* if peer support Ralink Aggregation, we use it. */ | ||
543 | TxFrameType = TX_RALINK_FRAME; | ||
544 | } else { | ||
545 | TxFrameType = TX_LEGACY_FRAME; | ||
546 | } | ||
547 | } | ||
548 | |||
549 | /* Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU. */ | ||
550 | if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) | ||
551 | && (TxFrameType == TX_LEGACY_FRAME)) | ||
552 | TxFrameType = TX_FRAG_FRAME; | ||
553 | |||
554 | return TxFrameType; | ||
555 | } | ||
556 | |||
557 | BOOLEAN RTMP_FillTxBlkInfo(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk) | ||
558 | { | ||
559 | struct rt_packet_info PacketInfo; | ||
560 | void *pPacket; | ||
561 | struct rt_mac_table_entry *pMacEntry = NULL; | ||
562 | |||
563 | pPacket = pTxBlk->pPacket; | ||
564 | RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, | ||
565 | &pTxBlk->SrcBufLen); | ||
566 | |||
567 | pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket); | ||
568 | pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket); | ||
569 | pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket); | ||
570 | pTxBlk->FrameGap = IFS_HTTXOP; /* ASIC determine Frame Gap */ | ||
571 | |||
572 | if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket)) | ||
573 | TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame); | ||
574 | else | ||
575 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame); | ||
576 | |||
577 | /* Default to clear this flag */ | ||
578 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS); | ||
579 | |||
580 | if (pTxBlk->Wcid == MCAST_WCID) { | ||
581 | pTxBlk->pMacEntry = NULL; | ||
582 | { | ||
583 | pTxBlk->pTransmit = | ||
584 | &pAd->MacTab.Content[MCAST_WCID].HTPhyMode; | ||
585 | } | ||
586 | |||
587 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); /* AckRequired = FALSE, when broadcast packet in Adhoc mode. */ | ||
588 | /*TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate); */ | ||
589 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag); | ||
590 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM); | ||
591 | if (RTMP_GET_PACKET_MOREDATA(pPacket)) { | ||
592 | TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData); | ||
593 | } | ||
594 | |||
595 | } else { | ||
596 | pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid]; | ||
597 | pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode; | ||
598 | |||
599 | pMacEntry = pTxBlk->pMacEntry; | ||
600 | |||
601 | /* For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK. */ | ||
602 | if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK) | ||
603 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); | ||
604 | else | ||
605 | TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired); | ||
606 | |||
607 | if ((pAd->OpMode == OPMODE_STA) && | ||
608 | (ADHOC_ON(pAd)) && | ||
609 | (RX_FILTER_TEST_FLAG(pAd, fRX_FILTER_ACCEPT_PROMISCUOUS))) { | ||
610 | if (pAd->CommonCfg.PSPXlink) | ||
611 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); | ||
612 | } | ||
613 | |||
614 | { | ||
615 | { | ||
616 | |||
617 | /* If support WMM, enable it. */ | ||
618 | if (OPSTATUS_TEST_FLAG | ||
619 | (pAd, fOP_STATUS_WMM_INUSED) | ||
620 | && CLIENT_STATUS_TEST_FLAG(pMacEntry, | ||
621 | fCLIENT_STATUS_WMM_CAPABLE)) | ||
622 | TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM); | ||
623 | |||
624 | /* if (pAd->StaCfg.bAutoTxRateSwitch) */ | ||
625 | /* TX_BLK_SET_FLAG(pTxBlk, fTX_AutoRateSwitch); */ | ||
626 | } | ||
627 | } | ||
628 | |||
629 | if (pTxBlk->TxFrameType == TX_LEGACY_FRAME) { | ||
630 | if ((RTMP_GET_PACKET_LOWRATE(pPacket)) || ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1))) { /* Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate. */ | ||
631 | pTxBlk->pTransmit = | ||
632 | &pAd->MacTab.Content[MCAST_WCID].HTPhyMode; | ||
633 | |||
634 | /* Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it??? */ | ||
635 | if (IS_HT_STA(pTxBlk->pMacEntry) && | ||
636 | (CLIENT_STATUS_TEST_FLAG | ||
637 | (pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) | ||
638 | && ((pAd->CommonCfg.bRdg == TRUE) | ||
639 | && CLIENT_STATUS_TEST_FLAG(pMacEntry, | ||
640 | fCLIENT_STATUS_RDG_CAPABLE))) | ||
641 | { | ||
642 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM); | ||
643 | TX_BLK_SET_FLAG(pTxBlk, | ||
644 | fTX_bForceNonQoS); | ||
645 | } | ||
646 | } | ||
647 | |||
648 | if ((IS_HT_RATE(pMacEntry) == FALSE) && (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE))) { /* Currently piggy-back only support when peer is operate in b/g mode. */ | ||
649 | TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack); | ||
650 | } | ||
651 | |||
652 | if (RTMP_GET_PACKET_MOREDATA(pPacket)) { | ||
653 | TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData); | ||
654 | } | ||
655 | } else if (pTxBlk->TxFrameType == TX_FRAG_FRAME) { | ||
656 | TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag); | ||
657 | } | ||
658 | |||
659 | pMacEntry->DebugTxCount++; | ||
660 | } | ||
661 | |||
662 | return TRUE; | ||
663 | } | ||
664 | |||
665 | BOOLEAN CanDoAggregateTransmit(struct rt_rtmp_adapter *pAd, | ||
666 | char * pPacket, struct rt_tx_blk *pTxBlk) | ||
667 | { | ||
668 | |||
669 | /*DBGPRINT(RT_DEBUG_TRACE, ("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType)); */ | ||
670 | |||
671 | if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID) | ||
672 | return FALSE; | ||
673 | |||
674 | if (RTMP_GET_PACKET_DHCP(pPacket) || | ||
675 | RTMP_GET_PACKET_EAPOL(pPacket) || RTMP_GET_PACKET_WAI(pPacket)) | ||
676 | return FALSE; | ||
677 | |||
678 | if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) && ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket)) > (RX_BUFFER_AGGRESIZE - 100))) { /* For AMSDU, allow the packets with total length < max-amsdu size */ | ||
679 | return FALSE; | ||
680 | } | ||
681 | |||
682 | if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) && (pTxBlk->TxPacketList.Number == 2)) { /* For RALINK-Aggregation, allow two frames in one batch. */ | ||
683 | return FALSE; | ||
684 | } | ||
685 | |||
686 | if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) /* must be unicast to AP */ | ||
687 | return TRUE; | ||
688 | else | ||
689 | return FALSE; | ||
690 | |||
691 | } | ||
692 | |||
693 | /* | ||
694 | ======================================================================== | ||
695 | |||
696 | Routine Description: | ||
697 | To do the enqueue operation and extract the first item of waiting | ||
698 | list. If a number of available shared memory segments could meet | ||
699 | the request of extracted item, the extracted item will be fragmented | ||
700 | into shared memory segments. | ||
701 | |||
702 | Arguments: | ||
703 | pAd Pointer to our adapter | ||
704 | pQueue Pointer to Waiting Queue | ||
705 | |||
706 | Return Value: | ||
707 | None | ||
708 | |||
709 | IRQL = DISPATCH_LEVEL | ||
710 | |||
711 | Note: | ||
712 | |||
713 | ======================================================================== | ||
714 | */ | ||
715 | void RTMPDeQueuePacket(struct rt_rtmp_adapter *pAd, IN BOOLEAN bIntContext, u8 QIdx, /* BulkOutPipeId */ | ||
716 | u8 Max_Tx_Packets) | ||
717 | { | ||
718 | struct rt_queue_entry *pEntry = NULL; | ||
719 | void *pPacket; | ||
720 | int Status = NDIS_STATUS_SUCCESS; | ||
721 | u8 Count = 0; | ||
722 | struct rt_queue_header *pQueue; | ||
723 | unsigned long FreeNumber[NUM_OF_TX_RING]; | ||
724 | u8 QueIdx, sQIdx, eQIdx; | ||
725 | unsigned long IrqFlags = 0; | ||
726 | BOOLEAN hasTxDesc = FALSE; | ||
727 | struct rt_tx_blk TxBlk; | ||
728 | struct rt_tx_blk *pTxBlk; | ||
729 | |||
730 | if (QIdx == NUM_OF_TX_RING) { | ||
731 | sQIdx = 0; | ||
732 | eQIdx = 3; /* 4 ACs, start from 0. */ | ||
733 | } else { | ||
734 | sQIdx = eQIdx = QIdx; | ||
735 | } | ||
736 | |||
737 | for (QueIdx = sQIdx; QueIdx <= eQIdx; QueIdx++) { | ||
738 | Count = 0; | ||
739 | |||
740 | RTMP_START_DEQUEUE(pAd, QueIdx, IrqFlags); | ||
741 | |||
742 | while (1) { | ||
743 | if ((RTMP_TEST_FLAG | ||
744 | (pAd, | ||
745 | (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS | | ||
746 | fRTMP_ADAPTER_RADIO_OFF | | ||
747 | fRTMP_ADAPTER_RESET_IN_PROGRESS | | ||
748 | fRTMP_ADAPTER_HALT_IN_PROGRESS | | ||
749 | fRTMP_ADAPTER_NIC_NOT_EXIST)))) { | ||
750 | RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags); | ||
751 | return; | ||
752 | } | ||
753 | |||
754 | if (Count >= Max_Tx_Packets) | ||
755 | break; | ||
756 | |||
757 | DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags); | ||
758 | if (&pAd->TxSwQueue[QueIdx] == NULL) { | ||
759 | DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, | ||
760 | IrqFlags); | ||
761 | break; | ||
762 | } | ||
763 | #ifdef RTMP_MAC_PCI | ||
764 | FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx); | ||
765 | |||
766 | if (FreeNumber[QueIdx] <= 5) { | ||
767 | /* free Tx(QueIdx) resources */ | ||
768 | RTMPFreeTXDUponTxDmaDone(pAd, QueIdx); | ||
769 | FreeNumber[QueIdx] = | ||
770 | GET_TXRING_FREENO(pAd, QueIdx); | ||
771 | } | ||
772 | #endif /* RTMP_MAC_PCI // */ | ||
773 | |||
774 | /* probe the Queue Head */ | ||
775 | pQueue = &pAd->TxSwQueue[QueIdx]; | ||
776 | pEntry = pQueue->Head; | ||
777 | if (pEntry == NULL) { | ||
778 | DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, | ||
779 | IrqFlags); | ||
780 | break; | ||
781 | } | ||
782 | |||
783 | pTxBlk = &TxBlk; | ||
784 | NdisZeroMemory((u8 *)pTxBlk, sizeof(struct rt_tx_blk)); | ||
785 | /*InitializeQueueHeader(&pTxBlk->TxPacketList); // Didn't need it because we already memzero it. */ | ||
786 | pTxBlk->QueIdx = QueIdx; | ||
787 | |||
788 | pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); | ||
789 | |||
790 | /* Early check to make sure we have enoguh Tx Resource. */ | ||
791 | hasTxDesc = | ||
792 | RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, | ||
793 | FreeNumber[QueIdx], | ||
794 | pPacket); | ||
795 | if (!hasTxDesc) { | ||
796 | pAd->PrivateInfo.TxRingFullCnt++; | ||
797 | |||
798 | DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, | ||
799 | IrqFlags); | ||
800 | |||
801 | break; | ||
802 | } | ||
803 | |||
804 | pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket); | ||
805 | pEntry = RemoveHeadQueue(pQueue); | ||
806 | pTxBlk->TotalFrameNum++; | ||
807 | pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); /* The real fragment number maybe vary */ | ||
808 | pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket); | ||
809 | pTxBlk->pPacket = pPacket; | ||
810 | InsertTailQueue(&pTxBlk->TxPacketList, | ||
811 | PACKET_TO_QUEUE_ENTRY(pPacket)); | ||
812 | |||
813 | if (pTxBlk->TxFrameType == TX_RALINK_FRAME | ||
814 | || pTxBlk->TxFrameType == TX_AMSDU_FRAME) { | ||
815 | /* Enhance SW Aggregation Mechanism */ | ||
816 | if (NEED_QUEUE_BACK_FOR_AGG | ||
817 | (pAd, QueIdx, FreeNumber[QueIdx], | ||
818 | pTxBlk->TxFrameType)) { | ||
819 | InsertHeadQueue(pQueue, | ||
820 | PACKET_TO_QUEUE_ENTRY | ||
821 | (pPacket)); | ||
822 | DEQUEUE_UNLOCK(&pAd->irq_lock, | ||
823 | bIntContext, IrqFlags); | ||
824 | break; | ||
825 | } | ||
826 | |||
827 | do { | ||
828 | pEntry = pQueue->Head; | ||
829 | if (pEntry == NULL) | ||
830 | break; | ||
831 | |||
832 | /* For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation. */ | ||
833 | pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); | ||
834 | FreeNumber[QueIdx] = | ||
835 | GET_TXRING_FREENO(pAd, QueIdx); | ||
836 | hasTxDesc = | ||
837 | RTMP_HAS_ENOUGH_FREE_DESC(pAd, | ||
838 | pTxBlk, | ||
839 | FreeNumber | ||
840 | [QueIdx], | ||
841 | pPacket); | ||
842 | if ((hasTxDesc == FALSE) | ||
843 | || | ||
844 | (CanDoAggregateTransmit | ||
845 | (pAd, pPacket, pTxBlk) == FALSE)) | ||
846 | break; | ||
847 | |||
848 | /*Remove the packet from the TxSwQueue and insert into pTxBlk */ | ||
849 | pEntry = RemoveHeadQueue(pQueue); | ||
850 | ASSERT(pEntry); | ||
851 | pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); | ||
852 | pTxBlk->TotalFrameNum++; | ||
853 | pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); /* The real fragment number maybe vary */ | ||
854 | pTxBlk->TotalFrameLen += | ||
855 | GET_OS_PKT_LEN(pPacket); | ||
856 | InsertTailQueue(&pTxBlk->TxPacketList, | ||
857 | PACKET_TO_QUEUE_ENTRY | ||
858 | (pPacket)); | ||
859 | } while (1); | ||
860 | |||
861 | if (pTxBlk->TxPacketList.Number == 1) | ||
862 | pTxBlk->TxFrameType = TX_LEGACY_FRAME; | ||
863 | } | ||
864 | #ifdef RTMP_MAC_USB | ||
865 | DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); | ||
866 | #endif /* RTMP_MAC_USB // */ | ||
867 | Count += pTxBlk->TxPacketList.Number; | ||
868 | |||
869 | /* Do HardTransmit now. */ | ||
870 | Status = STAHardTransmit(pAd, pTxBlk, QueIdx); | ||
871 | |||
872 | #ifdef RTMP_MAC_PCI | ||
873 | DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); | ||
874 | /* static rate also need NICUpdateFifoStaCounters() function. */ | ||
875 | /*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */ | ||
876 | NICUpdateFifoStaCounters(pAd); | ||
877 | #endif /* RTMP_MAC_PCI // */ | ||
878 | |||
879 | } | ||
880 | |||
881 | RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags); | ||
882 | |||
883 | #ifdef RTMP_MAC_USB | ||
884 | if (!hasTxDesc) | ||
885 | RTUSBKickBulkOut(pAd); | ||
886 | #endif /* RTMP_MAC_USB // */ | ||
887 | } | ||
888 | |||
889 | } | ||
890 | |||
891 | /* | ||
892 | ======================================================================== | ||
893 | |||
894 | Routine Description: | ||
895 | Calculates the duration which is required to transmit out frames | ||
896 | with given size and specified rate. | ||
897 | |||
898 | Arguments: | ||
899 | pAd Pointer to our adapter | ||
900 | Rate Transmit rate | ||
901 | Size Frame size in units of byte | ||
902 | |||
903 | Return Value: | ||
904 | Duration number in units of usec | ||
905 | |||
906 | IRQL = PASSIVE_LEVEL | ||
907 | IRQL = DISPATCH_LEVEL | ||
908 | |||
909 | Note: | ||
910 | |||
911 | ======================================================================== | ||
912 | */ | ||
913 | u16 RTMPCalcDuration(struct rt_rtmp_adapter *pAd, u8 Rate, unsigned long Size) | ||
914 | { | ||
915 | unsigned long Duration = 0; | ||
916 | |||
917 | if (Rate < RATE_FIRST_OFDM_RATE) /* CCK */ | ||
918 | { | ||
919 | if ((Rate > RATE_1) | ||
920 | && OPSTATUS_TEST_FLAG(pAd, | ||
921 | fOP_STATUS_SHORT_PREAMBLE_INUSED)) | ||
922 | Duration = 96; /* 72+24 preamble+plcp */ | ||
923 | else | ||
924 | Duration = 192; /* 144+48 preamble+plcp */ | ||
925 | |||
926 | Duration += (u16)((Size << 4) / RateIdTo500Kbps[Rate]); | ||
927 | if ((Size << 4) % RateIdTo500Kbps[Rate]) | ||
928 | Duration++; | ||
929 | } else if (Rate <= RATE_LAST_OFDM_RATE) /* OFDM rates */ | ||
930 | { | ||
931 | Duration = 20 + 6; /* 16+4 preamble+plcp + Signal Extension */ | ||
932 | Duration += | ||
933 | 4 * (u16)((11 + Size * 4) / RateIdTo500Kbps[Rate]); | ||
934 | if ((11 + Size * 4) % RateIdTo500Kbps[Rate]) | ||
935 | Duration += 4; | ||
936 | } else /*mimo rate */ | ||
937 | { | ||
938 | Duration = 20 + 6; /* 16+4 preamble+plcp + Signal Extension */ | ||
939 | } | ||
940 | |||
941 | return (u16)Duration; | ||
942 | } | ||
943 | |||
944 | /* | ||
945 | ======================================================================== | ||
946 | |||
947 | Routine Description: | ||
948 | Calculates the duration which is required to transmit out frames | ||
949 | with given size and specified rate. | ||
950 | |||
951 | Arguments: | ||
952 | pTxWI Pointer to head of each MPDU to HW. | ||
953 | Ack Setting for Ack requirement bit | ||
954 | Fragment Setting for Fragment bit | ||
955 | RetryMode Setting for retry mode | ||
956 | Ifs Setting for IFS gap | ||
957 | Rate Setting for transmit rate | ||
958 | Service Setting for service | ||
959 | Length Frame length | ||
960 | TxPreamble Short or Long preamble when using CCK rates | ||
961 | QueIdx - 0-3, according to 802.11e/d4.4 June/2003 | ||
962 | |||
963 | Return Value: | ||
964 | None | ||
965 | |||
966 | IRQL = PASSIVE_LEVEL | ||
967 | IRQL = DISPATCH_LEVEL | ||
968 | |||
969 | See also : BASmartHardTransmit() ! | ||
970 | |||
971 | ======================================================================== | ||
972 | */ | ||
973 | void RTMPWriteTxWI(struct rt_rtmp_adapter *pAd, struct rt_txwi * pOutTxWI, IN BOOLEAN FRAG, IN BOOLEAN CFACK, IN BOOLEAN InsTimestamp, IN BOOLEAN AMPDU, IN BOOLEAN Ack, IN BOOLEAN NSeq, /* HW new a sequence. */ | ||
974 | u8 BASize, | ||
975 | u8 WCID, | ||
976 | unsigned long Length, | ||
977 | u8 PID, | ||
978 | u8 TID, | ||
979 | u8 TxRate, | ||
980 | u8 Txopmode, | ||
981 | IN BOOLEAN CfAck, IN HTTRANSMIT_SETTING * pTransmit) | ||
982 | { | ||
983 | struct rt_mac_table_entry *pMac = NULL; | ||
984 | struct rt_txwi TxWI; | ||
985 | struct rt_txwi * pTxWI; | ||
986 | |||
987 | if (WCID < MAX_LEN_OF_MAC_TABLE) | ||
988 | pMac = &pAd->MacTab.Content[WCID]; | ||
989 | |||
990 | /* */ | ||
991 | /* Always use Long preamble before verifiation short preamble functionality works well. */ | ||
992 | /* Todo: remove the following line if short preamble functionality works */ | ||
993 | /* */ | ||
994 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); | ||
995 | NdisZeroMemory(&TxWI, TXWI_SIZE); | ||
996 | pTxWI = &TxWI; | ||
997 | |||
998 | pTxWI->FRAG = FRAG; | ||
999 | |||
1000 | pTxWI->CFACK = CFACK; | ||
1001 | pTxWI->TS = InsTimestamp; | ||
1002 | pTxWI->AMPDU = AMPDU; | ||
1003 | pTxWI->ACK = Ack; | ||
1004 | pTxWI->txop = Txopmode; | ||
1005 | |||
1006 | pTxWI->NSEQ = NSeq; | ||
1007 | /* John tune the performace with Intel Client in 20 MHz performance */ | ||
1008 | BASize = pAd->CommonCfg.TxBASize; | ||
1009 | if (pAd->MACVersion == 0x28720200) { | ||
1010 | if (BASize > 13) | ||
1011 | BASize = 13; | ||
1012 | } else { | ||
1013 | if (BASize > 7) | ||
1014 | BASize = 7; | ||
1015 | } | ||
1016 | pTxWI->BAWinSize = BASize; | ||
1017 | pTxWI->ShortGI = pTransmit->field.ShortGI; | ||
1018 | pTxWI->STBC = pTransmit->field.STBC; | ||
1019 | |||
1020 | pTxWI->WirelessCliID = WCID; | ||
1021 | pTxWI->MPDUtotalByteCount = Length; | ||
1022 | pTxWI->PacketId = PID; | ||
1023 | |||
1024 | /* If CCK or OFDM, BW must be 20 */ | ||
1025 | pTxWI->BW = | ||
1026 | (pTransmit->field.MODE <= | ||
1027 | MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); | ||
1028 | |||
1029 | pTxWI->MCS = pTransmit->field.MCS; | ||
1030 | pTxWI->PHYMODE = pTransmit->field.MODE; | ||
1031 | pTxWI->CFACK = CfAck; | ||
1032 | |||
1033 | if (pMac) { | ||
1034 | if (pAd->CommonCfg.bMIMOPSEnable) { | ||
1035 | if ((pMac->MmpsMode == MMPS_DYNAMIC) | ||
1036 | && (pTransmit->field.MCS > 7)) { | ||
1037 | /* Dynamic MIMO Power Save Mode */ | ||
1038 | pTxWI->MIMOps = 1; | ||
1039 | } else if (pMac->MmpsMode == MMPS_STATIC) { | ||
1040 | /* Static MIMO Power Save Mode */ | ||
1041 | if (pTransmit->field.MODE >= MODE_HTMIX | ||
1042 | && pTransmit->field.MCS > 7) { | ||
1043 | pTxWI->MCS = 7; | ||
1044 | pTxWI->MIMOps = 0; | ||
1045 | } | ||
1046 | } | ||
1047 | } | ||
1048 | /*pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0; */ | ||
1049 | if (pMac->bIAmBadAtheros | ||
1050 | && (pMac->WepStatus != Ndis802_11WEPDisabled)) { | ||
1051 | pTxWI->MpduDensity = 7; | ||
1052 | } else { | ||
1053 | pTxWI->MpduDensity = pMac->MpduDensity; | ||
1054 | } | ||
1055 | } | ||
1056 | |||
1057 | pTxWI->PacketId = pTxWI->MCS; | ||
1058 | NdisMoveMemory(pOutTxWI, &TxWI, sizeof(struct rt_txwi)); | ||
1059 | } | ||
1060 | |||
1061 | void RTMPWriteTxWI_Data(struct rt_rtmp_adapter *pAd, | ||
1062 | struct rt_txwi * pTxWI, struct rt_tx_blk *pTxBlk) | ||
1063 | { | ||
1064 | HTTRANSMIT_SETTING *pTransmit; | ||
1065 | struct rt_mac_table_entry *pMacEntry; | ||
1066 | u8 BASize; | ||
1067 | |||
1068 | ASSERT(pTxWI); | ||
1069 | |||
1070 | pTransmit = pTxBlk->pTransmit; | ||
1071 | pMacEntry = pTxBlk->pMacEntry; | ||
1072 | |||
1073 | /* */ | ||
1074 | /* Always use Long preamble before verifiation short preamble functionality works well. */ | ||
1075 | /* Todo: remove the following line if short preamble functionality works */ | ||
1076 | /* */ | ||
1077 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); | ||
1078 | NdisZeroMemory(pTxWI, TXWI_SIZE); | ||
1079 | |||
1080 | pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag); | ||
1081 | pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired); | ||
1082 | pTxWI->txop = pTxBlk->FrameGap; | ||
1083 | |||
1084 | pTxWI->WirelessCliID = pTxBlk->Wcid; | ||
1085 | |||
1086 | pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; | ||
1087 | pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack); | ||
1088 | |||
1089 | /* If CCK or OFDM, BW must be 20 */ | ||
1090 | pTxWI->BW = | ||
1091 | (pTransmit->field.MODE <= | ||
1092 | MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); | ||
1093 | pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE); | ||
1094 | |||
1095 | /* John tune the performace with Intel Client in 20 MHz performance */ | ||
1096 | BASize = pAd->CommonCfg.TxBASize; | ||
1097 | if ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry)) { | ||
1098 | u8 RABAOriIdx = 0; /*The RA's BA Originator table index. */ | ||
1099 | |||
1100 | RABAOriIdx = | ||
1101 | pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority]; | ||
1102 | BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize; | ||
1103 | } | ||
1104 | |||
1105 | pTxWI->TxBF = pTransmit->field.TxBF; | ||
1106 | pTxWI->BAWinSize = BASize; | ||
1107 | pTxWI->ShortGI = pTransmit->field.ShortGI; | ||
1108 | pTxWI->STBC = pTransmit->field.STBC; | ||
1109 | |||
1110 | pTxWI->MCS = pTransmit->field.MCS; | ||
1111 | pTxWI->PHYMODE = pTransmit->field.MODE; | ||
1112 | |||
1113 | if (pMacEntry) { | ||
1114 | if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) | ||
1115 | && (pTransmit->field.MCS > 7)) { | ||
1116 | /* Dynamic MIMO Power Save Mode */ | ||
1117 | pTxWI->MIMOps = 1; | ||
1118 | } else if (pMacEntry->MmpsMode == MMPS_STATIC) { | ||
1119 | /* Static MIMO Power Save Mode */ | ||
1120 | if (pTransmit->field.MODE >= MODE_HTMIX | ||
1121 | && pTransmit->field.MCS > 7) { | ||
1122 | pTxWI->MCS = 7; | ||
1123 | pTxWI->MIMOps = 0; | ||
1124 | } | ||
1125 | } | ||
1126 | |||
1127 | if (pMacEntry->bIAmBadAtheros | ||
1128 | && (pMacEntry->WepStatus != Ndis802_11WEPDisabled)) { | ||
1129 | pTxWI->MpduDensity = 7; | ||
1130 | } else { | ||
1131 | pTxWI->MpduDensity = pMacEntry->MpduDensity; | ||
1132 | } | ||
1133 | } | ||
1134 | |||
1135 | /* for rate adapation */ | ||
1136 | pTxWI->PacketId = pTxWI->MCS; | ||
1137 | } | ||
1138 | |||
1139 | void RTMPWriteTxWI_Cache(struct rt_rtmp_adapter *pAd, | ||
1140 | struct rt_txwi * pTxWI, struct rt_tx_blk *pTxBlk) | ||
1141 | { | ||
1142 | PHTTRANSMIT_SETTING /*pTxHTPhyMode, */ pTransmit; | ||
1143 | struct rt_mac_table_entry *pMacEntry; | ||
1144 | |||
1145 | /* */ | ||
1146 | /* update TXWI */ | ||
1147 | /* */ | ||
1148 | pMacEntry = pTxBlk->pMacEntry; | ||
1149 | pTransmit = pTxBlk->pTransmit; | ||
1150 | |||
1151 | /*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */ | ||
1152 | /*if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pMacEntry)) */ | ||
1153 | /*if (TX_BLK_TEST_FLAG(pTxBlk, fTX_AutoRateSwitch)) */ | ||
1154 | if (pMacEntry->bAutoTxRateSwitch) { | ||
1155 | pTxWI->txop = IFS_HTTXOP; | ||
1156 | |||
1157 | /* If CCK or OFDM, BW must be 20 */ | ||
1158 | pTxWI->BW = | ||
1159 | (pTransmit->field.MODE <= | ||
1160 | MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); | ||
1161 | pTxWI->ShortGI = pTransmit->field.ShortGI; | ||
1162 | pTxWI->STBC = pTransmit->field.STBC; | ||
1163 | |||
1164 | pTxWI->MCS = pTransmit->field.MCS; | ||
1165 | pTxWI->PHYMODE = pTransmit->field.MODE; | ||
1166 | |||
1167 | /* set PID for TxRateSwitching */ | ||
1168 | pTxWI->PacketId = pTransmit->field.MCS; | ||
1169 | } | ||
1170 | |||
1171 | pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE : FALSE); | ||
1172 | pTxWI->MIMOps = 0; | ||
1173 | |||
1174 | if (pAd->CommonCfg.bMIMOPSEnable) { | ||
1175 | /* MIMO Power Save Mode */ | ||
1176 | if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) | ||
1177 | && (pTransmit->field.MCS > 7)) { | ||
1178 | /* Dynamic MIMO Power Save Mode */ | ||
1179 | pTxWI->MIMOps = 1; | ||
1180 | } else if (pMacEntry->MmpsMode == MMPS_STATIC) { | ||
1181 | /* Static MIMO Power Save Mode */ | ||
1182 | if ((pTransmit->field.MODE >= MODE_HTMIX) | ||
1183 | && (pTransmit->field.MCS > 7)) { | ||
1184 | pTxWI->MCS = 7; | ||
1185 | pTxWI->MIMOps = 0; | ||
1186 | } | ||
1187 | } | ||
1188 | } | ||
1189 | |||
1190 | pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; | ||
1191 | |||
1192 | } | ||
1193 | |||
1194 | /* should be called only when - */ | ||
1195 | /* 1. MEADIA_CONNECTED */ | ||
1196 | /* 2. AGGREGATION_IN_USED */ | ||
1197 | /* 3. Fragmentation not in used */ | ||
1198 | /* 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible */ | ||
1199 | BOOLEAN TxFrameIsAggregatible(struct rt_rtmp_adapter *pAd, | ||
1200 | u8 *pPrevAddr1, u8 *p8023hdr) | ||
1201 | { | ||
1202 | |||
1203 | /* can't aggregate EAPOL (802.1x) frame */ | ||
1204 | if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e)) | ||
1205 | return FALSE; | ||
1206 | |||
1207 | /* can't aggregate multicast/broadcast frame */ | ||
1208 | if (p8023hdr[0] & 0x01) | ||
1209 | return FALSE; | ||
1210 | |||
1211 | if (INFRA_ON(pAd)) /* must be unicast to AP */ | ||
1212 | return TRUE; | ||
1213 | else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) /* unicast to same STA */ | ||
1214 | return TRUE; | ||
1215 | else | ||
1216 | return FALSE; | ||
1217 | } | ||
1218 | |||
1219 | /* | ||
1220 | ======================================================================== | ||
1221 | |||
1222 | Routine Description: | ||
1223 | Check the MSDU Aggregation policy | ||
1224 | 1.HT aggregation is A-MSDU | ||
1225 | 2.legaacy rate aggregation is software aggregation by Ralink. | ||
1226 | |||
1227 | Arguments: | ||
1228 | |||
1229 | Return Value: | ||
1230 | |||
1231 | Note: | ||
1232 | |||
1233 | ======================================================================== | ||
1234 | */ | ||
1235 | BOOLEAN PeerIsAggreOn(struct rt_rtmp_adapter *pAd, | ||
1236 | unsigned long TxRate, struct rt_mac_table_entry *pMacEntry) | ||
1237 | { | ||
1238 | unsigned long AFlags = | ||
1239 | (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE); | ||
1240 | |||
1241 | if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags)) { | ||
1242 | if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) { | ||
1243 | return TRUE; | ||
1244 | } | ||
1245 | #ifdef AGGREGATION_SUPPORT | ||
1246 | if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)))) { /* legacy Ralink Aggregation support */ | ||
1247 | return TRUE; | ||
1248 | } | ||
1249 | #endif /* AGGREGATION_SUPPORT // */ | ||
1250 | } | ||
1251 | |||
1252 | return FALSE; | ||
1253 | |||
1254 | } | ||
1255 | |||
1256 | /* | ||
1257 | ======================================================================== | ||
1258 | |||
1259 | Routine Description: | ||
1260 | Check and fine the packet waiting in SW queue with highest priority | ||
1261 | |||
1262 | Arguments: | ||
1263 | pAd Pointer to our adapter | ||
1264 | |||
1265 | Return Value: | ||
1266 | pQueue Pointer to Waiting Queue | ||
1267 | |||
1268 | IRQL = DISPATCH_LEVEL | ||
1269 | |||
1270 | Note: | ||
1271 | |||
1272 | ======================================================================== | ||
1273 | */ | ||
1274 | struct rt_queue_header *RTMPCheckTxSwQueue(struct rt_rtmp_adapter *pAd, u8 *pQueIdx) | ||
1275 | { | ||
1276 | |||
1277 | unsigned long Number; | ||
1278 | /* 2004-11-15 to be removed. test aggregation only */ | ||
1279 | /* if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2)) */ | ||
1280 | /* return NULL; */ | ||
1281 | |||
1282 | Number = pAd->TxSwQueue[QID_AC_BK].Number | ||
1283 | + pAd->TxSwQueue[QID_AC_BE].Number | ||
1284 | + pAd->TxSwQueue[QID_AC_VI].Number | ||
1285 | + pAd->TxSwQueue[QID_AC_VO].Number; | ||
1286 | |||
1287 | if (pAd->TxSwQueue[QID_AC_VO].Head != NULL) { | ||
1288 | *pQueIdx = QID_AC_VO; | ||
1289 | return (&pAd->TxSwQueue[QID_AC_VO]); | ||
1290 | } else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL) { | ||
1291 | *pQueIdx = QID_AC_VI; | ||
1292 | return (&pAd->TxSwQueue[QID_AC_VI]); | ||
1293 | } else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL) { | ||
1294 | *pQueIdx = QID_AC_BE; | ||
1295 | return (&pAd->TxSwQueue[QID_AC_BE]); | ||
1296 | } else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL) { | ||
1297 | *pQueIdx = QID_AC_BK; | ||
1298 | return (&pAd->TxSwQueue[QID_AC_BK]); | ||
1299 | } | ||
1300 | /* No packet pending in Tx Sw queue */ | ||
1301 | *pQueIdx = QID_AC_BK; | ||
1302 | |||
1303 | return (NULL); | ||
1304 | } | ||
1305 | |||
1306 | /* | ||
1307 | ======================================================================== | ||
1308 | |||
1309 | Routine Description: | ||
1310 | Suspend MSDU transmission | ||
1311 | |||
1312 | Arguments: | ||
1313 | pAd Pointer to our adapter | ||
1314 | |||
1315 | Return Value: | ||
1316 | None | ||
1317 | |||
1318 | Note: | ||
1319 | |||
1320 | ======================================================================== | ||
1321 | */ | ||
1322 | void RTMPSuspendMsduTransmission(struct rt_rtmp_adapter *pAd) | ||
1323 | { | ||
1324 | DBGPRINT(RT_DEBUG_TRACE, ("SCANNING, suspend MSDU transmission ...\n")); | ||
1325 | |||
1326 | /* */ | ||
1327 | /* Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and */ | ||
1328 | /* use Lowbound as R66 value on ScanNextChannel(...) */ | ||
1329 | /* */ | ||
1330 | RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, | ||
1331 | &pAd->BbpTuning.R66CurrentValue); | ||
1332 | |||
1333 | /* set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning) */ | ||
1334 | /*RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd))); */ | ||
1335 | RTMPSetAGCInitValue(pAd, BW_20); | ||
1336 | |||
1337 | RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); | ||
1338 | /*RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000); // abort all TX rings */ | ||
1339 | } | ||
1340 | |||
1341 | /* | ||
1342 | ======================================================================== | ||
1343 | |||
1344 | Routine Description: | ||
1345 | Resume MSDU transmission | ||
1346 | |||
1347 | Arguments: | ||
1348 | pAd Pointer to our adapter | ||
1349 | |||
1350 | Return Value: | ||
1351 | None | ||
1352 | |||
1353 | IRQL = DISPATCH_LEVEL | ||
1354 | |||
1355 | Note: | ||
1356 | |||
1357 | ======================================================================== | ||
1358 | */ | ||
1359 | void RTMPResumeMsduTransmission(struct rt_rtmp_adapter *pAd) | ||
1360 | { | ||
1361 | /* u8 IrqState; */ | ||
1362 | |||
1363 | DBGPRINT(RT_DEBUG_TRACE, ("SCAN done, resume MSDU transmission ...\n")); | ||
1364 | |||
1365 | /* After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value */ | ||
1366 | /* R66 should not be 0 */ | ||
1367 | if (pAd->BbpTuning.R66CurrentValue == 0) { | ||
1368 | pAd->BbpTuning.R66CurrentValue = 0x38; | ||
1369 | DBGPRINT_ERR("RTMPResumeMsduTransmission, R66CurrentValue=0...\n"); | ||
1370 | } | ||
1371 | |||
1372 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, | ||
1373 | pAd->BbpTuning.R66CurrentValue); | ||
1374 | |||
1375 | RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); | ||
1376 | /* sample, for IRQ LOCK to SEM LOCK */ | ||
1377 | /* IrqState = pAd->irq_disabled; */ | ||
1378 | /* if (IrqState) */ | ||
1379 | /* RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS); */ | ||
1380 | /* else */ | ||
1381 | RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); | ||
1382 | } | ||
1383 | |||
1384 | u32 deaggregate_AMSDU_announce(struct rt_rtmp_adapter *pAd, | ||
1385 | void *pPacket, | ||
1386 | u8 *pData, unsigned long DataSize) | ||
1387 | { | ||
1388 | u16 PayloadSize; | ||
1389 | u16 SubFrameSize; | ||
1390 | struct rt_header_802_3 * pAMSDUsubheader; | ||
1391 | u32 nMSDU; | ||
1392 | u8 Header802_3[14]; | ||
1393 | |||
1394 | u8 *pPayload, *pDA, *pSA, *pRemovedLLCSNAP; | ||
1395 | void *pClonePacket; | ||
1396 | |||
1397 | nMSDU = 0; | ||
1398 | |||
1399 | while (DataSize > LENGTH_802_3) { | ||
1400 | |||
1401 | nMSDU++; | ||
1402 | |||
1403 | /*hex_dump("subheader", pData, 64); */ | ||
1404 | pAMSDUsubheader = (struct rt_header_802_3 *) pData; | ||
1405 | /*pData += LENGTH_802_3; */ | ||
1406 | PayloadSize = | ||
1407 | pAMSDUsubheader->Octet[1] + | ||
1408 | (pAMSDUsubheader->Octet[0] << 8); | ||
1409 | SubFrameSize = PayloadSize + LENGTH_802_3; | ||
1410 | |||
1411 | if ((DataSize < SubFrameSize) || (PayloadSize > 1518)) { | ||
1412 | break; | ||
1413 | } | ||
1414 | /*DBGPRINT(RT_DEBUG_TRACE,("%d subframe: Size = %d\n", nMSDU, PayloadSize)); */ | ||
1415 | |||
1416 | pPayload = pData + LENGTH_802_3; | ||
1417 | pDA = pData; | ||
1418 | pSA = pData + MAC_ADDR_LEN; | ||
1419 | |||
1420 | /* convert to 802.3 header */ | ||
1421 | CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, | ||
1422 | pRemovedLLCSNAP); | ||
1423 | |||
1424 | if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E)) { | ||
1425 | /* avoid local heap overflow, use dyanamic allocation */ | ||
1426 | struct rt_mlme_queue_elem *Elem = | ||
1427 | kmalloc(sizeof(struct rt_mlme_queue_elem), | ||
1428 | MEM_ALLOC_FLAG); | ||
1429 | if (Elem != NULL) { | ||
1430 | memmove(Elem->Msg + | ||
1431 | (LENGTH_802_11 + LENGTH_802_1_H), | ||
1432 | pPayload, PayloadSize); | ||
1433 | Elem->MsgLen = | ||
1434 | LENGTH_802_11 + LENGTH_802_1_H + | ||
1435 | PayloadSize; | ||
1436 | /*WpaEAPOLKeyAction(pAd, Elem); */ | ||
1437 | REPORT_MGMT_FRAME_TO_MLME(pAd, BSSID_WCID, | ||
1438 | Elem->Msg, | ||
1439 | Elem->MsgLen, 0, 0, 0, | ||
1440 | 0); | ||
1441 | kfree(Elem); | ||
1442 | } | ||
1443 | } | ||
1444 | |||
1445 | { | ||
1446 | if (pRemovedLLCSNAP) { | ||
1447 | pPayload -= LENGTH_802_3; | ||
1448 | PayloadSize += LENGTH_802_3; | ||
1449 | NdisMoveMemory(pPayload, &Header802_3[0], | ||
1450 | LENGTH_802_3); | ||
1451 | } | ||
1452 | } | ||
1453 | |||
1454 | pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize); | ||
1455 | if (pClonePacket) { | ||
1456 | ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, | ||
1457 | RTMP_GET_PACKET_IF | ||
1458 | (pPacket)); | ||
1459 | } | ||
1460 | |||
1461 | /* A-MSDU has padding to multiple of 4 including subframe header. */ | ||
1462 | /* align SubFrameSize up to multiple of 4 */ | ||
1463 | SubFrameSize = (SubFrameSize + 3) & (~0x3); | ||
1464 | |||
1465 | if (SubFrameSize > 1528 || SubFrameSize < 32) { | ||
1466 | break; | ||
1467 | } | ||
1468 | |||
1469 | if (DataSize > SubFrameSize) { | ||
1470 | pData += SubFrameSize; | ||
1471 | DataSize -= SubFrameSize; | ||
1472 | } else { | ||
1473 | /* end of A-MSDU */ | ||
1474 | DataSize = 0; | ||
1475 | } | ||
1476 | } | ||
1477 | |||
1478 | /* finally release original rx packet */ | ||
1479 | RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); | ||
1480 | |||
1481 | return nMSDU; | ||
1482 | } | ||
1483 | |||
1484 | u32 BA_Reorder_AMSDU_Announce(struct rt_rtmp_adapter *pAd, void *pPacket) | ||
1485 | { | ||
1486 | u8 *pData; | ||
1487 | u16 DataSize; | ||
1488 | u32 nMSDU = 0; | ||
1489 | |||
1490 | pData = (u8 *)GET_OS_PKT_DATAPTR(pPacket); | ||
1491 | DataSize = (u16)GET_OS_PKT_LEN(pPacket); | ||
1492 | |||
1493 | nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize); | ||
1494 | |||
1495 | return nMSDU; | ||
1496 | } | ||
1497 | |||
1498 | /* | ||
1499 | ========================================================================== | ||
1500 | Description: | ||
1501 | Look up the MAC address in the MAC table. Return NULL if not found. | ||
1502 | Return: | ||
1503 | pEntry - pointer to the MAC entry; NULL is not found | ||
1504 | ========================================================================== | ||
1505 | */ | ||
1506 | struct rt_mac_table_entry *MacTableLookup(struct rt_rtmp_adapter *pAd, u8 *pAddr) | ||
1507 | { | ||
1508 | unsigned long HashIdx; | ||
1509 | struct rt_mac_table_entry *pEntry = NULL; | ||
1510 | |||
1511 | HashIdx = MAC_ADDR_HASH_INDEX(pAddr); | ||
1512 | pEntry = pAd->MacTab.Hash[HashIdx]; | ||
1513 | |||
1514 | while (pEntry | ||
1515 | && (pEntry->ValidAsCLI || pEntry->ValidAsWDS | ||
1516 | || pEntry->ValidAsApCli || pEntry->ValidAsMesh)) { | ||
1517 | if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) { | ||
1518 | break; | ||
1519 | } else | ||
1520 | pEntry = pEntry->pNext; | ||
1521 | } | ||
1522 | |||
1523 | return pEntry; | ||
1524 | } | ||
1525 | |||
1526 | struct rt_mac_table_entry *MacTableInsertEntry(struct rt_rtmp_adapter *pAd, | ||
1527 | u8 *pAddr, | ||
1528 | u8 apidx, IN BOOLEAN CleanAll) | ||
1529 | { | ||
1530 | u8 HashIdx; | ||
1531 | int i, FirstWcid; | ||
1532 | struct rt_mac_table_entry *pEntry = NULL, *pCurrEntry; | ||
1533 | /* u16 offset; */ | ||
1534 | /* unsigned long addr; */ | ||
1535 | |||
1536 | /* if FULL, return */ | ||
1537 | if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE) | ||
1538 | return NULL; | ||
1539 | |||
1540 | FirstWcid = 1; | ||
1541 | |||
1542 | if (pAd->StaCfg.BssType == BSS_INFRA) | ||
1543 | FirstWcid = 2; | ||
1544 | |||
1545 | /* allocate one MAC entry */ | ||
1546 | NdisAcquireSpinLock(&pAd->MacTabLock); | ||
1547 | for (i = FirstWcid; i < MAX_LEN_OF_MAC_TABLE; i++) /* skip entry#0 so that "entry index == AID" for fast lookup */ | ||
1548 | { | ||
1549 | /* pick up the first available vacancy */ | ||
1550 | if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) && | ||
1551 | (pAd->MacTab.Content[i].ValidAsWDS == FALSE) && | ||
1552 | (pAd->MacTab.Content[i].ValidAsApCli == FALSE) && | ||
1553 | (pAd->MacTab.Content[i].ValidAsMesh == FALSE) | ||
1554 | ) { | ||
1555 | pEntry = &pAd->MacTab.Content[i]; | ||
1556 | if (CleanAll == TRUE) { | ||
1557 | pEntry->MaxSupportedRate = RATE_11; | ||
1558 | pEntry->CurrTxRate = RATE_11; | ||
1559 | NdisZeroMemory(pEntry, sizeof(struct rt_mac_table_entry)); | ||
1560 | pEntry->PairwiseKey.KeyLen = 0; | ||
1561 | pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; | ||
1562 | } | ||
1563 | { | ||
1564 | { | ||
1565 | pEntry->ValidAsCLI = TRUE; | ||
1566 | pEntry->ValidAsWDS = FALSE; | ||
1567 | pEntry->ValidAsApCli = FALSE; | ||
1568 | pEntry->ValidAsMesh = FALSE; | ||
1569 | pEntry->ValidAsDls = FALSE; | ||
1570 | } | ||
1571 | } | ||
1572 | |||
1573 | pEntry->bIAmBadAtheros = FALSE; | ||
1574 | pEntry->pAd = pAd; | ||
1575 | pEntry->CMTimerRunning = FALSE; | ||
1576 | pEntry->EnqueueEapolStartTimerRunning = | ||
1577 | EAPOL_START_DISABLE; | ||
1578 | pEntry->RSNIE_Len = 0; | ||
1579 | NdisZeroMemory(pEntry->R_Counter, | ||
1580 | sizeof(pEntry->R_Counter)); | ||
1581 | pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR; | ||
1582 | |||
1583 | if (pEntry->ValidAsMesh) | ||
1584 | pEntry->apidx = | ||
1585 | (apidx - MIN_NET_DEVICE_FOR_MESH); | ||
1586 | else if (pEntry->ValidAsApCli) | ||
1587 | pEntry->apidx = | ||
1588 | (apidx - MIN_NET_DEVICE_FOR_APCLI); | ||
1589 | else if (pEntry->ValidAsWDS) | ||
1590 | pEntry->apidx = | ||
1591 | (apidx - MIN_NET_DEVICE_FOR_WDS); | ||
1592 | else | ||
1593 | pEntry->apidx = apidx; | ||
1594 | |||
1595 | { | ||
1596 | { | ||
1597 | pEntry->AuthMode = pAd->StaCfg.AuthMode; | ||
1598 | pEntry->WepStatus = | ||
1599 | pAd->StaCfg.WepStatus; | ||
1600 | pEntry->PrivacyFilter = | ||
1601 | Ndis802_11PrivFilterAcceptAll; | ||
1602 | #ifdef RTMP_MAC_PCI | ||
1603 | AsicRemovePairwiseKeyEntry(pAd, | ||
1604 | pEntry-> | ||
1605 | apidx, | ||
1606 | (u8)i); | ||
1607 | #endif /* RTMP_MAC_PCI // */ | ||
1608 | } | ||
1609 | } | ||
1610 | |||
1611 | pEntry->GTKState = REKEY_NEGOTIATING; | ||
1612 | pEntry->PairwiseKey.KeyLen = 0; | ||
1613 | pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; | ||
1614 | pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; | ||
1615 | |||
1616 | pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND; | ||
1617 | COPY_MAC_ADDR(pEntry->Addr, pAddr); | ||
1618 | pEntry->Sst = SST_NOT_AUTH; | ||
1619 | pEntry->AuthState = AS_NOT_AUTH; | ||
1620 | pEntry->Aid = (u16)i; /*0; */ | ||
1621 | pEntry->CapabilityInfo = 0; | ||
1622 | pEntry->PsMode = PWR_ACTIVE; | ||
1623 | pEntry->PsQIdleCount = 0; | ||
1624 | pEntry->NoDataIdleCount = 0; | ||
1625 | pEntry->AssocDeadLine = MAC_TABLE_ASSOC_TIMEOUT; | ||
1626 | pEntry->ContinueTxFailCnt = 0; | ||
1627 | InitializeQueueHeader(&pEntry->PsQueue); | ||
1628 | |||
1629 | pAd->MacTab.Size++; | ||
1630 | /* Add this entry into ASIC RX WCID search table */ | ||
1631 | RTMP_STA_ENTRY_ADD(pAd, pEntry); | ||
1632 | |||
1633 | DBGPRINT(RT_DEBUG_TRACE, | ||
1634 | ("MacTableInsertEntry - allocate entry #%d, Total= %d\n", | ||
1635 | i, pAd->MacTab.Size)); | ||
1636 | break; | ||
1637 | } | ||
1638 | } | ||
1639 | |||
1640 | /* add this MAC entry into HASH table */ | ||
1641 | if (pEntry) { | ||
1642 | HashIdx = MAC_ADDR_HASH_INDEX(pAddr); | ||
1643 | if (pAd->MacTab.Hash[HashIdx] == NULL) { | ||
1644 | pAd->MacTab.Hash[HashIdx] = pEntry; | ||
1645 | } else { | ||
1646 | pCurrEntry = pAd->MacTab.Hash[HashIdx]; | ||
1647 | while (pCurrEntry->pNext != NULL) | ||
1648 | pCurrEntry = pCurrEntry->pNext; | ||
1649 | pCurrEntry->pNext = pEntry; | ||
1650 | } | ||
1651 | } | ||
1652 | |||
1653 | NdisReleaseSpinLock(&pAd->MacTabLock); | ||
1654 | return pEntry; | ||
1655 | } | ||
1656 | |||
1657 | /* | ||
1658 | ========================================================================== | ||
1659 | Description: | ||
1660 | Delete a specified client from MAC table | ||
1661 | ========================================================================== | ||
1662 | */ | ||
1663 | BOOLEAN MacTableDeleteEntry(struct rt_rtmp_adapter *pAd, | ||
1664 | u16 wcid, u8 *pAddr) | ||
1665 | { | ||
1666 | u16 HashIdx; | ||
1667 | struct rt_mac_table_entry *pEntry, *pPrevEntry, *pProbeEntry; | ||
1668 | BOOLEAN Cancelled; | ||
1669 | /*u16 offset; // unused variable */ | ||
1670 | /*u8 j; // unused variable */ | ||
1671 | |||
1672 | if (wcid >= MAX_LEN_OF_MAC_TABLE) | ||
1673 | return FALSE; | ||
1674 | |||
1675 | NdisAcquireSpinLock(&pAd->MacTabLock); | ||
1676 | |||
1677 | HashIdx = MAC_ADDR_HASH_INDEX(pAddr); | ||
1678 | /*pEntry = pAd->MacTab.Hash[HashIdx]; */ | ||
1679 | pEntry = &pAd->MacTab.Content[wcid]; | ||
1680 | |||
1681 | if (pEntry | ||
1682 | && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS | ||
1683 | || pEntry->ValidAsMesh)) { | ||
1684 | if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) { | ||
1685 | |||
1686 | /* Delete this entry from ASIC on-chip WCID Table */ | ||
1687 | RTMP_STA_ENTRY_MAC_RESET(pAd, wcid); | ||
1688 | |||
1689 | /* free resources of BA */ | ||
1690 | BASessionTearDownALL(pAd, pEntry->Aid); | ||
1691 | |||
1692 | pPrevEntry = NULL; | ||
1693 | pProbeEntry = pAd->MacTab.Hash[HashIdx]; | ||
1694 | ASSERT(pProbeEntry); | ||
1695 | |||
1696 | /* update Hash list */ | ||
1697 | do { | ||
1698 | if (pProbeEntry == pEntry) { | ||
1699 | if (pPrevEntry == NULL) { | ||
1700 | pAd->MacTab.Hash[HashIdx] = | ||
1701 | pEntry->pNext; | ||
1702 | } else { | ||
1703 | pPrevEntry->pNext = | ||
1704 | pEntry->pNext; | ||
1705 | } | ||
1706 | break; | ||
1707 | } | ||
1708 | |||
1709 | pPrevEntry = pProbeEntry; | ||
1710 | pProbeEntry = pProbeEntry->pNext; | ||
1711 | } while (pProbeEntry); | ||
1712 | |||
1713 | /* not found ! */ | ||
1714 | ASSERT(pProbeEntry != NULL); | ||
1715 | |||
1716 | RTMP_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid); | ||
1717 | |||
1718 | if (pEntry->EnqueueEapolStartTimerRunning != | ||
1719 | EAPOL_START_DISABLE) { | ||
1720 | RTMPCancelTimer(&pEntry-> | ||
1721 | EnqueueStartForPSKTimer, | ||
1722 | &Cancelled); | ||
1723 | pEntry->EnqueueEapolStartTimerRunning = | ||
1724 | EAPOL_START_DISABLE; | ||
1725 | } | ||
1726 | |||
1727 | NdisZeroMemory(pEntry, sizeof(struct rt_mac_table_entry)); | ||
1728 | pAd->MacTab.Size--; | ||
1729 | DBGPRINT(RT_DEBUG_TRACE, | ||
1730 | ("MacTableDeleteEntry1 - Total= %d\n", | ||
1731 | pAd->MacTab.Size)); | ||
1732 | } else { | ||
1733 | DBGPRINT(RT_DEBUG_OFF, | ||
1734 | ("\n%s: Impossible Wcid = %d !\n", | ||
1735 | __func__, wcid)); | ||
1736 | } | ||
1737 | } | ||
1738 | |||
1739 | NdisReleaseSpinLock(&pAd->MacTabLock); | ||
1740 | |||
1741 | /*Reset operating mode when no Sta. */ | ||
1742 | if (pAd->MacTab.Size == 0) { | ||
1743 | pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0; | ||
1744 | RTMP_UPDATE_PROTECT(pAd); /* edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet */ | ||
1745 | } | ||
1746 | |||
1747 | return TRUE; | ||
1748 | } | ||
1749 | |||
1750 | /* | ||
1751 | ========================================================================== | ||
1752 | Description: | ||
1753 | This routine reset the entire MAC table. All packets pending in | ||
1754 | the power-saving queues are freed here. | ||
1755 | ========================================================================== | ||
1756 | */ | ||
1757 | void MacTableReset(struct rt_rtmp_adapter *pAd) | ||
1758 | { | ||
1759 | int i; | ||
1760 | |||
1761 | DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n")); | ||
1762 | /*NdisAcquireSpinLock(&pAd->MacTabLock); */ | ||
1763 | |||
1764 | for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) { | ||
1765 | #ifdef RTMP_MAC_PCI | ||
1766 | RTMP_STA_ENTRY_MAC_RESET(pAd, i); | ||
1767 | #endif /* RTMP_MAC_PCI // */ | ||
1768 | if (pAd->MacTab.Content[i].ValidAsCLI == TRUE) { | ||
1769 | |||
1770 | /* free resources of BA */ | ||
1771 | BASessionTearDownALL(pAd, i); | ||
1772 | |||
1773 | pAd->MacTab.Content[i].ValidAsCLI = FALSE; | ||
1774 | |||
1775 | #ifdef RTMP_MAC_USB | ||
1776 | NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6); | ||
1777 | RTMP_STA_ENTRY_MAC_RESET(pAd, i); | ||
1778 | #endif /* RTMP_MAC_USB // */ | ||
1779 | |||
1780 | /*AsicDelWcidTab(pAd, i); */ | ||
1781 | } | ||
1782 | } | ||
1783 | |||
1784 | return; | ||
1785 | } | ||
1786 | |||
1787 | /* | ||
1788 | ========================================================================== | ||
1789 | Description: | ||
1790 | |||
1791 | IRQL = DISPATCH_LEVEL | ||
1792 | |||
1793 | ========================================================================== | ||
1794 | */ | ||
1795 | void AssocParmFill(struct rt_rtmp_adapter *pAd, | ||
1796 | struct rt_mlme_assoc_req *AssocReq, | ||
1797 | u8 *pAddr, | ||
1798 | u16 CapabilityInfo, | ||
1799 | unsigned long Timeout, u16 ListenIntv) | ||
1800 | { | ||
1801 | COPY_MAC_ADDR(AssocReq->Addr, pAddr); | ||
1802 | /* Add mask to support 802.11b mode only */ | ||
1803 | AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; /* not cf-pollable, not cf-poll-request */ | ||
1804 | AssocReq->Timeout = Timeout; | ||
1805 | AssocReq->ListenIntv = ListenIntv; | ||
1806 | } | ||
1807 | |||
1808 | /* | ||
1809 | ========================================================================== | ||
1810 | Description: | ||
1811 | |||
1812 | IRQL = DISPATCH_LEVEL | ||
1813 | |||
1814 | ========================================================================== | ||
1815 | */ | ||
1816 | void DisassocParmFill(struct rt_rtmp_adapter *pAd, | ||
1817 | struct rt_mlme_disassoc_req *DisassocReq, | ||
1818 | u8 *pAddr, u16 Reason) | ||
1819 | { | ||
1820 | COPY_MAC_ADDR(DisassocReq->Addr, pAddr); | ||
1821 | DisassocReq->Reason = Reason; | ||
1822 | } | ||
1823 | |||
1824 | /* | ||
1825 | ======================================================================== | ||
1826 | |||
1827 | Routine Description: | ||
1828 | Check the out going frame, if this is an DHCP or ARP datagram | ||
1829 | will be duplicate another frame at low data rate transmit. | ||
1830 | |||
1831 | Arguments: | ||
1832 | pAd Pointer to our adapter | ||
1833 | pPacket Pointer to outgoing Ndis frame | ||
1834 | |||
1835 | Return Value: | ||
1836 | TRUE To be duplicate at Low data rate transmit. (1mb) | ||
1837 | FALSE Do nothing. | ||
1838 | |||
1839 | IRQL = DISPATCH_LEVEL | ||
1840 | |||
1841 | Note: | ||
1842 | |||
1843 | MAC header + IP Header + UDP Header | ||
1844 | 14 Bytes 20 Bytes | ||
1845 | |||
1846 | UDP Header | ||
1847 | 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15| | ||
1848 | Source Port | ||
1849 | 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31| | ||
1850 | Destination Port | ||
1851 | |||
1852 | port 0x43 means Bootstrap Protocol, server. | ||
1853 | Port 0x44 means Bootstrap Protocol, client. | ||
1854 | |||
1855 | ======================================================================== | ||
1856 | */ | ||
1857 | |||
1858 | BOOLEAN RTMPCheckDHCPFrame(struct rt_rtmp_adapter *pAd, void *pPacket) | ||
1859 | { | ||
1860 | struct rt_packet_info PacketInfo; | ||
1861 | unsigned long NumberOfBytesRead = 0; | ||
1862 | unsigned long CurrentOffset = 0; | ||
1863 | void *pVirtualAddress = NULL; | ||
1864 | u32 NdisBufferLength; | ||
1865 | u8 *pSrc; | ||
1866 | u16 Protocol; | ||
1867 | u8 ByteOffset36 = 0; | ||
1868 | u8 ByteOffset38 = 0; | ||
1869 | BOOLEAN ReadFirstParm = TRUE; | ||
1870 | |||
1871 | RTMP_QueryPacketInfo(pPacket, &PacketInfo, (u8 **) & pVirtualAddress, | ||
1872 | &NdisBufferLength); | ||
1873 | |||
1874 | NumberOfBytesRead += NdisBufferLength; | ||
1875 | pSrc = (u8 *)pVirtualAddress; | ||
1876 | Protocol = *(pSrc + 12) * 256 + *(pSrc + 13); | ||
1877 | |||
1878 | /* */ | ||
1879 | /* Check DHCP & BOOTP protocol */ | ||
1880 | /* */ | ||
1881 | while (NumberOfBytesRead <= PacketInfo.TotalPacketLength) { | ||
1882 | if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE)) { | ||
1883 | CurrentOffset = | ||
1884 | 35 - (NumberOfBytesRead - NdisBufferLength); | ||
1885 | ByteOffset36 = *(pSrc + CurrentOffset); | ||
1886 | ReadFirstParm = FALSE; | ||
1887 | } | ||
1888 | |||
1889 | if (NumberOfBytesRead >= 37) { | ||
1890 | CurrentOffset = | ||
1891 | 37 - (NumberOfBytesRead - NdisBufferLength); | ||
1892 | ByteOffset38 = *(pSrc + CurrentOffset); | ||
1893 | /*End of Read */ | ||
1894 | break; | ||
1895 | } | ||
1896 | return FALSE; | ||
1897 | } | ||
1898 | |||
1899 | /* Check for DHCP & BOOTP protocol */ | ||
1900 | if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43)) { | ||
1901 | /* */ | ||
1902 | /* 2054 (hex 0806) for ARP datagrams */ | ||
1903 | /* if this packet is not ARP datagrams, then do nothing */ | ||
1904 | /* ARP datagrams will also be duplicate at 1mb broadcast frames */ | ||
1905 | /* */ | ||
1906 | if (Protocol != 0x0806) | ||
1907 | return FALSE; | ||
1908 | } | ||
1909 | |||
1910 | return TRUE; | ||
1911 | } | ||
1912 | |||
1913 | BOOLEAN RTMPCheckEtherType(struct rt_rtmp_adapter *pAd, void *pPacket) | ||
1914 | { | ||
1915 | u16 TypeLen; | ||
1916 | u8 Byte0, Byte1; | ||
1917 | u8 *pSrcBuf; | ||
1918 | u32 pktLen; | ||
1919 | u16 srcPort, dstPort; | ||
1920 | BOOLEAN status = TRUE; | ||
1921 | |||
1922 | pSrcBuf = GET_OS_PKT_DATAPTR(pPacket); | ||
1923 | pktLen = GET_OS_PKT_LEN(pPacket); | ||
1924 | |||
1925 | ASSERT(pSrcBuf); | ||
1926 | |||
1927 | RTMP_SET_PACKET_SPECIFIC(pPacket, 0); | ||
1928 | |||
1929 | /* get Ethernet protocol field */ | ||
1930 | TypeLen = (pSrcBuf[12] << 8) | pSrcBuf[13]; | ||
1931 | |||
1932 | pSrcBuf += LENGTH_802_3; /* Skip the Ethernet Header. */ | ||
1933 | |||
1934 | if (TypeLen <= 1500) { /* 802.3, 802.3 LLC */ | ||
1935 | /* | ||
1936 | DestMAC(6) + SrcMAC(6) + Length(2) + | ||
1937 | DSAP(1) + SSAP(1) + Control(1) + | ||
1938 | if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header. | ||
1939 | => + SNAP (5, OriginationID(3) + etherType(2)) | ||
1940 | */ | ||
1941 | if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA | ||
1942 | && pSrcBuf[2] == 0x03) { | ||
1943 | Sniff2BytesFromNdisBuffer((char *)pSrcBuf, 6, | ||
1944 | &Byte0, &Byte1); | ||
1945 | RTMP_SET_PACKET_LLCSNAP(pPacket, 1); | ||
1946 | TypeLen = (u16)((Byte0 << 8) + Byte1); | ||
1947 | pSrcBuf += 8; /* Skip this LLC/SNAP header */ | ||
1948 | } else { | ||
1949 | /*It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it. */ | ||
1950 | } | ||
1951 | } | ||
1952 | /* If it's a VLAN packet, get the real Type/Length field. */ | ||
1953 | if (TypeLen == 0x8100) { | ||
1954 | /* 0x8100 means VLAN packets */ | ||
1955 | |||
1956 | /* Dest. MAC Address (6-bytes) + | ||
1957 | Source MAC Address (6-bytes) + | ||
1958 | Length/Type = 802.1Q Tag Type (2-byte) + | ||
1959 | Tag Control Information (2-bytes) + | ||
1960 | Length / Type (2-bytes) + | ||
1961 | data payload (0-n bytes) + | ||
1962 | Pad (0-p bytes) + | ||
1963 | Frame Check Sequence (4-bytes) */ | ||
1964 | |||
1965 | RTMP_SET_PACKET_VLAN(pPacket, 1); | ||
1966 | Sniff2BytesFromNdisBuffer((char *)pSrcBuf, 2, &Byte0, | ||
1967 | &Byte1); | ||
1968 | TypeLen = (u16)((Byte0 << 8) + Byte1); | ||
1969 | |||
1970 | pSrcBuf += 4; /* Skip the VLAN Header. */ | ||
1971 | } | ||
1972 | |||
1973 | switch (TypeLen) { | ||
1974 | case 0x0800: | ||
1975 | { | ||
1976 | ASSERT((pktLen > 34)); | ||
1977 | if (*(pSrcBuf + 9) == 0x11) { /* udp packet */ | ||
1978 | ASSERT((pktLen > 34)); /* 14 for ethernet header, 20 for IP header */ | ||
1979 | |||
1980 | pSrcBuf += 20; /* Skip the IP header */ | ||
1981 | srcPort = | ||
1982 | OS_NTOHS(get_unaligned | ||
1983 | ((u16 *)(pSrcBuf))); | ||
1984 | dstPort = | ||
1985 | OS_NTOHS(get_unaligned | ||
1986 | ((u16 *)(pSrcBuf + 2))); | ||
1987 | |||
1988 | if ((srcPort == 0x44 && dstPort == 0x43) || (srcPort == 0x43 && dstPort == 0x44)) { /*It's a BOOTP/DHCP packet */ | ||
1989 | RTMP_SET_PACKET_DHCP(pPacket, 1); | ||
1990 | } | ||
1991 | } | ||
1992 | } | ||
1993 | break; | ||
1994 | case 0x0806: | ||
1995 | { | ||
1996 | /*ARP Packet. */ | ||
1997 | RTMP_SET_PACKET_DHCP(pPacket, 1); | ||
1998 | } | ||
1999 | break; | ||
2000 | case 0x888e: | ||
2001 | { | ||
2002 | /* EAPOL Packet. */ | ||
2003 | RTMP_SET_PACKET_EAPOL(pPacket, 1); | ||
2004 | } | ||
2005 | break; | ||
2006 | default: | ||
2007 | status = FALSE; | ||
2008 | break; | ||
2009 | } | ||
2010 | |||
2011 | return status; | ||
2012 | |||
2013 | } | ||
2014 | |||
2015 | void Update_Rssi_Sample(struct rt_rtmp_adapter *pAd, | ||
2016 | struct rt_rssi_sample *pRssi, struct rt_rxwi * pRxWI) | ||
2017 | { | ||
2018 | char rssi0 = pRxWI->RSSI0; | ||
2019 | char rssi1 = pRxWI->RSSI1; | ||
2020 | char rssi2 = pRxWI->RSSI2; | ||
2021 | |||
2022 | if (rssi0 != 0) { | ||
2023 | pRssi->LastRssi0 = ConvertToRssi(pAd, (char)rssi0, RSSI_0); | ||
2024 | pRssi->AvgRssi0X8 = | ||
2025 | (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0; | ||
2026 | pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3; | ||
2027 | } | ||
2028 | |||
2029 | if (rssi1 != 0) { | ||
2030 | pRssi->LastRssi1 = ConvertToRssi(pAd, (char)rssi1, RSSI_1); | ||
2031 | pRssi->AvgRssi1X8 = | ||
2032 | (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1; | ||
2033 | pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3; | ||
2034 | } | ||
2035 | |||
2036 | if (rssi2 != 0) { | ||
2037 | pRssi->LastRssi2 = ConvertToRssi(pAd, (char)rssi2, RSSI_2); | ||
2038 | pRssi->AvgRssi2X8 = | ||
2039 | (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2; | ||
2040 | pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3; | ||
2041 | } | ||
2042 | } | ||
2043 | |||
2044 | /* Normal legacy Rx packet indication */ | ||
2045 | void Indicate_Legacy_Packet(struct rt_rtmp_adapter *pAd, | ||
2046 | struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID) | ||
2047 | { | ||
2048 | void *pRxPacket = pRxBlk->pRxPacket; | ||
2049 | u8 Header802_3[LENGTH_802_3]; | ||
2050 | |||
2051 | /* 1. get 802.3 Header */ | ||
2052 | /* 2. remove LLC */ | ||
2053 | /* a. pointer pRxBlk->pData to payload */ | ||
2054 | /* b. modify pRxBlk->DataSize */ | ||
2055 | RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); | ||
2056 | |||
2057 | if (pRxBlk->DataSize > MAX_RX_PKT_LEN) { | ||
2058 | |||
2059 | /* release packet */ | ||
2060 | RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); | ||
2061 | return; | ||
2062 | } | ||
2063 | |||
2064 | STATS_INC_RX_PACKETS(pAd, FromWhichBSSID); | ||
2065 | |||
2066 | #ifdef RTMP_MAC_USB | ||
2067 | if (pAd->CommonCfg.bDisableReordering == 0) { | ||
2068 | struct rt_ba_rec_entry *pBAEntry; | ||
2069 | unsigned long Now32; | ||
2070 | u8 Wcid = pRxBlk->pRxWI->WirelessCliID; | ||
2071 | u8 TID = pRxBlk->pRxWI->TID; | ||
2072 | u16 Idx; | ||
2073 | |||
2074 | #define REORDERING_PACKET_TIMEOUT ((100 * OS_HZ)/1000) /* system ticks -- 100 ms */ | ||
2075 | |||
2076 | if (Wcid < MAX_LEN_OF_MAC_TABLE) { | ||
2077 | Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; | ||
2078 | if (Idx != 0) { | ||
2079 | pBAEntry = &pAd->BATable.BARecEntry[Idx]; | ||
2080 | /* update last rx time */ | ||
2081 | NdisGetSystemUpTime(&Now32); | ||
2082 | if ((pBAEntry->list.qlen > 0) && | ||
2083 | RTMP_TIME_AFTER((unsigned long)Now32, | ||
2084 | (unsigned long)(pBAEntry-> | ||
2085 | LastIndSeqAtTimer | ||
2086 | + | ||
2087 | (REORDERING_PACKET_TIMEOUT))) | ||
2088 | ) { | ||
2089 | DBGPRINT(RT_DEBUG_OFF, | ||
2090 | ("Indicate_Legacy_Packet():flush reordering_timeout_mpdus! RxWI->Flags=%d, pRxWI.TID=%d, RxD->AMPDU=%d!\n", | ||
2091 | pRxBlk->Flags, | ||
2092 | pRxBlk->pRxWI->TID, | ||
2093 | pRxBlk->RxD.AMPDU)); | ||
2094 | hex_dump("Dump the legacy Packet:", | ||
2095 | GET_OS_PKT_DATAPTR(pRxBlk-> | ||
2096 | pRxPacket), | ||
2097 | 64); | ||
2098 | ba_flush_reordering_timeout_mpdus(pAd, | ||
2099 | pBAEntry, | ||
2100 | Now32); | ||
2101 | } | ||
2102 | } | ||
2103 | } | ||
2104 | } | ||
2105 | #endif /* RTMP_MAC_USB // */ | ||
2106 | |||
2107 | wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID); | ||
2108 | |||
2109 | /* */ | ||
2110 | /* pass this 802.3 packet to upper layer or forward this packet to WM directly */ | ||
2111 | /* */ | ||
2112 | ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID); | ||
2113 | } | ||
2114 | |||
2115 | /* Normal, AMPDU or AMSDU */ | ||
2116 | void CmmRxnonRalinkFrameIndicate(struct rt_rtmp_adapter *pAd, | ||
2117 | struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID) | ||
2118 | { | ||
2119 | if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) | ||
2120 | && (pAd->CommonCfg.bDisableReordering == 0)) { | ||
2121 | Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID); | ||
2122 | } else { | ||
2123 | if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) { | ||
2124 | /* handle A-MSDU */ | ||
2125 | Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID); | ||
2126 | } else { | ||
2127 | Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); | ||
2128 | } | ||
2129 | } | ||
2130 | } | ||
2131 | |||
2132 | void CmmRxRalinkFrameIndicate(struct rt_rtmp_adapter *pAd, | ||
2133 | struct rt_mac_table_entry *pEntry, | ||
2134 | struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID) | ||
2135 | { | ||
2136 | u8 Header802_3[LENGTH_802_3]; | ||
2137 | u16 Msdu2Size; | ||
2138 | u16 Payload1Size, Payload2Size; | ||
2139 | u8 *pData2; | ||
2140 | void *pPacket2 = NULL; | ||
2141 | |||
2142 | Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData + 1) << 8); | ||
2143 | |||
2144 | if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize)) { | ||
2145 | /* skip two byte MSDU2 len */ | ||
2146 | pRxBlk->pData += 2; | ||
2147 | pRxBlk->DataSize -= 2; | ||
2148 | } else { | ||
2149 | /* release packet */ | ||
2150 | RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, | ||
2151 | NDIS_STATUS_FAILURE); | ||
2152 | return; | ||
2153 | } | ||
2154 | |||
2155 | /* get 802.3 Header and remove LLC */ | ||
2156 | RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); | ||
2157 | |||
2158 | ASSERT(pRxBlk->pRxPacket); | ||
2159 | |||
2160 | /* Ralink Aggregation frame */ | ||
2161 | pAd->RalinkCounters.OneSecRxAggregationCount++; | ||
2162 | Payload1Size = pRxBlk->DataSize - Msdu2Size; | ||
2163 | Payload2Size = Msdu2Size - LENGTH_802_3; | ||
2164 | |||
2165 | pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3; | ||
2166 | |||
2167 | pPacket2 = | ||
2168 | duplicate_pkt(pAd, (pData2 - LENGTH_802_3), LENGTH_802_3, pData2, | ||
2169 | Payload2Size, FromWhichBSSID); | ||
2170 | |||
2171 | if (!pPacket2) { | ||
2172 | /* release packet */ | ||
2173 | RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, | ||
2174 | NDIS_STATUS_FAILURE); | ||
2175 | return; | ||
2176 | } | ||
2177 | /* update payload size of 1st packet */ | ||
2178 | pRxBlk->DataSize = Payload1Size; | ||
2179 | wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID); | ||
2180 | |||
2181 | ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, | ||
2182 | FromWhichBSSID); | ||
2183 | |||
2184 | if (pPacket2) { | ||
2185 | ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID); | ||
2186 | } | ||
2187 | } | ||
2188 | |||
2189 | #define RESET_FRAGFRAME(_fragFrame) \ | ||
2190 | { \ | ||
2191 | _fragFrame.RxSize = 0; \ | ||
2192 | _fragFrame.Sequence = 0; \ | ||
2193 | _fragFrame.LastFrag = 0; \ | ||
2194 | _fragFrame.Flags = 0; \ | ||
2195 | } | ||
2196 | |||
2197 | void *RTMPDeFragmentDataFrame(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk) | ||
2198 | { | ||
2199 | struct rt_header_802_11 * pHeader = pRxBlk->pHeader; | ||
2200 | void *pRxPacket = pRxBlk->pRxPacket; | ||
2201 | u8 *pData = pRxBlk->pData; | ||
2202 | u16 DataSize = pRxBlk->DataSize; | ||
2203 | void *pRetPacket = NULL; | ||
2204 | u8 *pFragBuffer = NULL; | ||
2205 | BOOLEAN bReassDone = FALSE; | ||
2206 | u8 HeaderRoom = 0; | ||
2207 | |||
2208 | ASSERT(pHeader); | ||
2209 | |||
2210 | HeaderRoom = pData - (u8 *) pHeader; | ||
2211 | |||
2212 | /* Re-assemble the fragmented packets */ | ||
2213 | if (pHeader->Frag == 0) /* Frag. Number is 0 : First frag or only one pkt */ | ||
2214 | { | ||
2215 | /* the first pkt of fragment, record it. */ | ||
2216 | if (pHeader->FC.MoreFrag) { | ||
2217 | ASSERT(pAd->FragFrame.pFragPacket); | ||
2218 | pFragBuffer = | ||
2219 | GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket); | ||
2220 | pAd->FragFrame.RxSize = DataSize + HeaderRoom; | ||
2221 | NdisMoveMemory(pFragBuffer, pHeader, | ||
2222 | pAd->FragFrame.RxSize); | ||
2223 | pAd->FragFrame.Sequence = pHeader->Sequence; | ||
2224 | pAd->FragFrame.LastFrag = pHeader->Frag; /* Should be 0 */ | ||
2225 | ASSERT(pAd->FragFrame.LastFrag == 0); | ||
2226 | goto done; /* end of processing this frame */ | ||
2227 | } | ||
2228 | } else /*Middle & End of fragment */ | ||
2229 | { | ||
2230 | if ((pHeader->Sequence != pAd->FragFrame.Sequence) || | ||
2231 | (pHeader->Frag != (pAd->FragFrame.LastFrag + 1))) { | ||
2232 | /* Fragment is not the same sequence or out of fragment number order */ | ||
2233 | /* Reset Fragment control blk */ | ||
2234 | RESET_FRAGFRAME(pAd->FragFrame); | ||
2235 | DBGPRINT(RT_DEBUG_ERROR, | ||
2236 | ("Fragment is not the same sequence or out of fragment number order.\n")); | ||
2237 | goto done; /* give up this frame */ | ||
2238 | } else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE) { | ||
2239 | /* Fragment frame is too large, it exeeds the maximum frame size. */ | ||
2240 | /* Reset Fragment control blk */ | ||
2241 | RESET_FRAGFRAME(pAd->FragFrame); | ||
2242 | DBGPRINT(RT_DEBUG_ERROR, | ||
2243 | ("Fragment frame is too large, it exeeds the maximum frame size.\n")); | ||
2244 | goto done; /* give up this frame */ | ||
2245 | } | ||
2246 | /* */ | ||
2247 | /* Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment. */ | ||
2248 | /* In this case, we will dropt it. */ | ||
2249 | /* */ | ||
2250 | if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H))) { | ||
2251 | DBGPRINT(RT_DEBUG_ERROR, | ||
2252 | ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", | ||
2253 | pHeader->Sequence, pHeader->Frag)); | ||
2254 | goto done; /* give up this frame */ | ||
2255 | } | ||
2256 | |||
2257 | pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket); | ||
2258 | |||
2259 | /* concatenate this fragment into the re-assembly buffer */ | ||
2260 | NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, | ||
2261 | DataSize); | ||
2262 | pAd->FragFrame.RxSize += DataSize; | ||
2263 | pAd->FragFrame.LastFrag = pHeader->Frag; /* Update fragment number */ | ||
2264 | |||
2265 | /* Last fragment */ | ||
2266 | if (pHeader->FC.MoreFrag == FALSE) { | ||
2267 | bReassDone = TRUE; | ||
2268 | } | ||
2269 | } | ||
2270 | |||
2271 | done: | ||
2272 | /* always release rx fragmented packet */ | ||
2273 | RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); | ||
2274 | |||
2275 | /* return defragmented packet if packet is reassembled completely */ | ||
2276 | /* otherwise return NULL */ | ||
2277 | if (bReassDone) { | ||
2278 | void *pNewFragPacket; | ||
2279 | |||
2280 | /* allocate a new packet buffer for fragment */ | ||
2281 | pNewFragPacket = | ||
2282 | RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); | ||
2283 | if (pNewFragPacket) { | ||
2284 | /* update RxBlk */ | ||
2285 | pRetPacket = pAd->FragFrame.pFragPacket; | ||
2286 | pAd->FragFrame.pFragPacket = pNewFragPacket; | ||
2287 | pRxBlk->pHeader = | ||
2288 | (struct rt_header_802_11 *) GET_OS_PKT_DATAPTR(pRetPacket); | ||
2289 | pRxBlk->pData = (u8 *) pRxBlk->pHeader + HeaderRoom; | ||
2290 | pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom; | ||
2291 | pRxBlk->pRxPacket = pRetPacket; | ||
2292 | } else { | ||
2293 | RESET_FRAGFRAME(pAd->FragFrame); | ||
2294 | } | ||
2295 | } | ||
2296 | |||
2297 | return pRetPacket; | ||
2298 | } | ||
2299 | |||
2300 | void Indicate_AMSDU_Packet(struct rt_rtmp_adapter *pAd, | ||
2301 | struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID) | ||
2302 | { | ||
2303 | u32 nMSDU; | ||
2304 | |||
2305 | update_os_packet_info(pAd, pRxBlk, FromWhichBSSID); | ||
2306 | RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID); | ||
2307 | nMSDU = | ||
2308 | deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, | ||
2309 | pRxBlk->DataSize); | ||
2310 | } | ||
2311 | |||
2312 | void Indicate_EAPOL_Packet(struct rt_rtmp_adapter *pAd, | ||
2313 | struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID) | ||
2314 | { | ||
2315 | struct rt_mac_table_entry *pEntry = NULL; | ||
2316 | |||
2317 | { | ||
2318 | pEntry = &pAd->MacTab.Content[BSSID_WCID]; | ||
2319 | STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); | ||
2320 | return; | ||
2321 | } | ||
2322 | |||
2323 | if (pEntry == NULL) { | ||
2324 | DBGPRINT(RT_DEBUG_WARN, | ||
2325 | ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n")); | ||
2326 | /* release packet */ | ||
2327 | RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, | ||
2328 | NDIS_STATUS_FAILURE); | ||
2329 | return; | ||
2330 | } | ||
2331 | } | ||
2332 | |||
2333 | #define BCN_TBTT_OFFSET 64 /*defer 64 us */ | ||
2334 | void ReSyncBeaconTime(struct rt_rtmp_adapter *pAd) | ||
2335 | { | ||
2336 | |||
2337 | u32 Offset; | ||
2338 | |||
2339 | Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET); | ||
2340 | |||
2341 | pAd->TbttTickCount++; | ||
2342 | |||
2343 | /* */ | ||
2344 | /* The updated BeaconInterval Value will affect Beacon Interval after two TBTT */ | ||
2345 | /* beacasue the original BeaconInterval had been loaded into next TBTT_TIMER */ | ||
2346 | /* */ | ||
2347 | if (Offset == (BCN_TBTT_OFFSET - 2)) { | ||
2348 | BCN_TIME_CFG_STRUC csr; | ||
2349 | RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); | ||
2350 | csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1; /* ASIC register in units of 1/16 TU = 64us */ | ||
2351 | RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); | ||
2352 | } else { | ||
2353 | if (Offset == (BCN_TBTT_OFFSET - 1)) { | ||
2354 | BCN_TIME_CFG_STRUC csr; | ||
2355 | |||
2356 | RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); | ||
2357 | csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; /* ASIC register in units of 1/16 TU */ | ||
2358 | RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); | ||
2359 | } | ||
2360 | } | ||
2361 | } | ||
diff --git a/drivers/staging/rt2860/common/cmm_data_pci.c b/drivers/staging/rt2860/common/cmm_data_pci.c deleted file mode 100644 index bef0bbd8cef..00000000000 --- a/drivers/staging/rt2860/common/cmm_data_pci.c +++ /dev/null | |||
@@ -1,1096 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | */ | ||
27 | |||
28 | /* | ||
29 | All functions in this file must be PCI-depended, or you should out your function | ||
30 | in other files. | ||
31 | |||
32 | */ | ||
33 | #include "../rt_config.h" | ||
34 | |||
35 | u16 RtmpPCI_WriteTxResource(struct rt_rtmp_adapter *pAd, | ||
36 | struct rt_tx_blk *pTxBlk, | ||
37 | IN BOOLEAN bIsLast, u16 * FreeNumber) | ||
38 | { | ||
39 | |||
40 | u8 *pDMAHeaderBufVA; | ||
41 | u16 TxIdx, RetTxIdx; | ||
42 | struct rt_txd * pTxD; | ||
43 | u32 BufBasePaLow; | ||
44 | struct rt_rtmp_tx_ring *pTxRing; | ||
45 | u16 hwHeaderLen; | ||
46 | |||
47 | /* */ | ||
48 | /* get Tx Ring Resource */ | ||
49 | /* */ | ||
50 | pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; | ||
51 | TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; | ||
52 | pDMAHeaderBufVA = (u8 *)pTxRing->Cell[TxIdx].DmaBuf.AllocVa; | ||
53 | BufBasePaLow = | ||
54 | RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); | ||
55 | |||
56 | /* copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer */ | ||
57 | if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) { | ||
58 | /*hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD; */ | ||
59 | hwHeaderLen = | ||
60 | pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + | ||
61 | pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD; | ||
62 | } else { | ||
63 | /*hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */ | ||
64 | hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; | ||
65 | } | ||
66 | NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, | ||
67 | TXINFO_SIZE + TXWI_SIZE + hwHeaderLen); | ||
68 | |||
69 | pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; | ||
70 | pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; | ||
71 | |||
72 | /* */ | ||
73 | /* build Tx Descriptor */ | ||
74 | /* */ | ||
75 | |||
76 | pTxD = (struct rt_txd *) pTxRing->Cell[TxIdx].AllocVa; | ||
77 | NdisZeroMemory(pTxD, TXD_SIZE); | ||
78 | |||
79 | pTxD->SDPtr0 = BufBasePaLow; | ||
80 | pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; /* include padding */ | ||
81 | pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE); | ||
82 | pTxD->SDLen1 = pTxBlk->SrcBufLen; | ||
83 | pTxD->LastSec0 = 0; | ||
84 | pTxD->LastSec1 = (bIsLast) ? 1 : 0; | ||
85 | |||
86 | RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); | ||
87 | |||
88 | RetTxIdx = TxIdx; | ||
89 | /* */ | ||
90 | /* Update Tx index */ | ||
91 | /* */ | ||
92 | INC_RING_INDEX(TxIdx, TX_RING_SIZE); | ||
93 | pTxRing->TxCpuIdx = TxIdx; | ||
94 | |||
95 | *FreeNumber -= 1; | ||
96 | |||
97 | return RetTxIdx; | ||
98 | } | ||
99 | |||
100 | u16 RtmpPCI_WriteSingleTxResource(struct rt_rtmp_adapter *pAd, | ||
101 | struct rt_tx_blk *pTxBlk, | ||
102 | IN BOOLEAN bIsLast, | ||
103 | u16 * FreeNumber) | ||
104 | { | ||
105 | |||
106 | u8 *pDMAHeaderBufVA; | ||
107 | u16 TxIdx, RetTxIdx; | ||
108 | struct rt_txd * pTxD; | ||
109 | u32 BufBasePaLow; | ||
110 | struct rt_rtmp_tx_ring *pTxRing; | ||
111 | u16 hwHeaderLen; | ||
112 | |||
113 | /* */ | ||
114 | /* get Tx Ring Resource */ | ||
115 | /* */ | ||
116 | pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; | ||
117 | TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; | ||
118 | pDMAHeaderBufVA = (u8 *)pTxRing->Cell[TxIdx].DmaBuf.AllocVa; | ||
119 | BufBasePaLow = | ||
120 | RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); | ||
121 | |||
122 | /* copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer */ | ||
123 | /*hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */ | ||
124 | hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; | ||
125 | |||
126 | NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, | ||
127 | TXINFO_SIZE + TXWI_SIZE + hwHeaderLen); | ||
128 | |||
129 | pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; | ||
130 | pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; | ||
131 | |||
132 | /* */ | ||
133 | /* build Tx Descriptor */ | ||
134 | /* */ | ||
135 | pTxD = (struct rt_txd *) pTxRing->Cell[TxIdx].AllocVa; | ||
136 | NdisZeroMemory(pTxD, TXD_SIZE); | ||
137 | |||
138 | pTxD->SDPtr0 = BufBasePaLow; | ||
139 | pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; /* include padding */ | ||
140 | pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE); | ||
141 | pTxD->SDLen1 = pTxBlk->SrcBufLen; | ||
142 | pTxD->LastSec0 = 0; | ||
143 | pTxD->LastSec1 = (bIsLast) ? 1 : 0; | ||
144 | |||
145 | RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); | ||
146 | |||
147 | RetTxIdx = TxIdx; | ||
148 | /* */ | ||
149 | /* Update Tx index */ | ||
150 | /* */ | ||
151 | INC_RING_INDEX(TxIdx, TX_RING_SIZE); | ||
152 | pTxRing->TxCpuIdx = TxIdx; | ||
153 | |||
154 | *FreeNumber -= 1; | ||
155 | |||
156 | return RetTxIdx; | ||
157 | } | ||
158 | |||
159 | u16 RtmpPCI_WriteMultiTxResource(struct rt_rtmp_adapter *pAd, | ||
160 | struct rt_tx_blk *pTxBlk, | ||
161 | u8 frameNum, u16 * FreeNumber) | ||
162 | { | ||
163 | BOOLEAN bIsLast; | ||
164 | u8 *pDMAHeaderBufVA; | ||
165 | u16 TxIdx, RetTxIdx; | ||
166 | struct rt_txd * pTxD; | ||
167 | u32 BufBasePaLow; | ||
168 | struct rt_rtmp_tx_ring *pTxRing; | ||
169 | u16 hwHdrLen; | ||
170 | u32 firstDMALen; | ||
171 | |||
172 | bIsLast = ((frameNum == (pTxBlk->TotalFrameNum - 1)) ? 1 : 0); | ||
173 | |||
174 | /* */ | ||
175 | /* get Tx Ring Resource */ | ||
176 | /* */ | ||
177 | pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; | ||
178 | TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; | ||
179 | pDMAHeaderBufVA = (u8 *)pTxRing->Cell[TxIdx].DmaBuf.AllocVa; | ||
180 | BufBasePaLow = | ||
181 | RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); | ||
182 | |||
183 | if (frameNum == 0) { | ||
184 | /* copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer */ | ||
185 | if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) | ||
186 | /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD; */ | ||
187 | hwHdrLen = | ||
188 | pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + | ||
189 | pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD; | ||
190 | else if (pTxBlk->TxFrameType == TX_RALINK_FRAME) | ||
191 | /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD; */ | ||
192 | hwHdrLen = | ||
193 | pTxBlk->MpduHeaderLen - | ||
194 | LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + | ||
195 | LENGTH_ARALINK_HEADER_FIELD; | ||
196 | else | ||
197 | /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */ | ||
198 | hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; | ||
199 | |||
200 | firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHdrLen; | ||
201 | } else { | ||
202 | firstDMALen = pTxBlk->MpduHeaderLen; | ||
203 | } | ||
204 | |||
205 | NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen); | ||
206 | |||
207 | pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; | ||
208 | pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; | ||
209 | |||
210 | /* */ | ||
211 | /* build Tx Descriptor */ | ||
212 | /* */ | ||
213 | pTxD = (struct rt_txd *) pTxRing->Cell[TxIdx].AllocVa; | ||
214 | NdisZeroMemory(pTxD, TXD_SIZE); | ||
215 | |||
216 | pTxD->SDPtr0 = BufBasePaLow; | ||
217 | pTxD->SDLen0 = firstDMALen; /* include padding */ | ||
218 | pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE); | ||
219 | pTxD->SDLen1 = pTxBlk->SrcBufLen; | ||
220 | pTxD->LastSec0 = 0; | ||
221 | pTxD->LastSec1 = (bIsLast) ? 1 : 0; | ||
222 | |||
223 | RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); | ||
224 | |||
225 | RetTxIdx = TxIdx; | ||
226 | /* */ | ||
227 | /* Update Tx index */ | ||
228 | /* */ | ||
229 | INC_RING_INDEX(TxIdx, TX_RING_SIZE); | ||
230 | pTxRing->TxCpuIdx = TxIdx; | ||
231 | |||
232 | *FreeNumber -= 1; | ||
233 | |||
234 | return RetTxIdx; | ||
235 | |||
236 | } | ||
237 | |||
238 | void RtmpPCI_FinalWriteTxResource(struct rt_rtmp_adapter *pAd, | ||
239 | struct rt_tx_blk *pTxBlk, | ||
240 | u16 totalMPDUSize, u16 FirstTxIdx) | ||
241 | { | ||
242 | |||
243 | struct rt_txwi * pTxWI; | ||
244 | struct rt_rtmp_tx_ring *pTxRing; | ||
245 | |||
246 | /* */ | ||
247 | /* get Tx Ring Resource */ | ||
248 | /* */ | ||
249 | pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; | ||
250 | pTxWI = (struct rt_txwi *) pTxRing->Cell[FirstTxIdx].DmaBuf.AllocVa; | ||
251 | pTxWI->MPDUtotalByteCount = totalMPDUSize; | ||
252 | |||
253 | } | ||
254 | |||
255 | void RtmpPCIDataLastTxIdx(struct rt_rtmp_adapter *pAd, | ||
256 | u8 QueIdx, u16 LastTxIdx) | ||
257 | { | ||
258 | struct rt_txd * pTxD; | ||
259 | struct rt_rtmp_tx_ring *pTxRing; | ||
260 | |||
261 | /* */ | ||
262 | /* get Tx Ring Resource */ | ||
263 | /* */ | ||
264 | pTxRing = &pAd->TxRing[QueIdx]; | ||
265 | |||
266 | /* */ | ||
267 | /* build Tx Descriptor */ | ||
268 | /* */ | ||
269 | pTxD = (struct rt_txd *) pTxRing->Cell[LastTxIdx].AllocVa; | ||
270 | |||
271 | pTxD->LastSec1 = 1; | ||
272 | |||
273 | } | ||
274 | |||
275 | u16 RtmpPCI_WriteFragTxResource(struct rt_rtmp_adapter *pAd, | ||
276 | struct rt_tx_blk *pTxBlk, | ||
277 | u8 fragNum, u16 * FreeNumber) | ||
278 | { | ||
279 | u8 *pDMAHeaderBufVA; | ||
280 | u16 TxIdx, RetTxIdx; | ||
281 | struct rt_txd * pTxD; | ||
282 | u32 BufBasePaLow; | ||
283 | struct rt_rtmp_tx_ring *pTxRing; | ||
284 | u16 hwHeaderLen; | ||
285 | u32 firstDMALen; | ||
286 | |||
287 | /* */ | ||
288 | /* Get Tx Ring Resource */ | ||
289 | /* */ | ||
290 | pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; | ||
291 | TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; | ||
292 | pDMAHeaderBufVA = (u8 *)pTxRing->Cell[TxIdx].DmaBuf.AllocVa; | ||
293 | BufBasePaLow = | ||
294 | RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); | ||
295 | |||
296 | /* */ | ||
297 | /* Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer */ | ||
298 | /* */ | ||
299 | /*hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */ | ||
300 | hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; | ||
301 | |||
302 | firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; | ||
303 | NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen); | ||
304 | |||
305 | /* */ | ||
306 | /* Build Tx Descriptor */ | ||
307 | /* */ | ||
308 | pTxD = (struct rt_txd *) pTxRing->Cell[TxIdx].AllocVa; | ||
309 | NdisZeroMemory(pTxD, TXD_SIZE); | ||
310 | |||
311 | if (fragNum == pTxBlk->TotalFragNum) { | ||
312 | pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; | ||
313 | pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; | ||
314 | } | ||
315 | |||
316 | pTxD->SDPtr0 = BufBasePaLow; | ||
317 | pTxD->SDLen0 = firstDMALen; /* include padding */ | ||
318 | pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE); | ||
319 | pTxD->SDLen1 = pTxBlk->SrcBufLen; | ||
320 | pTxD->LastSec0 = 0; | ||
321 | pTxD->LastSec1 = 1; | ||
322 | |||
323 | RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); | ||
324 | |||
325 | RetTxIdx = TxIdx; | ||
326 | pTxBlk->Priv += pTxBlk->SrcBufLen; | ||
327 | |||
328 | /* */ | ||
329 | /* Update Tx index */ | ||
330 | /* */ | ||
331 | INC_RING_INDEX(TxIdx, TX_RING_SIZE); | ||
332 | pTxRing->TxCpuIdx = TxIdx; | ||
333 | |||
334 | *FreeNumber -= 1; | ||
335 | |||
336 | return RetTxIdx; | ||
337 | |||
338 | } | ||
339 | |||
340 | /* | ||
341 | Must be run in Interrupt context | ||
342 | This function handle PCI specific TxDesc and cpu index update and kick the packet out. | ||
343 | */ | ||
344 | int RtmpPCIMgmtKickOut(struct rt_rtmp_adapter *pAd, | ||
345 | u8 QueIdx, | ||
346 | void *pPacket, | ||
347 | u8 *pSrcBufVA, u32 SrcBufLen) | ||
348 | { | ||
349 | struct rt_txd * pTxD; | ||
350 | unsigned long SwIdx = pAd->MgmtRing.TxCpuIdx; | ||
351 | |||
352 | pTxD = (struct rt_txd *) pAd->MgmtRing.Cell[SwIdx].AllocVa; | ||
353 | |||
354 | pAd->MgmtRing.Cell[SwIdx].pNdisPacket = pPacket; | ||
355 | pAd->MgmtRing.Cell[SwIdx].pNextNdisPacket = NULL; | ||
356 | |||
357 | RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_MGMT); | ||
358 | pTxD->LastSec0 = 1; | ||
359 | pTxD->LastSec1 = 1; | ||
360 | pTxD->DMADONE = 0; | ||
361 | pTxD->SDLen1 = 0; | ||
362 | pTxD->SDPtr0 = | ||
363 | PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE); | ||
364 | pTxD->SDLen0 = SrcBufLen; | ||
365 | |||
366 | /*================================================================== */ | ||
367 | /* DBGPRINT_RAW(RT_DEBUG_TRACE, ("MLMEHardTransmit\n")); | ||
368 | for (i = 0; i < (TXWI_SIZE+24); i++) | ||
369 | { | ||
370 | |||
371 | DBGPRINT_RAW(RT_DEBUG_TRACE, ("%x:", *(pSrcBufVA+i))); | ||
372 | if ( i%4 == 3) | ||
373 | DBGPRINT_RAW(RT_DEBUG_TRACE, (" :: ")); | ||
374 | if ( i%16 == 15) | ||
375 | DBGPRINT_RAW(RT_DEBUG_TRACE, ("\n ")); | ||
376 | } | ||
377 | DBGPRINT_RAW(RT_DEBUG_TRACE, ("\n "));*/ | ||
378 | /*======================================================================= */ | ||
379 | |||
380 | pAd->RalinkCounters.KickTxCount++; | ||
381 | pAd->RalinkCounters.OneSecTxDoneCount++; | ||
382 | |||
383 | /* Increase TX_CTX_IDX, but write to register later. */ | ||
384 | INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE); | ||
385 | |||
386 | RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx); | ||
387 | |||
388 | return 0; | ||
389 | } | ||
390 | |||
391 | /* | ||
392 | ======================================================================== | ||
393 | |||
394 | Routine Description: | ||
395 | Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound | ||
396 | |||
397 | Arguments: | ||
398 | pRxD Pointer to the Rx descriptor | ||
399 | |||
400 | Return Value: | ||
401 | NDIS_STATUS_SUCCESS No err | ||
402 | NDIS_STATUS_FAILURE Error | ||
403 | |||
404 | Note: | ||
405 | |||
406 | ======================================================================== | ||
407 | */ | ||
408 | int RTMPCheckRxError(struct rt_rtmp_adapter *pAd, | ||
409 | struct rt_header_802_11 * pHeader, | ||
410 | struct rt_rxwi * pRxWI, IN PRT28XX_RXD_STRUC pRxD) | ||
411 | { | ||
412 | struct rt_cipher_key *pWpaKey; | ||
413 | int dBm; | ||
414 | |||
415 | /* Phy errors & CRC errors */ | ||
416 | if ( /*(pRxD->PhyErr) || */ (pRxD->Crc)) { | ||
417 | /* Check RSSI for Noise Hist statistic collection. */ | ||
418 | dBm = (int)(pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta; | ||
419 | if (dBm <= -87) | ||
420 | pAd->StaCfg.RPIDensity[0] += 1; | ||
421 | else if (dBm <= -82) | ||
422 | pAd->StaCfg.RPIDensity[1] += 1; | ||
423 | else if (dBm <= -77) | ||
424 | pAd->StaCfg.RPIDensity[2] += 1; | ||
425 | else if (dBm <= -72) | ||
426 | pAd->StaCfg.RPIDensity[3] += 1; | ||
427 | else if (dBm <= -67) | ||
428 | pAd->StaCfg.RPIDensity[4] += 1; | ||
429 | else if (dBm <= -62) | ||
430 | pAd->StaCfg.RPIDensity[5] += 1; | ||
431 | else if (dBm <= -57) | ||
432 | pAd->StaCfg.RPIDensity[6] += 1; | ||
433 | else if (dBm > -57) | ||
434 | pAd->StaCfg.RPIDensity[7] += 1; | ||
435 | |||
436 | return (NDIS_STATUS_FAILURE); | ||
437 | } | ||
438 | /* Add Rx size to channel load counter, we should ignore error counts */ | ||
439 | pAd->StaCfg.CLBusyBytes += (pRxD->SDL0 + 14); | ||
440 | |||
441 | /* Drop ToDs promiscuous frame, it is opened due to CCX 2 channel load statistics */ | ||
442 | if (pHeader != NULL) { | ||
443 | if (pHeader->FC.ToDs) { | ||
444 | return (NDIS_STATUS_FAILURE); | ||
445 | } | ||
446 | } | ||
447 | /* Drop not U2M frames, can't's drop here because we will drop beacon in this case */ | ||
448 | /* I am kind of doubting the U2M bit operation */ | ||
449 | /* if (pRxD->U2M == 0) */ | ||
450 | /* return(NDIS_STATUS_FAILURE); */ | ||
451 | |||
452 | /* drop decyption fail frame */ | ||
453 | if (pRxD->CipherErr) { | ||
454 | if (pRxD->CipherErr == 2) { | ||
455 | DBGPRINT_RAW(RT_DEBUG_TRACE, | ||
456 | ("pRxD ERROR: ICV ok but MICErr ")); | ||
457 | } else if (pRxD->CipherErr == 1) { | ||
458 | DBGPRINT_RAW(RT_DEBUG_TRACE, ("pRxD ERROR: ICV Err ")); | ||
459 | } else if (pRxD->CipherErr == 3) | ||
460 | DBGPRINT_RAW(RT_DEBUG_TRACE, | ||
461 | ("pRxD ERROR: Key not valid ")); | ||
462 | |||
463 | if (((pRxD->CipherErr & 1) == 1) | ||
464 | && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd)) | ||
465 | RTMPSendWirelessEvent(pAd, IW_ICV_ERROR_EVENT_FLAG, | ||
466 | pAd->MacTab.Content[BSSID_WCID]. | ||
467 | Addr, BSS0, 0); | ||
468 | |||
469 | DBGPRINT_RAW(RT_DEBUG_TRACE, | ||
470 | (" %d (len=%d, Mcast=%d, MyBss=%d, Wcid=%d, KeyId=%d)\n", | ||
471 | pRxD->CipherErr, pRxD->SDL0, | ||
472 | pRxD->Mcast | pRxD->Bcast, pRxD->MyBss, | ||
473 | pRxWI->WirelessCliID, | ||
474 | /* CipherName[pRxD->CipherAlg], */ | ||
475 | pRxWI->KeyIndex)); | ||
476 | |||
477 | /* */ | ||
478 | /* MIC Error */ | ||
479 | /* */ | ||
480 | if (pRxD->CipherErr == 2) { | ||
481 | pWpaKey = &pAd->SharedKey[BSS0][pRxWI->KeyIndex]; | ||
482 | if (pAd->StaCfg.WpaSupplicantUP) | ||
483 | WpaSendMicFailureToWpaSupplicant(pAd, | ||
484 | (pWpaKey-> | ||
485 | Type == | ||
486 | PAIRWISEKEY) ? | ||
487 | TRUE : FALSE); | ||
488 | else | ||
489 | RTMPReportMicError(pAd, pWpaKey); | ||
490 | |||
491 | if (((pRxD->CipherErr & 2) == 2) | ||
492 | && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd)) | ||
493 | RTMPSendWirelessEvent(pAd, | ||
494 | IW_MIC_ERROR_EVENT_FLAG, | ||
495 | pAd->MacTab. | ||
496 | Content[BSSID_WCID].Addr, | ||
497 | BSS0, 0); | ||
498 | |||
499 | DBGPRINT_RAW(RT_DEBUG_ERROR, ("Rx MIC Value error\n")); | ||
500 | } | ||
501 | |||
502 | if (pHeader == NULL) | ||
503 | return (NDIS_STATUS_SUCCESS); | ||
504 | /*if ((pRxD->CipherAlg == CIPHER_AES) && | ||
505 | (pHeader->Sequence == pAd->FragFrame.Sequence)) | ||
506 | { | ||
507 | // | ||
508 | // Acceptable since the First FragFrame no CipherErr problem. | ||
509 | // | ||
510 | return(NDIS_STATUS_SUCCESS); | ||
511 | } */ | ||
512 | |||
513 | return (NDIS_STATUS_FAILURE); | ||
514 | } | ||
515 | |||
516 | return (NDIS_STATUS_SUCCESS); | ||
517 | } | ||
518 | |||
519 | BOOLEAN RTMPFreeTXDUponTxDmaDone(struct rt_rtmp_adapter *pAd, u8 QueIdx) | ||
520 | { | ||
521 | struct rt_rtmp_tx_ring *pTxRing; | ||
522 | struct rt_txd * pTxD; | ||
523 | void *pPacket; | ||
524 | u8 FREE = 0; | ||
525 | struct rt_txd TxD, *pOriTxD; | ||
526 | /*unsigned long IrqFlags; */ | ||
527 | BOOLEAN bReschedule = FALSE; | ||
528 | |||
529 | ASSERT(QueIdx < NUM_OF_TX_RING); | ||
530 | pTxRing = &pAd->TxRing[QueIdx]; | ||
531 | |||
532 | RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF, | ||
533 | &pTxRing->TxDmaIdx); | ||
534 | while (pTxRing->TxSwFreeIdx != pTxRing->TxDmaIdx) { | ||
535 | /* RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); */ | ||
536 | |||
537 | /* static rate also need NICUpdateFifoStaCounters() function. */ | ||
538 | /*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */ | ||
539 | NICUpdateFifoStaCounters(pAd); | ||
540 | |||
541 | /* Note : If (pAd->ate.bQATxStart == TRUE), we will never reach here. */ | ||
542 | FREE++; | ||
543 | pTxD = | ||
544 | (struct rt_txd *) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); | ||
545 | pOriTxD = pTxD; | ||
546 | NdisMoveMemory(&TxD, pTxD, sizeof(struct rt_txd)); | ||
547 | pTxD = &TxD; | ||
548 | |||
549 | pTxD->DMADONE = 0; | ||
550 | |||
551 | { | ||
552 | pPacket = | ||
553 | pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket; | ||
554 | if (pPacket) { | ||
555 | PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, | ||
556 | pTxD->SDLen1, | ||
557 | PCI_DMA_TODEVICE); | ||
558 | RELEASE_NDIS_PACKET(pAd, pPacket, | ||
559 | NDIS_STATUS_SUCCESS); | ||
560 | } | ||
561 | /*Always assign pNdisPacket as NULL after clear */ | ||
562 | pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket = NULL; | ||
563 | |||
564 | pPacket = | ||
565 | pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket; | ||
566 | |||
567 | ASSERT(pPacket == NULL); | ||
568 | if (pPacket) { | ||
569 | PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, | ||
570 | pTxD->SDLen1, | ||
571 | PCI_DMA_TODEVICE); | ||
572 | RELEASE_NDIS_PACKET(pAd, pPacket, | ||
573 | NDIS_STATUS_SUCCESS); | ||
574 | } | ||
575 | /*Always assign pNextNdisPacket as NULL after clear */ | ||
576 | pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = | ||
577 | NULL; | ||
578 | } | ||
579 | |||
580 | pAd->RalinkCounters.TransmittedByteCount += | ||
581 | (pTxD->SDLen1 + pTxD->SDLen0); | ||
582 | pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx]++; | ||
583 | INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); | ||
584 | /* get tx_tdx_idx again */ | ||
585 | RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF, | ||
586 | &pTxRing->TxDmaIdx); | ||
587 | NdisMoveMemory(pOriTxD, pTxD, sizeof(struct rt_txd)); | ||
588 | |||
589 | /* RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); */ | ||
590 | } | ||
591 | |||
592 | return bReschedule; | ||
593 | |||
594 | } | ||
595 | |||
596 | /* | ||
597 | ======================================================================== | ||
598 | |||
599 | Routine Description: | ||
600 | Process TX Rings DMA Done interrupt, running in DPC level | ||
601 | |||
602 | Arguments: | ||
603 | Adapter Pointer to our adapter | ||
604 | |||
605 | Return Value: | ||
606 | None | ||
607 | |||
608 | IRQL = DISPATCH_LEVEL | ||
609 | |||
610 | ======================================================================== | ||
611 | */ | ||
612 | BOOLEAN RTMPHandleTxRingDmaDoneInterrupt(struct rt_rtmp_adapter *pAd, | ||
613 | INT_SOURCE_CSR_STRUC TxRingBitmap) | ||
614 | { | ||
615 | /* u8 Count = 0; */ | ||
616 | unsigned long IrqFlags; | ||
617 | BOOLEAN bReschedule = FALSE; | ||
618 | |||
619 | /* Make sure Tx ring resource won't be used by other threads */ | ||
620 | /*NdisAcquireSpinLock(&pAd->TxRingLock); */ | ||
621 | |||
622 | RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); | ||
623 | |||
624 | if (TxRingBitmap.field.Ac0DmaDone) | ||
625 | bReschedule = RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BE); | ||
626 | |||
627 | if (TxRingBitmap.field.Ac3DmaDone) | ||
628 | bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VO); | ||
629 | |||
630 | if (TxRingBitmap.field.Ac2DmaDone) | ||
631 | bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VI); | ||
632 | |||
633 | if (TxRingBitmap.field.Ac1DmaDone) | ||
634 | bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BK); | ||
635 | |||
636 | /* Make sure to release Tx ring resource */ | ||
637 | /*NdisReleaseSpinLock(&pAd->TxRingLock); */ | ||
638 | RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); | ||
639 | |||
640 | /* Dequeue outgoing frames from TxSwQueue[] and process it */ | ||
641 | RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); | ||
642 | |||
643 | return bReschedule; | ||
644 | } | ||
645 | |||
646 | /* | ||
647 | ======================================================================== | ||
648 | |||
649 | Routine Description: | ||
650 | Process MGMT ring DMA done interrupt, running in DPC level | ||
651 | |||
652 | Arguments: | ||
653 | pAd Pointer to our adapter | ||
654 | |||
655 | Return Value: | ||
656 | None | ||
657 | |||
658 | IRQL = DISPATCH_LEVEL | ||
659 | |||
660 | Note: | ||
661 | |||
662 | ======================================================================== | ||
663 | */ | ||
664 | void RTMPHandleMgmtRingDmaDoneInterrupt(struct rt_rtmp_adapter *pAd) | ||
665 | { | ||
666 | struct rt_txd * pTxD; | ||
667 | void *pPacket; | ||
668 | /* int i; */ | ||
669 | u8 FREE = 0; | ||
670 | struct rt_rtmp_mgmt_ring *pMgmtRing = &pAd->MgmtRing; | ||
671 | |||
672 | NdisAcquireSpinLock(&pAd->MgmtRingLock); | ||
673 | |||
674 | RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pMgmtRing->TxDmaIdx); | ||
675 | while (pMgmtRing->TxSwFreeIdx != pMgmtRing->TxDmaIdx) { | ||
676 | FREE++; | ||
677 | pTxD = | ||
678 | (struct rt_txd *) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx]. | ||
679 | AllocVa); | ||
680 | pTxD->DMADONE = 0; | ||
681 | pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket; | ||
682 | |||
683 | if (pPacket) { | ||
684 | PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, | ||
685 | PCI_DMA_TODEVICE); | ||
686 | RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); | ||
687 | } | ||
688 | pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket = NULL; | ||
689 | |||
690 | pPacket = | ||
691 | pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket; | ||
692 | if (pPacket) { | ||
693 | PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, | ||
694 | PCI_DMA_TODEVICE); | ||
695 | RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); | ||
696 | } | ||
697 | pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket = NULL; | ||
698 | INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE); | ||
699 | |||
700 | } | ||
701 | NdisReleaseSpinLock(&pAd->MgmtRingLock); | ||
702 | |||
703 | } | ||
704 | |||
705 | /* | ||
706 | ======================================================================== | ||
707 | |||
708 | Routine Description: | ||
709 | Arguments: | ||
710 | Adapter Pointer to our adapter. Dequeue all power safe delayed braodcast frames after beacon. | ||
711 | |||
712 | IRQL = DISPATCH_LEVEL | ||
713 | |||
714 | ======================================================================== | ||
715 | */ | ||
716 | void RTMPHandleTBTTInterrupt(struct rt_rtmp_adapter *pAd) | ||
717 | { | ||
718 | { | ||
719 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) { | ||
720 | } | ||
721 | } | ||
722 | } | ||
723 | |||
724 | /* | ||
725 | ======================================================================== | ||
726 | |||
727 | Routine Description: | ||
728 | Arguments: | ||
729 | pAd Pointer to our adapter. Rewrite beacon content before next send-out. | ||
730 | |||
731 | IRQL = DISPATCH_LEVEL | ||
732 | |||
733 | ======================================================================== | ||
734 | */ | ||
735 | void RTMPHandlePreTBTTInterrupt(struct rt_rtmp_adapter *pAd) | ||
736 | { | ||
737 | { | ||
738 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) { | ||
739 | DBGPRINT(RT_DEBUG_TRACE, | ||
740 | ("RTMPHandlePreTBTTInterrupt...\n")); | ||
741 | } | ||
742 | } | ||
743 | |||
744 | } | ||
745 | |||
746 | void RTMPHandleRxCoherentInterrupt(struct rt_rtmp_adapter *pAd) | ||
747 | { | ||
748 | WPDMA_GLO_CFG_STRUC GloCfg; | ||
749 | |||
750 | if (pAd == NULL) { | ||
751 | DBGPRINT(RT_DEBUG_TRACE, ("====> pAd is NULL, return.\n")); | ||
752 | return; | ||
753 | } | ||
754 | |||
755 | DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPHandleRxCoherentInterrupt \n")); | ||
756 | |||
757 | RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); | ||
758 | |||
759 | GloCfg.field.EnTXWriteBackDDONE = 0; | ||
760 | GloCfg.field.EnableRxDMA = 0; | ||
761 | GloCfg.field.EnableTxDMA = 0; | ||
762 | RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); | ||
763 | |||
764 | RTMPRingCleanUp(pAd, QID_AC_BE); | ||
765 | RTMPRingCleanUp(pAd, QID_AC_BK); | ||
766 | RTMPRingCleanUp(pAd, QID_AC_VI); | ||
767 | RTMPRingCleanUp(pAd, QID_AC_VO); | ||
768 | RTMPRingCleanUp(pAd, QID_MGMT); | ||
769 | RTMPRingCleanUp(pAd, QID_RX); | ||
770 | |||
771 | RTMPEnableRxTx(pAd); | ||
772 | |||
773 | DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPHandleRxCoherentInterrupt \n")); | ||
774 | } | ||
775 | |||
776 | void *GetPacketFromRxRing(struct rt_rtmp_adapter *pAd, | ||
777 | OUT PRT28XX_RXD_STRUC pSaveRxD, | ||
778 | OUT BOOLEAN * pbReschedule, | ||
779 | IN u32 * pRxPending) | ||
780 | { | ||
781 | struct rt_rxd * pRxD; | ||
782 | void *pRxPacket = NULL; | ||
783 | void *pNewPacket; | ||
784 | void *AllocVa; | ||
785 | dma_addr_t AllocPa; | ||
786 | BOOLEAN bReschedule = FALSE; | ||
787 | struct rt_rtmp_dmacb *pRxCell; | ||
788 | |||
789 | RTMP_SEM_LOCK(&pAd->RxRingLock); | ||
790 | |||
791 | if (*pRxPending == 0) { | ||
792 | /* Get how may packets had been received */ | ||
793 | RTMP_IO_READ32(pAd, RX_DRX_IDX, &pAd->RxRing.RxDmaIdx); | ||
794 | |||
795 | if (pAd->RxRing.RxSwReadIdx == pAd->RxRing.RxDmaIdx) { | ||
796 | /* no more rx packets */ | ||
797 | bReschedule = FALSE; | ||
798 | goto done; | ||
799 | } | ||
800 | /* get rx pending count */ | ||
801 | if (pAd->RxRing.RxDmaIdx > pAd->RxRing.RxSwReadIdx) | ||
802 | *pRxPending = | ||
803 | pAd->RxRing.RxDmaIdx - pAd->RxRing.RxSwReadIdx; | ||
804 | else | ||
805 | *pRxPending = | ||
806 | pAd->RxRing.RxDmaIdx + RX_RING_SIZE - | ||
807 | pAd->RxRing.RxSwReadIdx; | ||
808 | |||
809 | } | ||
810 | |||
811 | pRxCell = &pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx]; | ||
812 | |||
813 | /* Point to Rx indexed rx ring descriptor */ | ||
814 | pRxD = (struct rt_rxd *) pRxCell->AllocVa; | ||
815 | |||
816 | if (pRxD->DDONE == 0) { | ||
817 | *pRxPending = 0; | ||
818 | /* DMAIndx had done but DDONE bit not ready */ | ||
819 | bReschedule = TRUE; | ||
820 | goto done; | ||
821 | } | ||
822 | |||
823 | /* return rx descriptor */ | ||
824 | NdisMoveMemory(pSaveRxD, pRxD, RXD_SIZE); | ||
825 | |||
826 | pNewPacket = | ||
827 | RTMP_AllocateRxPacketBuffer(pAd, RX_BUFFER_AGGRESIZE, FALSE, | ||
828 | &AllocVa, &AllocPa); | ||
829 | |||
830 | if (pNewPacket) { | ||
831 | /* unmap the rx buffer */ | ||
832 | PCI_UNMAP_SINGLE(pAd, pRxCell->DmaBuf.AllocPa, | ||
833 | pRxCell->DmaBuf.AllocSize, PCI_DMA_FROMDEVICE); | ||
834 | pRxPacket = pRxCell->pNdisPacket; | ||
835 | |||
836 | pRxCell->DmaBuf.AllocSize = RX_BUFFER_AGGRESIZE; | ||
837 | pRxCell->pNdisPacket = (void *)pNewPacket; | ||
838 | pRxCell->DmaBuf.AllocVa = AllocVa; | ||
839 | pRxCell->DmaBuf.AllocPa = AllocPa; | ||
840 | /* update SDP0 to new buffer of rx packet */ | ||
841 | pRxD->SDP0 = AllocPa; | ||
842 | } else { | ||
843 | /*DBGPRINT(RT_DEBUG_TRACE,("No Rx Buffer\n")); */ | ||
844 | pRxPacket = NULL; | ||
845 | bReschedule = TRUE; | ||
846 | } | ||
847 | |||
848 | pRxD->DDONE = 0; | ||
849 | |||
850 | /* had handled one rx packet */ | ||
851 | *pRxPending = *pRxPending - 1; | ||
852 | |||
853 | /* update rx descriptor and kick rx */ | ||
854 | INC_RING_INDEX(pAd->RxRing.RxSwReadIdx, RX_RING_SIZE); | ||
855 | |||
856 | pAd->RxRing.RxCpuIdx = | ||
857 | (pAd->RxRing.RxSwReadIdx == | ||
858 | 0) ? (RX_RING_SIZE - 1) : (pAd->RxRing.RxSwReadIdx - 1); | ||
859 | RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); | ||
860 | |||
861 | done: | ||
862 | RTMP_SEM_UNLOCK(&pAd->RxRingLock); | ||
863 | *pbReschedule = bReschedule; | ||
864 | return pRxPacket; | ||
865 | } | ||
866 | |||
867 | int MlmeHardTransmitTxRing(struct rt_rtmp_adapter *pAd, | ||
868 | u8 QueIdx, void *pPacket) | ||
869 | { | ||
870 | struct rt_packet_info PacketInfo; | ||
871 | u8 *pSrcBufVA; | ||
872 | u32 SrcBufLen; | ||
873 | struct rt_txd * pTxD; | ||
874 | struct rt_header_802_11 * pHeader_802_11; | ||
875 | BOOLEAN bAckRequired, bInsertTimestamp; | ||
876 | unsigned long SrcBufPA; | ||
877 | /*u8 TxBufIdx; */ | ||
878 | u8 MlmeRate; | ||
879 | unsigned long SwIdx = pAd->TxRing[QueIdx].TxCpuIdx; | ||
880 | struct rt_txwi * pFirstTxWI; | ||
881 | /*unsigned long i; */ | ||
882 | /*HTTRANSMIT_SETTING MlmeTransmit; //Rate for this MGMT frame. */ | ||
883 | unsigned long FreeNum; | ||
884 | struct rt_mac_table_entry *pMacEntry = NULL; | ||
885 | |||
886 | RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); | ||
887 | |||
888 | if (pSrcBufVA == NULL) { | ||
889 | /* The buffer shouldn't be NULL */ | ||
890 | return NDIS_STATUS_FAILURE; | ||
891 | } | ||
892 | /* Make sure MGMT ring resource won't be used by other threads */ | ||
893 | /*NdisAcquireSpinLock(&pAd->TxRingLock); */ | ||
894 | |||
895 | FreeNum = GET_TXRING_FREENO(pAd, QueIdx); | ||
896 | |||
897 | if (FreeNum == 0) { | ||
898 | /*NdisReleaseSpinLock(&pAd->TxRingLock); */ | ||
899 | return NDIS_STATUS_FAILURE; | ||
900 | } | ||
901 | |||
902 | SwIdx = pAd->TxRing[QueIdx].TxCpuIdx; | ||
903 | |||
904 | pTxD = (struct rt_txd *) pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa; | ||
905 | |||
906 | if (pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket) { | ||
907 | DBGPRINT(RT_DEBUG_OFF, ("MlmeHardTransmit Error\n")); | ||
908 | /*NdisReleaseSpinLock(&pAd->TxRingLock); */ | ||
909 | return NDIS_STATUS_FAILURE; | ||
910 | } | ||
911 | |||
912 | { | ||
913 | /* outgoing frame always wakeup PHY to prevent frame lost */ | ||
914 | /* if (pAd->StaCfg.Psm == PWR_SAVE) */ | ||
915 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) | ||
916 | AsicForceWakeup(pAd, TRUE); | ||
917 | } | ||
918 | pFirstTxWI = (struct rt_txwi *) pSrcBufVA; | ||
919 | |||
920 | pHeader_802_11 = (struct rt_header_802_11 *) (pSrcBufVA + TXWI_SIZE); | ||
921 | if (pHeader_802_11->Addr1[0] & 0x01) { | ||
922 | MlmeRate = pAd->CommonCfg.BasicMlmeRate; | ||
923 | } else { | ||
924 | MlmeRate = pAd->CommonCfg.MlmeRate; | ||
925 | } | ||
926 | |||
927 | if ((pHeader_802_11->FC.Type == BTYPE_DATA) && | ||
928 | (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) { | ||
929 | pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); | ||
930 | } | ||
931 | /* Verify Mlme rate for a / g bands. */ | ||
932 | if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) /* 11A band */ | ||
933 | MlmeRate = RATE_6; | ||
934 | |||
935 | /* */ | ||
936 | /* Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE) */ | ||
937 | /* Snice it's been set to 0 while on MgtMacHeaderInit */ | ||
938 | /* By the way this will cause frame to be send on PWR_SAVE failed. */ | ||
939 | /* */ | ||
940 | /* */ | ||
941 | /* In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame */ | ||
942 | /* Data-Null packets also pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD */ | ||
943 | if (pHeader_802_11->FC.Type != BTYPE_DATA) { | ||
944 | if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_REQ) | ||
945 | || !(pAd->CommonCfg.bAPSDCapable | ||
946 | && pAd->CommonCfg.APEdcaParm.bAPSDCapable)) { | ||
947 | pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; | ||
948 | } else { | ||
949 | pHeader_802_11->FC.PwrMgmt = | ||
950 | pAd->CommonCfg.bAPSDForcePowerSave; | ||
951 | } | ||
952 | } | ||
953 | |||
954 | bInsertTimestamp = FALSE; | ||
955 | if (pHeader_802_11->FC.Type == BTYPE_CNTL) /* must be PS-POLL */ | ||
956 | { | ||
957 | bAckRequired = FALSE; | ||
958 | } else /* BTYPE_MGMT or BTYPE_DATA(must be NULL frame) */ | ||
959 | { | ||
960 | if (pHeader_802_11->Addr1[0] & 0x01) /* MULTICAST, BROADCAST */ | ||
961 | { | ||
962 | bAckRequired = FALSE; | ||
963 | pHeader_802_11->Duration = 0; | ||
964 | } else { | ||
965 | bAckRequired = TRUE; | ||
966 | pHeader_802_11->Duration = | ||
967 | RTMPCalcDuration(pAd, MlmeRate, 14); | ||
968 | if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP) { | ||
969 | bInsertTimestamp = TRUE; | ||
970 | } | ||
971 | } | ||
972 | } | ||
973 | pHeader_802_11->Sequence = pAd->Sequence++; | ||
974 | if (pAd->Sequence > 0xfff) | ||
975 | pAd->Sequence = 0; | ||
976 | /* Before radar detection done, mgmt frame can not be sent but probe req */ | ||
977 | /* Because we need to use probe req to trigger driver to send probe req in passive scan */ | ||
978 | if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ) | ||
979 | && (pAd->CommonCfg.bIEEE80211H == 1) | ||
980 | && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)) { | ||
981 | DBGPRINT(RT_DEBUG_ERROR, | ||
982 | ("MlmeHardTransmit --> radar detect not in normal mode!\n")); | ||
983 | /*NdisReleaseSpinLock(&pAd->TxRingLock); */ | ||
984 | return (NDIS_STATUS_FAILURE); | ||
985 | } | ||
986 | /* */ | ||
987 | /* fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET */ | ||
988 | /* should always has only one ohysical buffer, and the whole frame size equals */ | ||
989 | /* to the first scatter buffer size */ | ||
990 | /* */ | ||
991 | |||
992 | /* Initialize TX Descriptor */ | ||
993 | /* For inter-frame gap, the number is for this frame and next frame */ | ||
994 | /* For MLME rate, we will fix as 2Mb to match other vendor's implement */ | ||
995 | /* pAd->CommonCfg.MlmeTransmit.field.MODE = 1; */ | ||
996 | |||
997 | /* management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not. */ | ||
998 | /* Only beacon use Nseq=TRUE. So here we use Nseq=FALSE. */ | ||
999 | if (pMacEntry == NULL) { | ||
1000 | RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, | ||
1001 | FALSE, bAckRequired, FALSE, 0, RESERVED_WCID, | ||
1002 | (SrcBufLen - TXWI_SIZE), PID_MGMT, 0, | ||
1003 | (u8)pAd->CommonCfg.MlmeTransmit.field.MCS, | ||
1004 | IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit); | ||
1005 | } else { | ||
1006 | RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, | ||
1007 | bInsertTimestamp, FALSE, bAckRequired, FALSE, | ||
1008 | 0, pMacEntry->Aid, (SrcBufLen - TXWI_SIZE), | ||
1009 | pMacEntry->MaxHTPhyMode.field.MCS, 0, | ||
1010 | (u8)pMacEntry->MaxHTPhyMode.field.MCS, | ||
1011 | IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode); | ||
1012 | } | ||
1013 | |||
1014 | pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket = pPacket; | ||
1015 | pAd->TxRing[QueIdx].Cell[SwIdx].pNextNdisPacket = NULL; | ||
1016 | /* pFirstTxWI->MPDUtotalByteCount = SrcBufLen - TXWI_SIZE; */ | ||
1017 | SrcBufPA = | ||
1018 | PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE); | ||
1019 | |||
1020 | RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_EDCA); | ||
1021 | pTxD->LastSec0 = 1; | ||
1022 | pTxD->LastSec1 = 1; | ||
1023 | pTxD->SDLen0 = SrcBufLen; | ||
1024 | pTxD->SDLen1 = 0; | ||
1025 | pTxD->SDPtr0 = SrcBufPA; | ||
1026 | pTxD->DMADONE = 0; | ||
1027 | |||
1028 | pAd->RalinkCounters.KickTxCount++; | ||
1029 | pAd->RalinkCounters.OneSecTxDoneCount++; | ||
1030 | |||
1031 | /* Increase TX_CTX_IDX, but write to register later. */ | ||
1032 | INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE); | ||
1033 | |||
1034 | RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx * 0x10, | ||
1035 | pAd->TxRing[QueIdx].TxCpuIdx); | ||
1036 | |||
1037 | /* Make sure to release MGMT ring resource */ | ||
1038 | /* NdisReleaseSpinLock(&pAd->TxRingLock); */ | ||
1039 | |||
1040 | return NDIS_STATUS_SUCCESS; | ||
1041 | } | ||
1042 | |||
1043 | int MlmeDataHardTransmit(struct rt_rtmp_adapter *pAd, | ||
1044 | u8 QueIdx, void *pPacket) | ||
1045 | { | ||
1046 | if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) | ||
1047 | ) { | ||
1048 | return NDIS_STATUS_FAILURE; | ||
1049 | } | ||
1050 | |||
1051 | return MlmeHardTransmitTxRing(pAd, QueIdx, pPacket); | ||
1052 | } | ||
1053 | |||
1054 | /* | ||
1055 | ======================================================================== | ||
1056 | |||
1057 | Routine Description: | ||
1058 | Calculates the duration which is required to transmit out frames | ||
1059 | with given size and specified rate. | ||
1060 | |||
1061 | Arguments: | ||
1062 | pTxD Pointer to transmit descriptor | ||
1063 | Ack Setting for Ack requirement bit | ||
1064 | Fragment Setting for Fragment bit | ||
1065 | RetryMode Setting for retry mode | ||
1066 | Ifs Setting for IFS gap | ||
1067 | Rate Setting for transmit rate | ||
1068 | Service Setting for service | ||
1069 | Length Frame length | ||
1070 | TxPreamble Short or Long preamble when using CCK rates | ||
1071 | QueIdx - 0-3, according to 802.11e/d4.4 June/2003 | ||
1072 | |||
1073 | Return Value: | ||
1074 | None | ||
1075 | |||
1076 | IRQL = PASSIVE_LEVEL | ||
1077 | IRQL = DISPATCH_LEVEL | ||
1078 | |||
1079 | ======================================================================== | ||
1080 | */ | ||
1081 | void RTMPWriteTxDescriptor(struct rt_rtmp_adapter *pAd, | ||
1082 | struct rt_txd * pTxD, | ||
1083 | IN BOOLEAN bWIV, u8 QueueSEL) | ||
1084 | { | ||
1085 | /* */ | ||
1086 | /* Always use Long preamble before verifiation short preamble functionality works well. */ | ||
1087 | /* Todo: remove the following line if short preamble functionality works */ | ||
1088 | /* */ | ||
1089 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); | ||
1090 | |||
1091 | pTxD->WIV = (bWIV) ? 1 : 0; | ||
1092 | pTxD->QSEL = (QueueSEL); | ||
1093 | /*RT2860c?? fixed using EDCA queue for test... We doubt Queue1 has problem. 2006-09-26 Jan */ | ||
1094 | /*pTxD->QSEL= FIFO_EDCA; */ | ||
1095 | pTxD->DMADONE = 0; | ||
1096 | } | ||
diff --git a/drivers/staging/rt2860/common/cmm_data_usb.c b/drivers/staging/rt2860/common/cmm_data_usb.c deleted file mode 100644 index 5637857ae9e..00000000000 --- a/drivers/staging/rt2860/common/cmm_data_usb.c +++ /dev/null | |||
@@ -1,951 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | */ | ||
27 | |||
28 | /* | ||
29 | All functions in this file must be USB-depended, or you should out your function | ||
30 | in other files. | ||
31 | |||
32 | */ | ||
33 | |||
34 | #ifdef RTMP_MAC_USB | ||
35 | |||
36 | #include "../rt_config.h" | ||
37 | |||
38 | /* | ||
39 | We can do copy the frame into pTxContext when match following conditions. | ||
40 | => | ||
41 | => | ||
42 | => | ||
43 | */ | ||
44 | static inline int RtmpUSBCanDoWrite(struct rt_rtmp_adapter *pAd, | ||
45 | u8 QueIdx, | ||
46 | struct rt_ht_tx_context *pHTTXContext) | ||
47 | { | ||
48 | int canWrite = NDIS_STATUS_RESOURCES; | ||
49 | |||
50 | if (((pHTTXContext->CurWritePosition) < | ||
51 | pHTTXContext->NextBulkOutPosition) | ||
52 | && (pHTTXContext->CurWritePosition + LOCAL_TXBUF_SIZE) > | ||
53 | pHTTXContext->NextBulkOutPosition) { | ||
54 | DBGPRINT(RT_DEBUG_ERROR, ("RtmpUSBCanDoWrite c1!\n")); | ||
55 | RTUSB_SET_BULK_FLAG(pAd, | ||
56 | (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx)); | ||
57 | } else if ((pHTTXContext->CurWritePosition == 8) | ||
58 | && (pHTTXContext->NextBulkOutPosition < LOCAL_TXBUF_SIZE)) { | ||
59 | DBGPRINT(RT_DEBUG_ERROR, ("RtmpUSBCanDoWrite c2!\n")); | ||
60 | RTUSB_SET_BULK_FLAG(pAd, | ||
61 | (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx)); | ||
62 | } else if (pHTTXContext->bCurWriting == TRUE) { | ||
63 | DBGPRINT(RT_DEBUG_ERROR, ("RtmpUSBCanDoWrite c3!\n")); | ||
64 | } else { | ||
65 | canWrite = NDIS_STATUS_SUCCESS; | ||
66 | } | ||
67 | |||
68 | return canWrite; | ||
69 | } | ||
70 | |||
71 | u16 RtmpUSB_WriteSubTxResource(struct rt_rtmp_adapter *pAd, | ||
72 | struct rt_tx_blk *pTxBlk, | ||
73 | IN BOOLEAN bIsLast, u16 * FreeNumber) | ||
74 | { | ||
75 | |||
76 | /* Dummy function. Should be removed in the future. */ | ||
77 | return 0; | ||
78 | |||
79 | } | ||
80 | |||
81 | u16 RtmpUSB_WriteFragTxResource(struct rt_rtmp_adapter *pAd, | ||
82 | struct rt_tx_blk *pTxBlk, | ||
83 | u8 fragNum, u16 * FreeNumber) | ||
84 | { | ||
85 | struct rt_ht_tx_context *pHTTXContext; | ||
86 | u16 hwHdrLen; /* The hwHdrLen consist of 802.11 header length plus the header padding length. */ | ||
87 | u32 fillOffset; | ||
88 | struct rt_txinfo *pTxInfo; | ||
89 | struct rt_txwi *pTxWI; | ||
90 | u8 *pWirelessPacket = NULL; | ||
91 | u8 QueIdx; | ||
92 | int Status; | ||
93 | unsigned long IrqFlags; | ||
94 | u32 USBDMApktLen = 0, DMAHdrLen, padding; | ||
95 | BOOLEAN TxQLastRound = FALSE; | ||
96 | |||
97 | /* */ | ||
98 | /* get Tx Ring Resource & Dma Buffer address */ | ||
99 | /* */ | ||
100 | QueIdx = pTxBlk->QueIdx; | ||
101 | pHTTXContext = &pAd->TxContext[QueIdx]; | ||
102 | |||
103 | RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); | ||
104 | |||
105 | pHTTXContext = &pAd->TxContext[QueIdx]; | ||
106 | fillOffset = pHTTXContext->CurWritePosition; | ||
107 | |||
108 | if (fragNum == 0) { | ||
109 | /* Check if we have enough space for this bulk-out batch. */ | ||
110 | Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); | ||
111 | if (Status == NDIS_STATUS_SUCCESS) { | ||
112 | pHTTXContext->bCurWriting = TRUE; | ||
113 | |||
114 | /* Reserve space for 8 bytes padding. */ | ||
115 | if ((pHTTXContext->ENextBulkOutPosition == | ||
116 | pHTTXContext->CurWritePosition)) { | ||
117 | pHTTXContext->ENextBulkOutPosition += 8; | ||
118 | pHTTXContext->CurWritePosition += 8; | ||
119 | fillOffset += 8; | ||
120 | } | ||
121 | pTxBlk->Priv = 0; | ||
122 | pHTTXContext->CurWriteRealPos = | ||
123 | pHTTXContext->CurWritePosition; | ||
124 | } else { | ||
125 | RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], | ||
126 | IrqFlags); | ||
127 | |||
128 | RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, | ||
129 | NDIS_STATUS_FAILURE); | ||
130 | return (Status); | ||
131 | } | ||
132 | } else { | ||
133 | /* For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer. */ | ||
134 | Status = | ||
135 | ((pHTTXContext->bCurWriting == | ||
136 | TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE); | ||
137 | if (Status == NDIS_STATUS_SUCCESS) { | ||
138 | fillOffset += pTxBlk->Priv; | ||
139 | } else { | ||
140 | RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], | ||
141 | IrqFlags); | ||
142 | |||
143 | RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, | ||
144 | NDIS_STATUS_FAILURE); | ||
145 | return (Status); | ||
146 | } | ||
147 | } | ||
148 | |||
149 | NdisZeroMemory((u8 *)(&pTxBlk->HeaderBuf[0]), TXINFO_SIZE); | ||
150 | pTxInfo = (struct rt_txinfo *)(&pTxBlk->HeaderBuf[0]); | ||
151 | pTxWI = (struct rt_txwi *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]); | ||
152 | |||
153 | pWirelessPacket = | ||
154 | &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; | ||
155 | |||
156 | /* copy TXWI + WLAN Header + LLC into DMA Header Buffer */ | ||
157 | /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */ | ||
158 | hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; | ||
159 | |||
160 | /* Build our URB for USBD */ | ||
161 | DMAHdrLen = TXWI_SIZE + hwHdrLen; | ||
162 | USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen; | ||
163 | padding = (4 - (USBDMApktLen % 4)) & 0x03; /* round up to 4 byte alignment */ | ||
164 | USBDMApktLen += padding; | ||
165 | |||
166 | pTxBlk->Priv += (TXINFO_SIZE + USBDMApktLen); | ||
167 | |||
168 | /* For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload */ | ||
169 | RTMPWriteTxInfo(pAd, pTxInfo, (u16)(USBDMApktLen), FALSE, FIFO_EDCA, | ||
170 | FALSE /*NextValid */ , FALSE); | ||
171 | |||
172 | if (fragNum == pTxBlk->TotalFragNum) { | ||
173 | pTxInfo->USBDMATxburst = 0; | ||
174 | if ((pHTTXContext->CurWritePosition + pTxBlk->Priv + 3906) > | ||
175 | MAX_TXBULK_LIMIT) { | ||
176 | pTxInfo->SwUseLastRound = 1; | ||
177 | TxQLastRound = TRUE; | ||
178 | } | ||
179 | } else { | ||
180 | pTxInfo->USBDMATxburst = 1; | ||
181 | } | ||
182 | |||
183 | NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, | ||
184 | TXINFO_SIZE + TXWI_SIZE + hwHdrLen); | ||
185 | pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); | ||
186 | pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); | ||
187 | |||
188 | RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); | ||
189 | |||
190 | NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); | ||
191 | |||
192 | /* Zero the last padding. */ | ||
193 | pWirelessPacket += pTxBlk->SrcBufLen; | ||
194 | NdisZeroMemory(pWirelessPacket, padding + 8); | ||
195 | |||
196 | if (fragNum == pTxBlk->TotalFragNum) { | ||
197 | RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); | ||
198 | |||
199 | /* Update the pHTTXContext->CurWritePosition. 3906 used to prevent the NextBulkOut is a A-RALINK/A-MSDU Frame. */ | ||
200 | pHTTXContext->CurWritePosition += pTxBlk->Priv; | ||
201 | if (TxQLastRound == TRUE) | ||
202 | pHTTXContext->CurWritePosition = 8; | ||
203 | pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; | ||
204 | |||
205 | /* Finally, set bCurWriting as FALSE */ | ||
206 | pHTTXContext->bCurWriting = FALSE; | ||
207 | |||
208 | RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); | ||
209 | |||
210 | /* succeed and release the skb buffer */ | ||
211 | RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); | ||
212 | } | ||
213 | |||
214 | return (Status); | ||
215 | |||
216 | } | ||
217 | |||
218 | u16 RtmpUSB_WriteSingleTxResource(struct rt_rtmp_adapter *pAd, | ||
219 | struct rt_tx_blk *pTxBlk, | ||
220 | IN BOOLEAN bIsLast, | ||
221 | u16 * FreeNumber) | ||
222 | { | ||
223 | struct rt_ht_tx_context *pHTTXContext; | ||
224 | u16 hwHdrLen; | ||
225 | u32 fillOffset; | ||
226 | struct rt_txinfo *pTxInfo; | ||
227 | struct rt_txwi *pTxWI; | ||
228 | u8 *pWirelessPacket; | ||
229 | u8 QueIdx; | ||
230 | unsigned long IrqFlags; | ||
231 | int Status; | ||
232 | u32 USBDMApktLen = 0, DMAHdrLen, padding; | ||
233 | BOOLEAN bTxQLastRound = FALSE; | ||
234 | |||
235 | /* For USB, didn't need PCI_MAP_SINGLE() */ | ||
236 | /*SrcBufPA = PCI_MAP_SINGLE(pAd, (char *) pTxBlk->pSrcBufData, pTxBlk->SrcBufLen, PCI_DMA_TODEVICE); */ | ||
237 | |||
238 | /* */ | ||
239 | /* get Tx Ring Resource & Dma Buffer address */ | ||
240 | /* */ | ||
241 | QueIdx = pTxBlk->QueIdx; | ||
242 | |||
243 | RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); | ||
244 | pHTTXContext = &pAd->TxContext[QueIdx]; | ||
245 | fillOffset = pHTTXContext->CurWritePosition; | ||
246 | |||
247 | /* Check ring full. */ | ||
248 | Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); | ||
249 | if (Status == NDIS_STATUS_SUCCESS) { | ||
250 | pHTTXContext->bCurWriting = TRUE; | ||
251 | |||
252 | pTxInfo = (struct rt_txinfo *)(&pTxBlk->HeaderBuf[0]); | ||
253 | pTxWI = (struct rt_txwi *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]); | ||
254 | |||
255 | /* Reserve space for 8 bytes padding. */ | ||
256 | if ((pHTTXContext->ENextBulkOutPosition == | ||
257 | pHTTXContext->CurWritePosition)) { | ||
258 | pHTTXContext->ENextBulkOutPosition += 8; | ||
259 | pHTTXContext->CurWritePosition += 8; | ||
260 | fillOffset += 8; | ||
261 | } | ||
262 | pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; | ||
263 | |||
264 | pWirelessPacket = | ||
265 | &pHTTXContext->TransferBuffer->field. | ||
266 | WirelessPacket[fillOffset]; | ||
267 | |||
268 | /* copy TXWI + WLAN Header + LLC into DMA Header Buffer */ | ||
269 | /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */ | ||
270 | hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; | ||
271 | |||
272 | /* Build our URB for USBD */ | ||
273 | DMAHdrLen = TXWI_SIZE + hwHdrLen; | ||
274 | USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen; | ||
275 | padding = (4 - (USBDMApktLen % 4)) & 0x03; /* round up to 4 byte alignment */ | ||
276 | USBDMApktLen += padding; | ||
277 | |||
278 | pTxBlk->Priv = (TXINFO_SIZE + USBDMApktLen); | ||
279 | |||
280 | /* For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload */ | ||
281 | RTMPWriteTxInfo(pAd, pTxInfo, (u16)(USBDMApktLen), FALSE, | ||
282 | FIFO_EDCA, FALSE /*NextValid */ , FALSE); | ||
283 | |||
284 | if ((pHTTXContext->CurWritePosition + 3906 + pTxBlk->Priv) > | ||
285 | MAX_TXBULK_LIMIT) { | ||
286 | pTxInfo->SwUseLastRound = 1; | ||
287 | bTxQLastRound = TRUE; | ||
288 | } | ||
289 | NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, | ||
290 | TXINFO_SIZE + TXWI_SIZE + hwHdrLen); | ||
291 | pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); | ||
292 | |||
293 | /* We unlock it here to prevent the first 8 bytes maybe over-writed issue. */ | ||
294 | /* 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxcontext. */ | ||
295 | /* 2. An interrupt break our routine and handle bulk-out complete. */ | ||
296 | /* 3. In the bulk-out compllete, it need to do another bulk-out, */ | ||
297 | /* if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition, */ | ||
298 | /* but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE. */ | ||
299 | /* 4. Interrupt complete. */ | ||
300 | /* 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext. */ | ||
301 | /* 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition. */ | ||
302 | /* and the packet will wrong. */ | ||
303 | pHTTXContext->CurWriteRealPos += | ||
304 | (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); | ||
305 | RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); | ||
306 | |||
307 | NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, | ||
308 | pTxBlk->SrcBufLen); | ||
309 | pWirelessPacket += pTxBlk->SrcBufLen; | ||
310 | NdisZeroMemory(pWirelessPacket, padding + 8); | ||
311 | |||
312 | RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); | ||
313 | |||
314 | pHTTXContext->CurWritePosition += pTxBlk->Priv; | ||
315 | if (bTxQLastRound) | ||
316 | pHTTXContext->CurWritePosition = 8; | ||
317 | pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; | ||
318 | |||
319 | pHTTXContext->bCurWriting = FALSE; | ||
320 | } | ||
321 | |||
322 | RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); | ||
323 | |||
324 | /* succeed and release the skb buffer */ | ||
325 | RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); | ||
326 | |||
327 | return (Status); | ||
328 | |||
329 | } | ||
330 | |||
331 | u16 RtmpUSB_WriteMultiTxResource(struct rt_rtmp_adapter *pAd, | ||
332 | struct rt_tx_blk *pTxBlk, | ||
333 | u8 frameNum, u16 * FreeNumber) | ||
334 | { | ||
335 | struct rt_ht_tx_context *pHTTXContext; | ||
336 | u16 hwHdrLen; /* The hwHdrLen consist of 802.11 header length plus the header padding length. */ | ||
337 | u32 fillOffset; | ||
338 | struct rt_txinfo *pTxInfo; | ||
339 | struct rt_txwi *pTxWI; | ||
340 | u8 *pWirelessPacket = NULL; | ||
341 | u8 QueIdx; | ||
342 | int Status; | ||
343 | unsigned long IrqFlags; | ||
344 | /*u32 USBDMApktLen = 0, DMAHdrLen, padding; */ | ||
345 | |||
346 | /* */ | ||
347 | /* get Tx Ring Resource & Dma Buffer address */ | ||
348 | /* */ | ||
349 | QueIdx = pTxBlk->QueIdx; | ||
350 | pHTTXContext = &pAd->TxContext[QueIdx]; | ||
351 | |||
352 | RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); | ||
353 | |||
354 | if (frameNum == 0) { | ||
355 | /* Check if we have enough space for this bulk-out batch. */ | ||
356 | Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); | ||
357 | if (Status == NDIS_STATUS_SUCCESS) { | ||
358 | pHTTXContext->bCurWriting = TRUE; | ||
359 | |||
360 | pTxInfo = (struct rt_txinfo *)(&pTxBlk->HeaderBuf[0]); | ||
361 | pTxWI = (struct rt_txwi *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]); | ||
362 | |||
363 | /* Reserve space for 8 bytes padding. */ | ||
364 | if ((pHTTXContext->ENextBulkOutPosition == | ||
365 | pHTTXContext->CurWritePosition)) { | ||
366 | |||
367 | pHTTXContext->CurWritePosition += 8; | ||
368 | pHTTXContext->ENextBulkOutPosition += 8; | ||
369 | } | ||
370 | fillOffset = pHTTXContext->CurWritePosition; | ||
371 | pHTTXContext->CurWriteRealPos = | ||
372 | pHTTXContext->CurWritePosition; | ||
373 | |||
374 | pWirelessPacket = | ||
375 | &pHTTXContext->TransferBuffer->field. | ||
376 | WirelessPacket[fillOffset]; | ||
377 | |||
378 | /* */ | ||
379 | /* Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer */ | ||
380 | /* */ | ||
381 | if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) | ||
382 | /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD; */ | ||
383 | hwHdrLen = | ||
384 | pTxBlk->MpduHeaderLen - | ||
385 | LENGTH_AMSDU_SUBFRAMEHEAD + | ||
386 | pTxBlk->HdrPadLen + | ||
387 | LENGTH_AMSDU_SUBFRAMEHEAD; | ||
388 | else if (pTxBlk->TxFrameType == TX_RALINK_FRAME) | ||
389 | /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD; */ | ||
390 | hwHdrLen = | ||
391 | pTxBlk->MpduHeaderLen - | ||
392 | LENGTH_ARALINK_HEADER_FIELD + | ||
393 | pTxBlk->HdrPadLen + | ||
394 | LENGTH_ARALINK_HEADER_FIELD; | ||
395 | else | ||
396 | /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */ | ||
397 | hwHdrLen = | ||
398 | pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; | ||
399 | |||
400 | /* Update the pTxBlk->Priv. */ | ||
401 | pTxBlk->Priv = TXINFO_SIZE + TXWI_SIZE + hwHdrLen; | ||
402 | |||
403 | /* pTxInfo->USBDMApktLen now just a temp value and will to correct latter. */ | ||
404 | RTMPWriteTxInfo(pAd, pTxInfo, (u16)(pTxBlk->Priv), | ||
405 | FALSE, FIFO_EDCA, FALSE /*NextValid */ , | ||
406 | FALSE); | ||
407 | |||
408 | /* Copy it. */ | ||
409 | NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, | ||
410 | pTxBlk->Priv); | ||
411 | pHTTXContext->CurWriteRealPos += pTxBlk->Priv; | ||
412 | pWirelessPacket += pTxBlk->Priv; | ||
413 | } | ||
414 | } else { /* For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer. */ | ||
415 | |||
416 | Status = | ||
417 | ((pHTTXContext->bCurWriting == | ||
418 | TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE); | ||
419 | if (Status == NDIS_STATUS_SUCCESS) { | ||
420 | fillOffset = | ||
421 | (pHTTXContext->CurWritePosition + pTxBlk->Priv); | ||
422 | pWirelessPacket = | ||
423 | &pHTTXContext->TransferBuffer->field. | ||
424 | WirelessPacket[fillOffset]; | ||
425 | |||
426 | /*hwHdrLen = pTxBlk->MpduHeaderLen; */ | ||
427 | NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, | ||
428 | pTxBlk->MpduHeaderLen); | ||
429 | pWirelessPacket += (pTxBlk->MpduHeaderLen); | ||
430 | pTxBlk->Priv += pTxBlk->MpduHeaderLen; | ||
431 | } else { /* It should not happened now unless we are going to shutdown. */ | ||
432 | DBGPRINT(RT_DEBUG_ERROR, | ||
433 | ("WriteMultiTxResource():bCurWriting is FALSE when handle sub-sequent frames.\n")); | ||
434 | Status = NDIS_STATUS_FAILURE; | ||
435 | } | ||
436 | } | ||
437 | |||
438 | /* We unlock it here to prevent the first 8 bytes maybe over-write issue. */ | ||
439 | /* 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxContext. */ | ||
440 | /* 2. An interrupt break our routine and handle bulk-out complete. */ | ||
441 | /* 3. In the bulk-out compllete, it need to do another bulk-out, */ | ||
442 | /* if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition, */ | ||
443 | /* but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE. */ | ||
444 | /* 4. Interrupt complete. */ | ||
445 | /* 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext. */ | ||
446 | /* 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition. */ | ||
447 | /* and the packet will wrong. */ | ||
448 | RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); | ||
449 | |||
450 | if (Status != NDIS_STATUS_SUCCESS) { | ||
451 | DBGPRINT(RT_DEBUG_ERROR, | ||
452 | ("WriteMultiTxResource: CWPos = %ld, NBOutPos = %ld.\n", | ||
453 | pHTTXContext->CurWritePosition, | ||
454 | pHTTXContext->NextBulkOutPosition)); | ||
455 | goto done; | ||
456 | } | ||
457 | /* Copy the frame content into DMA buffer and update the pTxBlk->Priv */ | ||
458 | NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); | ||
459 | pWirelessPacket += pTxBlk->SrcBufLen; | ||
460 | pTxBlk->Priv += pTxBlk->SrcBufLen; | ||
461 | |||
462 | done: | ||
463 | /* Release the skb buffer here */ | ||
464 | RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); | ||
465 | |||
466 | return (Status); | ||
467 | |||
468 | } | ||
469 | |||
470 | void RtmpUSB_FinalWriteTxResource(struct rt_rtmp_adapter *pAd, | ||
471 | struct rt_tx_blk *pTxBlk, | ||
472 | u16 totalMPDUSize, u16 TxIdx) | ||
473 | { | ||
474 | u8 QueIdx; | ||
475 | struct rt_ht_tx_context *pHTTXContext; | ||
476 | u32 fillOffset; | ||
477 | struct rt_txinfo *pTxInfo; | ||
478 | struct rt_txwi *pTxWI; | ||
479 | u32 USBDMApktLen, padding; | ||
480 | unsigned long IrqFlags; | ||
481 | u8 *pWirelessPacket; | ||
482 | |||
483 | QueIdx = pTxBlk->QueIdx; | ||
484 | pHTTXContext = &pAd->TxContext[QueIdx]; | ||
485 | |||
486 | RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); | ||
487 | |||
488 | if (pHTTXContext->bCurWriting == TRUE) { | ||
489 | fillOffset = pHTTXContext->CurWritePosition; | ||
490 | if (((pHTTXContext->ENextBulkOutPosition == | ||
491 | pHTTXContext->CurWritePosition) | ||
492 | || ((pHTTXContext->ENextBulkOutPosition - 8) == | ||
493 | pHTTXContext->CurWritePosition)) | ||
494 | && (pHTTXContext->bCopySavePad == TRUE)) | ||
495 | pWirelessPacket = (u8 *)(&pHTTXContext->SavedPad[0]); | ||
496 | else | ||
497 | pWirelessPacket = | ||
498 | (u8 *)(&pHTTXContext->TransferBuffer->field. | ||
499 | WirelessPacket[fillOffset]); | ||
500 | |||
501 | /* */ | ||
502 | /* Update TxInfo->USBDMApktLen , */ | ||
503 | /* the length = TXWI_SIZE + 802.11_hdr + 802.11_hdr_pad + payload_of_all_batch_frames + Bulk-Out-padding */ | ||
504 | /* */ | ||
505 | pTxInfo = (struct rt_txinfo *)(pWirelessPacket); | ||
506 | |||
507 | /* Calculate the bulk-out padding */ | ||
508 | USBDMApktLen = pTxBlk->Priv - TXINFO_SIZE; | ||
509 | padding = (4 - (USBDMApktLen % 4)) & 0x03; /* round up to 4 byte alignment */ | ||
510 | USBDMApktLen += padding; | ||
511 | |||
512 | pTxInfo->USBDMATxPktLen = USBDMApktLen; | ||
513 | |||
514 | /* */ | ||
515 | /* Update TXWI->MPDUtotalByteCount , */ | ||
516 | /* the length = 802.11 header + payload_of_all_batch_frames */ | ||
517 | pTxWI = (struct rt_txwi *) (pWirelessPacket + TXINFO_SIZE); | ||
518 | pTxWI->MPDUtotalByteCount = totalMPDUSize; | ||
519 | |||
520 | /* */ | ||
521 | /* Update the pHTTXContext->CurWritePosition */ | ||
522 | /* */ | ||
523 | pHTTXContext->CurWritePosition += (TXINFO_SIZE + USBDMApktLen); | ||
524 | if ((pHTTXContext->CurWritePosition + 3906) > MAX_TXBULK_LIMIT) { /* Add 3906 for prevent the NextBulkOut packet size is a A-RALINK/A-MSDU Frame. */ | ||
525 | pHTTXContext->CurWritePosition = 8; | ||
526 | pTxInfo->SwUseLastRound = 1; | ||
527 | } | ||
528 | pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; | ||
529 | |||
530 | /* */ | ||
531 | /* Zero the last padding. */ | ||
532 | /* */ | ||
533 | pWirelessPacket = | ||
534 | (&pHTTXContext->TransferBuffer->field. | ||
535 | WirelessPacket[fillOffset + pTxBlk->Priv]); | ||
536 | NdisZeroMemory(pWirelessPacket, padding + 8); | ||
537 | |||
538 | /* Finally, set bCurWriting as FALSE */ | ||
539 | pHTTXContext->bCurWriting = FALSE; | ||
540 | |||
541 | } else { /* It should not happened now unless we are going to shutdown. */ | ||
542 | DBGPRINT(RT_DEBUG_ERROR, | ||
543 | ("FinalWriteTxResource():bCurWriting is FALSE when handle last frames.\n")); | ||
544 | } | ||
545 | |||
546 | RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); | ||
547 | |||
548 | } | ||
549 | |||
550 | void RtmpUSBDataLastTxIdx(struct rt_rtmp_adapter *pAd, | ||
551 | u8 QueIdx, u16 TxIdx) | ||
552 | { | ||
553 | /* DO nothing for USB. */ | ||
554 | } | ||
555 | |||
556 | /* | ||
557 | When can do bulk-out: | ||
558 | 1. TxSwFreeIdx < TX_RING_SIZE; | ||
559 | It means has at least one Ring entity is ready for bulk-out, kick it out. | ||
560 | 2. If TxSwFreeIdx == TX_RING_SIZE | ||
561 | Check if the CurWriting flag is FALSE, if it's FALSE, we can do kick out. | ||
562 | |||
563 | */ | ||
564 | void RtmpUSBDataKickOut(struct rt_rtmp_adapter *pAd, | ||
565 | struct rt_tx_blk *pTxBlk, u8 QueIdx) | ||
566 | { | ||
567 | RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx)); | ||
568 | RTUSBKickBulkOut(pAd); | ||
569 | |||
570 | } | ||
571 | |||
572 | /* | ||
573 | Must be run in Interrupt context | ||
574 | This function handle RT2870 specific TxDesc and cpu index update and kick the packet out. | ||
575 | */ | ||
576 | int RtmpUSBMgmtKickOut(struct rt_rtmp_adapter *pAd, | ||
577 | u8 QueIdx, | ||
578 | void *pPacket, | ||
579 | u8 *pSrcBufVA, u32 SrcBufLen) | ||
580 | { | ||
581 | struct rt_txinfo *pTxInfo; | ||
582 | unsigned long BulkOutSize; | ||
583 | u8 padLen; | ||
584 | u8 *pDest; | ||
585 | unsigned long SwIdx = pAd->MgmtRing.TxCpuIdx; | ||
586 | struct rt_tx_context *pMLMEContext = | ||
587 | (struct rt_tx_context *)pAd->MgmtRing.Cell[SwIdx].AllocVa; | ||
588 | unsigned long IrqFlags; | ||
589 | |||
590 | pTxInfo = (struct rt_txinfo *)(pSrcBufVA); | ||
591 | |||
592 | /* Build our URB for USBD */ | ||
593 | BulkOutSize = SrcBufLen; | ||
594 | BulkOutSize = (BulkOutSize + 3) & (~3); | ||
595 | RTMPWriteTxInfo(pAd, pTxInfo, (u16)(BulkOutSize - TXINFO_SIZE), | ||
596 | TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE); | ||
597 | |||
598 | BulkOutSize += 4; /* Always add 4 extra bytes at every packet. */ | ||
599 | |||
600 | /* If BulkOutSize is multiple of BulkOutMaxPacketSize, add extra 4 bytes again. */ | ||
601 | if ((BulkOutSize % pAd->BulkOutMaxPacketSize) == 0) | ||
602 | BulkOutSize += 4; | ||
603 | |||
604 | padLen = BulkOutSize - SrcBufLen; | ||
605 | ASSERT((padLen <= RTMP_PKT_TAIL_PADDING)); | ||
606 | |||
607 | /* Now memzero all extra padding bytes. */ | ||
608 | pDest = (u8 *)(pSrcBufVA + SrcBufLen); | ||
609 | skb_put(GET_OS_PKT_TYPE(pPacket), padLen); | ||
610 | NdisZeroMemory(pDest, padLen); | ||
611 | |||
612 | RTMP_IRQ_LOCK(&pAd->MLMEBulkOutLock, IrqFlags); | ||
613 | |||
614 | pAd->MgmtRing.Cell[pAd->MgmtRing.TxCpuIdx].pNdisPacket = pPacket; | ||
615 | pMLMEContext->TransferBuffer = | ||
616 | (struct rt_tx_buffer *)(GET_OS_PKT_DATAPTR(pPacket)); | ||
617 | |||
618 | /* Length in TxInfo should be 8 less than bulkout size. */ | ||
619 | pMLMEContext->BulkOutSize = BulkOutSize; | ||
620 | pMLMEContext->InUse = TRUE; | ||
621 | pMLMEContext->bWaitingBulkOut = TRUE; | ||
622 | |||
623 | /*for debug */ | ||
624 | /*hex_dump("RtmpUSBMgmtKickOut", &pMLMEContext->TransferBuffer->field.WirelessPacket[0], (pMLMEContext->BulkOutSize > 16 ? 16 : pMLMEContext->BulkOutSize)); */ | ||
625 | |||
626 | /*pAd->RalinkCounters.KickTxCount++; */ | ||
627 | /*pAd->RalinkCounters.OneSecTxDoneCount++; */ | ||
628 | |||
629 | /*if (pAd->MgmtRing.TxSwFreeIdx == MGMT_RING_SIZE) */ | ||
630 | /* needKickOut = TRUE; */ | ||
631 | |||
632 | /* Decrease the TxSwFreeIdx and Increase the TX_CTX_IDX */ | ||
633 | pAd->MgmtRing.TxSwFreeIdx--; | ||
634 | INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE); | ||
635 | |||
636 | RTMP_IRQ_UNLOCK(&pAd->MLMEBulkOutLock, IrqFlags); | ||
637 | |||
638 | RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME); | ||
639 | /*if (needKickOut) */ | ||
640 | RTUSBKickBulkOut(pAd); | ||
641 | |||
642 | return 0; | ||
643 | } | ||
644 | |||
645 | void RtmpUSBNullFrameKickOut(struct rt_rtmp_adapter *pAd, | ||
646 | u8 QueIdx, | ||
647 | u8 * pNullFrame, u32 frameLen) | ||
648 | { | ||
649 | if (pAd->NullContext.InUse == FALSE) { | ||
650 | struct rt_tx_context *pNullContext; | ||
651 | struct rt_txinfo *pTxInfo; | ||
652 | struct rt_txwi * pTxWI; | ||
653 | u8 *pWirelessPkt; | ||
654 | |||
655 | pNullContext = &(pAd->NullContext); | ||
656 | |||
657 | /* Set the in use bit */ | ||
658 | pNullContext->InUse = TRUE; | ||
659 | pWirelessPkt = | ||
660 | (u8 *)& pNullContext->TransferBuffer->field. | ||
661 | WirelessPacket[0]; | ||
662 | |||
663 | RTMPZeroMemory(&pWirelessPkt[0], 100); | ||
664 | pTxInfo = (struct rt_txinfo *)& pWirelessPkt[0]; | ||
665 | RTMPWriteTxInfo(pAd, pTxInfo, | ||
666 | (u16)(sizeof(struct rt_header_802_11) + TXWI_SIZE), | ||
667 | TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE); | ||
668 | pTxInfo->QSEL = FIFO_EDCA; | ||
669 | pTxWI = (struct rt_txwi *) & pWirelessPkt[TXINFO_SIZE]; | ||
670 | RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, TRUE, | ||
671 | FALSE, 0, BSSID_WCID, (sizeof(struct rt_header_802_11)), 0, | ||
672 | 0, (u8)pAd->CommonCfg.MlmeTransmit.field.MCS, | ||
673 | IFS_HTTXOP, FALSE, &pAd->CommonCfg.MlmeTransmit); | ||
674 | |||
675 | RTMPMoveMemory(&pWirelessPkt[TXWI_SIZE + TXINFO_SIZE], | ||
676 | &pAd->NullFrame, sizeof(struct rt_header_802_11)); | ||
677 | pAd->NullContext.BulkOutSize = | ||
678 | TXINFO_SIZE + TXWI_SIZE + sizeof(pAd->NullFrame) + 4; | ||
679 | |||
680 | /* Fill out frame length information for global Bulk out arbitor */ | ||
681 | /*pNullContext->BulkOutSize = TransferBufferLength; */ | ||
682 | DBGPRINT(RT_DEBUG_TRACE, | ||
683 | ("SYNC - send NULL Frame @%d Mbps...\n", | ||
684 | RateIdToMbps[pAd->CommonCfg.TxRate])); | ||
685 | RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL); | ||
686 | |||
687 | /* Kick bulk out */ | ||
688 | RTUSBKickBulkOut(pAd); | ||
689 | } | ||
690 | |||
691 | } | ||
692 | |||
693 | /* | ||
694 | ======================================================================== | ||
695 | Routine Description: | ||
696 | Get a received packet. | ||
697 | |||
698 | Arguments: | ||
699 | pAd device control block | ||
700 | pSaveRxD receive descriptor information | ||
701 | *pbReschedule need reschedule flag | ||
702 | *pRxPending pending received packet flag | ||
703 | |||
704 | Return Value: | ||
705 | the received packet | ||
706 | |||
707 | Note: | ||
708 | ======================================================================== | ||
709 | */ | ||
710 | void *GetPacketFromRxRing(struct rt_rtmp_adapter *pAd, | ||
711 | OUT PRT28XX_RXD_STRUC pSaveRxD, | ||
712 | OUT BOOLEAN * pbReschedule, | ||
713 | IN u32 * pRxPending) | ||
714 | { | ||
715 | struct rt_rx_context *pRxContext; | ||
716 | void *pSkb; | ||
717 | u8 *pData; | ||
718 | unsigned long ThisFrameLen; | ||
719 | unsigned long RxBufferLength; | ||
720 | struct rt_rxwi * pRxWI; | ||
721 | |||
722 | pRxContext = &pAd->RxContext[pAd->NextRxBulkInReadIndex]; | ||
723 | if ((pRxContext->Readable == FALSE) || (pRxContext->InUse == TRUE)) | ||
724 | return NULL; | ||
725 | |||
726 | RxBufferLength = pRxContext->BulkInOffset - pAd->ReadPosition; | ||
727 | if (RxBufferLength < | ||
728 | (RT2870_RXDMALEN_FIELD_SIZE + sizeof(struct rt_rxwi) + | ||
729 | sizeof(struct rt_rxinfo))) { | ||
730 | goto label_null; | ||
731 | } | ||
732 | |||
733 | pData = &pRxContext->TransferBuffer[pAd->ReadPosition]; /* 4KB */ | ||
734 | /* The RXDMA field is 4 bytes, now just use the first 2 bytes. The Length including the (RXWI + MSDU + Padding) */ | ||
735 | ThisFrameLen = *pData + (*(pData + 1) << 8); | ||
736 | if (ThisFrameLen == 0) { | ||
737 | DBGPRINT(RT_DEBUG_TRACE, | ||
738 | ("BIRIdx(%d): RXDMALen is zero.[%ld], BulkInBufLen = %ld)\n", | ||
739 | pAd->NextRxBulkInReadIndex, ThisFrameLen, | ||
740 | pRxContext->BulkInOffset)); | ||
741 | goto label_null; | ||
742 | } | ||
743 | if ((ThisFrameLen & 0x3) != 0) { | ||
744 | DBGPRINT(RT_DEBUG_ERROR, | ||
745 | ("BIRIdx(%d): RXDMALen not multiple of 4.[%ld], BulkInBufLen = %ld)\n", | ||
746 | pAd->NextRxBulkInReadIndex, ThisFrameLen, | ||
747 | pRxContext->BulkInOffset)); | ||
748 | goto label_null; | ||
749 | } | ||
750 | |||
751 | if ((ThisFrameLen + 8) > RxBufferLength) /* 8 for (RT2870_RXDMALEN_FIELD_SIZE + sizeof(struct rt_rxinfo)) */ | ||
752 | { | ||
753 | DBGPRINT(RT_DEBUG_TRACE, | ||
754 | ("BIRIdx(%d):FrameLen(0x%lx) outranges. BulkInLen=0x%lx, remaining RxBufLen=0x%lx, ReadPos=0x%lx\n", | ||
755 | pAd->NextRxBulkInReadIndex, ThisFrameLen, | ||
756 | pRxContext->BulkInOffset, RxBufferLength, | ||
757 | pAd->ReadPosition)); | ||
758 | |||
759 | /* error frame. finish this loop */ | ||
760 | goto label_null; | ||
761 | } | ||
762 | /* skip USB frame length field */ | ||
763 | pData += RT2870_RXDMALEN_FIELD_SIZE; | ||
764 | pRxWI = (struct rt_rxwi *) pData; | ||
765 | if (pRxWI->MPDUtotalByteCount > ThisFrameLen) { | ||
766 | DBGPRINT(RT_DEBUG_ERROR, | ||
767 | ("%s():pRxWIMPDUtotalByteCount(%d) large than RxDMALen(%ld)\n", | ||
768 | __FUNCTION__, pRxWI->MPDUtotalByteCount, | ||
769 | ThisFrameLen)); | ||
770 | goto label_null; | ||
771 | } | ||
772 | /* allocate a rx packet */ | ||
773 | pSkb = dev_alloc_skb(ThisFrameLen); | ||
774 | if (pSkb == NULL) { | ||
775 | DBGPRINT(RT_DEBUG_ERROR, | ||
776 | ("%s():Cannot Allocate sk buffer for this Bulk-In buffer!\n", | ||
777 | __FUNCTION__)); | ||
778 | goto label_null; | ||
779 | } | ||
780 | /* copy the rx packet */ | ||
781 | memcpy(skb_put(pSkb, ThisFrameLen), pData, ThisFrameLen); | ||
782 | RTPKT_TO_OSPKT(pSkb)->dev = get_netdev_from_bssid(pAd, BSS0); | ||
783 | RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pSkb), PKTSRC_NDIS); | ||
784 | |||
785 | /* copy RxD */ | ||
786 | *pSaveRxD = *(struct rt_rxinfo *) (pData + ThisFrameLen); | ||
787 | |||
788 | /* update next packet read position. */ | ||
789 | pAd->ReadPosition += (ThisFrameLen + RT2870_RXDMALEN_FIELD_SIZE + RXINFO_SIZE); /* 8 for (RT2870_RXDMALEN_FIELD_SIZE + sizeof(struct rt_rxinfo)) */ | ||
790 | |||
791 | return pSkb; | ||
792 | |||
793 | label_null: | ||
794 | |||
795 | return NULL; | ||
796 | } | ||
797 | |||
798 | /* | ||
799 | ======================================================================== | ||
800 | |||
801 | Routine Description: | ||
802 | Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound | ||
803 | |||
804 | Arguments: | ||
805 | pRxD Pointer to the Rx descriptor | ||
806 | |||
807 | Return Value: | ||
808 | NDIS_STATUS_SUCCESS No err | ||
809 | NDIS_STATUS_FAILURE Error | ||
810 | |||
811 | Note: | ||
812 | |||
813 | ======================================================================== | ||
814 | */ | ||
815 | int RTMPCheckRxError(struct rt_rtmp_adapter *pAd, | ||
816 | struct rt_header_802_11 * pHeader, | ||
817 | struct rt_rxwi * pRxWI, IN PRT28XX_RXD_STRUC pRxINFO) | ||
818 | { | ||
819 | struct rt_cipher_key *pWpaKey; | ||
820 | int dBm; | ||
821 | |||
822 | if (pAd->bPromiscuous == TRUE) | ||
823 | return (NDIS_STATUS_SUCCESS); | ||
824 | if (pRxINFO == NULL) | ||
825 | return (NDIS_STATUS_FAILURE); | ||
826 | |||
827 | /* Phy errors & CRC errors */ | ||
828 | if (pRxINFO->Crc) { | ||
829 | /* Check RSSI for Noise Hist statistic collection. */ | ||
830 | dBm = (int)(pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta; | ||
831 | if (dBm <= -87) | ||
832 | pAd->StaCfg.RPIDensity[0] += 1; | ||
833 | else if (dBm <= -82) | ||
834 | pAd->StaCfg.RPIDensity[1] += 1; | ||
835 | else if (dBm <= -77) | ||
836 | pAd->StaCfg.RPIDensity[2] += 1; | ||
837 | else if (dBm <= -72) | ||
838 | pAd->StaCfg.RPIDensity[3] += 1; | ||
839 | else if (dBm <= -67) | ||
840 | pAd->StaCfg.RPIDensity[4] += 1; | ||
841 | else if (dBm <= -62) | ||
842 | pAd->StaCfg.RPIDensity[5] += 1; | ||
843 | else if (dBm <= -57) | ||
844 | pAd->StaCfg.RPIDensity[6] += 1; | ||
845 | else if (dBm > -57) | ||
846 | pAd->StaCfg.RPIDensity[7] += 1; | ||
847 | |||
848 | return (NDIS_STATUS_FAILURE); | ||
849 | } | ||
850 | /* Add Rx size to channel load counter, we should ignore error counts */ | ||
851 | pAd->StaCfg.CLBusyBytes += (pRxWI->MPDUtotalByteCount + 14); | ||
852 | |||
853 | /* Drop ToDs promiscuous frame, it is opened due to CCX 2 channel load statistics */ | ||
854 | if (pHeader->FC.ToDs) { | ||
855 | DBGPRINT_RAW(RT_DEBUG_ERROR, ("Err;FC.ToDs\n")); | ||
856 | return NDIS_STATUS_FAILURE; | ||
857 | } | ||
858 | /* Paul 04-03 for OFDM Rx length issue */ | ||
859 | if (pRxWI->MPDUtotalByteCount > MAX_AGGREGATION_SIZE) { | ||
860 | DBGPRINT_RAW(RT_DEBUG_ERROR, ("received packet too long\n")); | ||
861 | return NDIS_STATUS_FAILURE; | ||
862 | } | ||
863 | /* Drop not U2M frames, can't's drop here because we will drop beacon in this case */ | ||
864 | /* I am kind of doubting the U2M bit operation */ | ||
865 | /* if (pRxD->U2M == 0) */ | ||
866 | /* return(NDIS_STATUS_FAILURE); */ | ||
867 | |||
868 | /* drop decyption fail frame */ | ||
869 | if (pRxINFO->Decrypted && pRxINFO->CipherErr) { | ||
870 | |||
871 | if (((pRxINFO->CipherErr & 1) == 1) | ||
872 | && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd)) | ||
873 | RTMPSendWirelessEvent(pAd, IW_ICV_ERROR_EVENT_FLAG, | ||
874 | pAd->MacTab.Content[BSSID_WCID]. | ||
875 | Addr, BSS0, 0); | ||
876 | |||
877 | if (((pRxINFO->CipherErr & 2) == 2) | ||
878 | && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd)) | ||
879 | RTMPSendWirelessEvent(pAd, IW_MIC_ERROR_EVENT_FLAG, | ||
880 | pAd->MacTab.Content[BSSID_WCID]. | ||
881 | Addr, BSS0, 0); | ||
882 | /* */ | ||
883 | /* MIC Error */ | ||
884 | /* */ | ||
885 | if ((pRxINFO->CipherErr == 2) && pRxINFO->MyBss) { | ||
886 | pWpaKey = &pAd->SharedKey[BSS0][pRxWI->KeyIndex]; | ||
887 | RTMPReportMicError(pAd, pWpaKey); | ||
888 | DBGPRINT_RAW(RT_DEBUG_ERROR, ("Rx MIC Value error\n")); | ||
889 | } | ||
890 | |||
891 | if (pRxINFO->Decrypted && | ||
892 | (pAd->SharedKey[BSS0][pRxWI->KeyIndex].CipherAlg == | ||
893 | CIPHER_AES) | ||
894 | && (pHeader->Sequence == pAd->FragFrame.Sequence)) { | ||
895 | /* */ | ||
896 | /* Acceptable since the First FragFrame no CipherErr problem. */ | ||
897 | /* */ | ||
898 | return (NDIS_STATUS_SUCCESS); | ||
899 | } | ||
900 | |||
901 | return (NDIS_STATUS_FAILURE); | ||
902 | } | ||
903 | |||
904 | return (NDIS_STATUS_SUCCESS); | ||
905 | } | ||
906 | |||
907 | void RtmpUsbStaAsicForceWakeupTimeout(void *SystemSpecific1, | ||
908 | void *FunctionContext, | ||
909 | void *SystemSpecific2, | ||
910 | void *SystemSpecific3) | ||
911 | { | ||
912 | struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; | ||
913 | |||
914 | if (pAd && pAd->Mlme.AutoWakeupTimerRunning) { | ||
915 | AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02); | ||
916 | |||
917 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); | ||
918 | pAd->Mlme.AutoWakeupTimerRunning = FALSE; | ||
919 | } | ||
920 | } | ||
921 | |||
922 | void RT28xxUsbStaAsicForceWakeup(struct rt_rtmp_adapter *pAd, IN BOOLEAN bFromTx) | ||
923 | { | ||
924 | BOOLEAN Canceled; | ||
925 | |||
926 | if (pAd->Mlme.AutoWakeupTimerRunning) | ||
927 | RTMPCancelTimer(&pAd->Mlme.AutoWakeupTimer, &Canceled); | ||
928 | |||
929 | AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02); | ||
930 | |||
931 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); | ||
932 | } | ||
933 | |||
934 | void RT28xxUsbStaAsicSleepThenAutoWakeup(struct rt_rtmp_adapter *pAd, | ||
935 | u16 TbttNumToNextWakeUp) | ||
936 | { | ||
937 | |||
938 | /* we have decided to SLEEP, so at least do it for a BEACON period. */ | ||
939 | if (TbttNumToNextWakeUp == 0) | ||
940 | TbttNumToNextWakeUp = 1; | ||
941 | |||
942 | RTMPSetTimer(&pAd->Mlme.AutoWakeupTimer, AUTO_WAKEUP_TIMEOUT); | ||
943 | pAd->Mlme.AutoWakeupTimerRunning = TRUE; | ||
944 | |||
945 | AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02); /* send POWER-SAVE command to MCU. Timeout 40us. */ | ||
946 | |||
947 | OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE); | ||
948 | |||
949 | } | ||
950 | |||
951 | #endif /* RTMP_MAC_USB // */ | ||
diff --git a/drivers/staging/rt2860/common/cmm_info.c b/drivers/staging/rt2860/common/cmm_info.c deleted file mode 100644 index 25302e8363b..00000000000 --- a/drivers/staging/rt2860/common/cmm_info.c +++ /dev/null | |||
@@ -1,955 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | */ | ||
27 | |||
28 | #include <linux/sched.h> | ||
29 | #include "../rt_config.h" | ||
30 | |||
31 | /* | ||
32 | ======================================================================== | ||
33 | |||
34 | Routine Description: | ||
35 | Remove WPA Key process | ||
36 | |||
37 | Arguments: | ||
38 | pAd Pointer to our adapter | ||
39 | pBuf Pointer to the where the key stored | ||
40 | |||
41 | Return Value: | ||
42 | NDIS_SUCCESS Add key successfully | ||
43 | |||
44 | IRQL = DISPATCH_LEVEL | ||
45 | |||
46 | Note: | ||
47 | |||
48 | ======================================================================== | ||
49 | */ | ||
50 | void RTMPSetDesiredRates(struct rt_rtmp_adapter *pAdapter, long Rates) | ||
51 | { | ||
52 | NDIS_802_11_RATES aryRates; | ||
53 | |||
54 | memset(&aryRates, 0x00, sizeof(NDIS_802_11_RATES)); | ||
55 | switch (pAdapter->CommonCfg.PhyMode) { | ||
56 | case PHY_11A: /* A only */ | ||
57 | switch (Rates) { | ||
58 | case 6000000: /*6M */ | ||
59 | aryRates[0] = 0x0c; /* 6M */ | ||
60 | pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = | ||
61 | MCS_0; | ||
62 | break; | ||
63 | case 9000000: /*9M */ | ||
64 | aryRates[0] = 0x12; /* 9M */ | ||
65 | pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = | ||
66 | MCS_1; | ||
67 | break; | ||
68 | case 12000000: /*12M */ | ||
69 | aryRates[0] = 0x18; /* 12M */ | ||
70 | pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = | ||
71 | MCS_2; | ||
72 | break; | ||
73 | case 18000000: /*18M */ | ||
74 | aryRates[0] = 0x24; /* 18M */ | ||
75 | pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = | ||
76 | MCS_3; | ||
77 | break; | ||
78 | case 24000000: /*24M */ | ||
79 | aryRates[0] = 0x30; /* 24M */ | ||
80 | pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = | ||
81 | MCS_4; | ||
82 | break; | ||
83 | case 36000000: /*36M */ | ||
84 | aryRates[0] = 0x48; /* 36M */ | ||
85 | pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = | ||
86 | MCS_5; | ||
87 | break; | ||
88 | case 48000000: /*48M */ | ||
89 | aryRates[0] = 0x60; /* 48M */ | ||
90 | pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = | ||
91 | MCS_6; | ||
92 | break; | ||
93 | case 54000000: /*54M */ | ||
94 | aryRates[0] = 0x6c; /* 54M */ | ||
95 | pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = | ||
96 | MCS_7; | ||
97 | break; | ||
98 | case -1: /*Auto */ | ||
99 | default: | ||
100 | aryRates[0] = 0x6c; /* 54Mbps */ | ||
101 | aryRates[1] = 0x60; /* 48Mbps */ | ||
102 | aryRates[2] = 0x48; /* 36Mbps */ | ||
103 | aryRates[3] = 0x30; /* 24Mbps */ | ||
104 | aryRates[4] = 0x24; /* 18M */ | ||
105 | aryRates[5] = 0x18; /* 12M */ | ||
106 | aryRates[6] = 0x12; /* 9M */ | ||
107 | aryRates[7] = 0x0c; /* 6M */ | ||
108 | pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = | ||
109 | MCS_AUTO; | ||
110 | break; | ||
111 | } | ||
112 | break; | ||
113 | case PHY_11BG_MIXED: /* B/G Mixed */ | ||
114 | case PHY_11B: /* B only */ | ||
115 | case PHY_11ABG_MIXED: /* A/B/G Mixed */ | ||
116 | default: | ||
117 | switch (Rates) { | ||
118 | case 1000000: /*1M */ | ||
119 | aryRates[0] = 0x02; | ||
120 | pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = | ||
121 | MCS_0; | ||
122 | break; | ||
123 | case 2000000: /*2M */ | ||
124 | aryRates[0] = 0x04; | ||
125 | pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = | ||
126 | MCS_1; | ||
127 | break; | ||
128 | case 5000000: /*5.5M */ | ||
129 | aryRates[0] = 0x0b; /* 5.5M */ | ||
130 | pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = | ||
131 | MCS_2; | ||
132 | break; | ||
133 | case 11000000: /*11M */ | ||
134 | aryRates[0] = 0x16; /* 11M */ | ||
135 | pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = | ||
136 | MCS_3; | ||
137 | break; | ||
138 | case 6000000: /*6M */ | ||
139 | aryRates[0] = 0x0c; /* 6M */ | ||
140 | pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = | ||
141 | MCS_0; | ||
142 | break; | ||
143 | case 9000000: /*9M */ | ||
144 | aryRates[0] = 0x12; /* 9M */ | ||
145 | pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = | ||
146 | MCS_1; | ||
147 | break; | ||
148 | case 12000000: /*12M */ | ||
149 | aryRates[0] = 0x18; /* 12M */ | ||
150 | pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = | ||
151 | MCS_2; | ||
152 | break; | ||
153 | case 18000000: /*18M */ | ||
154 | aryRates[0] = 0x24; /* 18M */ | ||
155 | pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = | ||
156 | MCS_3; | ||
157 | break; | ||
158 | case 24000000: /*24M */ | ||
159 | aryRates[0] = 0x30; /* 24M */ | ||
160 | pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = | ||
161 | MCS_4; | ||
162 | break; | ||
163 | case 36000000: /*36M */ | ||
164 | aryRates[0] = 0x48; /* 36M */ | ||
165 | pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = | ||
166 | MCS_5; | ||
167 | break; | ||
168 | case 48000000: /*48M */ | ||
169 | aryRates[0] = 0x60; /* 48M */ | ||
170 | pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = | ||
171 | MCS_6; | ||
172 | break; | ||
173 | case 54000000: /*54M */ | ||
174 | aryRates[0] = 0x6c; /* 54M */ | ||
175 | pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = | ||
176 | MCS_7; | ||
177 | break; | ||
178 | case -1: /*Auto */ | ||
179 | default: | ||
180 | if (pAdapter->CommonCfg.PhyMode == PHY_11B) { /*B Only */ | ||
181 | aryRates[0] = 0x16; /* 11Mbps */ | ||
182 | aryRates[1] = 0x0b; /* 5.5Mbps */ | ||
183 | aryRates[2] = 0x04; /* 2Mbps */ | ||
184 | aryRates[3] = 0x02; /* 1Mbps */ | ||
185 | } else { /*(B/G) Mixed or (A/B/G) Mixed */ | ||
186 | aryRates[0] = 0x6c; /* 54Mbps */ | ||
187 | aryRates[1] = 0x60; /* 48Mbps */ | ||
188 | aryRates[2] = 0x48; /* 36Mbps */ | ||
189 | aryRates[3] = 0x30; /* 24Mbps */ | ||
190 | aryRates[4] = 0x16; /* 11Mbps */ | ||
191 | aryRates[5] = 0x0b; /* 5.5Mbps */ | ||
192 | aryRates[6] = 0x04; /* 2Mbps */ | ||
193 | aryRates[7] = 0x02; /* 1Mbps */ | ||
194 | } | ||
195 | pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = | ||
196 | MCS_AUTO; | ||
197 | break; | ||
198 | } | ||
199 | break; | ||
200 | } | ||
201 | |||
202 | NdisZeroMemory(pAdapter->CommonCfg.DesireRate, | ||
203 | MAX_LEN_OF_SUPPORTED_RATES); | ||
204 | NdisMoveMemory(pAdapter->CommonCfg.DesireRate, &aryRates, | ||
205 | sizeof(NDIS_802_11_RATES)); | ||
206 | DBGPRINT(RT_DEBUG_TRACE, | ||
207 | (" RTMPSetDesiredRates (%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x)\n", | ||
208 | pAdapter->CommonCfg.DesireRate[0], | ||
209 | pAdapter->CommonCfg.DesireRate[1], | ||
210 | pAdapter->CommonCfg.DesireRate[2], | ||
211 | pAdapter->CommonCfg.DesireRate[3], | ||
212 | pAdapter->CommonCfg.DesireRate[4], | ||
213 | pAdapter->CommonCfg.DesireRate[5], | ||
214 | pAdapter->CommonCfg.DesireRate[6], | ||
215 | pAdapter->CommonCfg.DesireRate[7])); | ||
216 | /* Changing DesiredRate may affect the MAX TX rate we used to TX frames out */ | ||
217 | MlmeUpdateTxRates(pAdapter, FALSE, 0); | ||
218 | } | ||
219 | |||
220 | /* | ||
221 | ======================================================================== | ||
222 | |||
223 | Routine Description: | ||
224 | Remove All WPA Keys | ||
225 | |||
226 | Arguments: | ||
227 | pAd Pointer to our adapter | ||
228 | |||
229 | Return Value: | ||
230 | None | ||
231 | |||
232 | IRQL = DISPATCH_LEVEL | ||
233 | |||
234 | Note: | ||
235 | |||
236 | ======================================================================== | ||
237 | */ | ||
238 | void RTMPWPARemoveAllKeys(struct rt_rtmp_adapter *pAd) | ||
239 | { | ||
240 | |||
241 | u8 i; | ||
242 | |||
243 | DBGPRINT(RT_DEBUG_TRACE, | ||
244 | ("RTMPWPARemoveAllKeys(AuthMode=%d, WepStatus=%d)\n", | ||
245 | pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus)); | ||
246 | RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); | ||
247 | /* For WEP/CKIP, there is no need to remove it, since WinXP won't set it again after */ | ||
248 | /* Link up. And it will be replaced if user changed it. */ | ||
249 | if (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA) | ||
250 | return; | ||
251 | |||
252 | /* For WPA-None, there is no need to remove it, since WinXP won't set it again after */ | ||
253 | /* Link up. And it will be replaced if user changed it. */ | ||
254 | if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) | ||
255 | return; | ||
256 | |||
257 | /* set BSSID wcid entry of the Pair-wise Key table as no-security mode */ | ||
258 | AsicRemovePairwiseKeyEntry(pAd, BSS0, BSSID_WCID); | ||
259 | |||
260 | /* set all shared key mode as no-security. */ | ||
261 | for (i = 0; i < SHARE_KEY_NUM; i++) { | ||
262 | DBGPRINT(RT_DEBUG_TRACE, | ||
263 | ("remove %s key #%d\n", | ||
264 | CipherName[pAd->SharedKey[BSS0][i].CipherAlg], i)); | ||
265 | NdisZeroMemory(&pAd->SharedKey[BSS0][i], sizeof(struct rt_cipher_key)); | ||
266 | |||
267 | AsicRemoveSharedKeyEntry(pAd, BSS0, i); | ||
268 | } | ||
269 | RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); | ||
270 | } | ||
271 | |||
272 | /* | ||
273 | ======================================================================== | ||
274 | |||
275 | Routine Description: | ||
276 | As STA's BSSID is a WC too, it uses shared key table. | ||
277 | This function write correct unicast TX key to ASIC WCID. | ||
278 | And we still make a copy in our MacTab.Content[BSSID_WCID].PairwiseKey. | ||
279 | Caller guarantee TKIP/AES always has keyidx = 0. (pairwise key) | ||
280 | Caller guarantee WEP calls this function when set Txkey, default key index=0~3. | ||
281 | |||
282 | Arguments: | ||
283 | pAd Pointer to our adapter | ||
284 | pKey Pointer to the where the key stored | ||
285 | |||
286 | Return Value: | ||
287 | NDIS_SUCCESS Add key successfully | ||
288 | |||
289 | IRQL = DISPATCH_LEVEL | ||
290 | |||
291 | Note: | ||
292 | |||
293 | ======================================================================== | ||
294 | */ | ||
295 | /* | ||
296 | ======================================================================== | ||
297 | Routine Description: | ||
298 | Change NIC PHY mode. Re-association may be necessary. possible settings | ||
299 | include - PHY_11B, PHY_11BG_MIXED, PHY_11A, and PHY_11ABG_MIXED | ||
300 | |||
301 | Arguments: | ||
302 | pAd - Pointer to our adapter | ||
303 | phymode - | ||
304 | |||
305 | IRQL = PASSIVE_LEVEL | ||
306 | IRQL = DISPATCH_LEVEL | ||
307 | |||
308 | ======================================================================== | ||
309 | */ | ||
310 | void RTMPSetPhyMode(struct rt_rtmp_adapter *pAd, unsigned long phymode) | ||
311 | { | ||
312 | int i; | ||
313 | /* the selected phymode must be supported by the RF IC encoded in E2PROM */ | ||
314 | |||
315 | /* if no change, do nothing */ | ||
316 | /* bug fix | ||
317 | if (pAd->CommonCfg.PhyMode == phymode) | ||
318 | return; | ||
319 | */ | ||
320 | pAd->CommonCfg.PhyMode = (u8)phymode; | ||
321 | |||
322 | DBGPRINT(RT_DEBUG_TRACE, | ||
323 | ("RTMPSetPhyMode : PhyMode=%d, channel=%d \n", | ||
324 | pAd->CommonCfg.PhyMode, pAd->CommonCfg.Channel)); | ||
325 | |||
326 | BuildChannelList(pAd); | ||
327 | |||
328 | /* sanity check user setting */ | ||
329 | for (i = 0; i < pAd->ChannelListNum; i++) { | ||
330 | if (pAd->CommonCfg.Channel == pAd->ChannelList[i].Channel) | ||
331 | break; | ||
332 | } | ||
333 | |||
334 | if (i == pAd->ChannelListNum) { | ||
335 | pAd->CommonCfg.Channel = FirstChannel(pAd); | ||
336 | DBGPRINT(RT_DEBUG_ERROR, | ||
337 | ("RTMPSetPhyMode: channel is out of range, use first channel=%d \n", | ||
338 | pAd->CommonCfg.Channel)); | ||
339 | } | ||
340 | |||
341 | NdisZeroMemory(pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES); | ||
342 | NdisZeroMemory(pAd->CommonCfg.ExtRate, MAX_LEN_OF_SUPPORTED_RATES); | ||
343 | NdisZeroMemory(pAd->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES); | ||
344 | switch (phymode) { | ||
345 | case PHY_11B: | ||
346 | pAd->CommonCfg.SupRate[0] = 0x82; /* 1 mbps, in units of 0.5 Mbps, basic rate */ | ||
347 | pAd->CommonCfg.SupRate[1] = 0x84; /* 2 mbps, in units of 0.5 Mbps, basic rate */ | ||
348 | pAd->CommonCfg.SupRate[2] = 0x8B; /* 5.5 mbps, in units of 0.5 Mbps, basic rate */ | ||
349 | pAd->CommonCfg.SupRate[3] = 0x96; /* 11 mbps, in units of 0.5 Mbps, basic rate */ | ||
350 | pAd->CommonCfg.SupRateLen = 4; | ||
351 | pAd->CommonCfg.ExtRateLen = 0; | ||
352 | pAd->CommonCfg.DesireRate[0] = 2; /* 1 mbps, in units of 0.5 Mbps */ | ||
353 | pAd->CommonCfg.DesireRate[1] = 4; /* 2 mbps, in units of 0.5 Mbps */ | ||
354 | pAd->CommonCfg.DesireRate[2] = 11; /* 5.5 mbps, in units of 0.5 Mbps */ | ||
355 | pAd->CommonCfg.DesireRate[3] = 22; /* 11 mbps, in units of 0.5 Mbps */ | ||
356 | /*pAd->CommonCfg.HTPhyMode.field.MODE = MODE_CCK; // This MODE is only FYI. not use */ | ||
357 | break; | ||
358 | |||
359 | case PHY_11G: | ||
360 | case PHY_11BG_MIXED: | ||
361 | case PHY_11ABG_MIXED: | ||
362 | case PHY_11N_2_4G: | ||
363 | case PHY_11ABGN_MIXED: | ||
364 | case PHY_11BGN_MIXED: | ||
365 | case PHY_11GN_MIXED: | ||
366 | pAd->CommonCfg.SupRate[0] = 0x82; /* 1 mbps, in units of 0.5 Mbps, basic rate */ | ||
367 | pAd->CommonCfg.SupRate[1] = 0x84; /* 2 mbps, in units of 0.5 Mbps, basic rate */ | ||
368 | pAd->CommonCfg.SupRate[2] = 0x8B; /* 5.5 mbps, in units of 0.5 Mbps, basic rate */ | ||
369 | pAd->CommonCfg.SupRate[3] = 0x96; /* 11 mbps, in units of 0.5 Mbps, basic rate */ | ||
370 | pAd->CommonCfg.SupRate[4] = 0x12; /* 9 mbps, in units of 0.5 Mbps */ | ||
371 | pAd->CommonCfg.SupRate[5] = 0x24; /* 18 mbps, in units of 0.5 Mbps */ | ||
372 | pAd->CommonCfg.SupRate[6] = 0x48; /* 36 mbps, in units of 0.5 Mbps */ | ||
373 | pAd->CommonCfg.SupRate[7] = 0x6c; /* 54 mbps, in units of 0.5 Mbps */ | ||
374 | pAd->CommonCfg.SupRateLen = 8; | ||
375 | pAd->CommonCfg.ExtRate[0] = 0x0C; /* 6 mbps, in units of 0.5 Mbps */ | ||
376 | pAd->CommonCfg.ExtRate[1] = 0x18; /* 12 mbps, in units of 0.5 Mbps */ | ||
377 | pAd->CommonCfg.ExtRate[2] = 0x30; /* 24 mbps, in units of 0.5 Mbps */ | ||
378 | pAd->CommonCfg.ExtRate[3] = 0x60; /* 48 mbps, in units of 0.5 Mbps */ | ||
379 | pAd->CommonCfg.ExtRateLen = 4; | ||
380 | pAd->CommonCfg.DesireRate[0] = 2; /* 1 mbps, in units of 0.5 Mbps */ | ||
381 | pAd->CommonCfg.DesireRate[1] = 4; /* 2 mbps, in units of 0.5 Mbps */ | ||
382 | pAd->CommonCfg.DesireRate[2] = 11; /* 5.5 mbps, in units of 0.5 Mbps */ | ||
383 | pAd->CommonCfg.DesireRate[3] = 22; /* 11 mbps, in units of 0.5 Mbps */ | ||
384 | pAd->CommonCfg.DesireRate[4] = 12; /* 6 mbps, in units of 0.5 Mbps */ | ||
385 | pAd->CommonCfg.DesireRate[5] = 18; /* 9 mbps, in units of 0.5 Mbps */ | ||
386 | pAd->CommonCfg.DesireRate[6] = 24; /* 12 mbps, in units of 0.5 Mbps */ | ||
387 | pAd->CommonCfg.DesireRate[7] = 36; /* 18 mbps, in units of 0.5 Mbps */ | ||
388 | pAd->CommonCfg.DesireRate[8] = 48; /* 24 mbps, in units of 0.5 Mbps */ | ||
389 | pAd->CommonCfg.DesireRate[9] = 72; /* 36 mbps, in units of 0.5 Mbps */ | ||
390 | pAd->CommonCfg.DesireRate[10] = 96; /* 48 mbps, in units of 0.5 Mbps */ | ||
391 | pAd->CommonCfg.DesireRate[11] = 108; /* 54 mbps, in units of 0.5 Mbps */ | ||
392 | break; | ||
393 | |||
394 | case PHY_11A: | ||
395 | case PHY_11AN_MIXED: | ||
396 | case PHY_11AGN_MIXED: | ||
397 | case PHY_11N_5G: | ||
398 | pAd->CommonCfg.SupRate[0] = 0x8C; /* 6 mbps, in units of 0.5 Mbps, basic rate */ | ||
399 | pAd->CommonCfg.SupRate[1] = 0x12; /* 9 mbps, in units of 0.5 Mbps */ | ||
400 | pAd->CommonCfg.SupRate[2] = 0x98; /* 12 mbps, in units of 0.5 Mbps, basic rate */ | ||
401 | pAd->CommonCfg.SupRate[3] = 0x24; /* 18 mbps, in units of 0.5 Mbps */ | ||
402 | pAd->CommonCfg.SupRate[4] = 0xb0; /* 24 mbps, in units of 0.5 Mbps, basic rate */ | ||
403 | pAd->CommonCfg.SupRate[5] = 0x48; /* 36 mbps, in units of 0.5 Mbps */ | ||
404 | pAd->CommonCfg.SupRate[6] = 0x60; /* 48 mbps, in units of 0.5 Mbps */ | ||
405 | pAd->CommonCfg.SupRate[7] = 0x6c; /* 54 mbps, in units of 0.5 Mbps */ | ||
406 | pAd->CommonCfg.SupRateLen = 8; | ||
407 | pAd->CommonCfg.ExtRateLen = 0; | ||
408 | pAd->CommonCfg.DesireRate[0] = 12; /* 6 mbps, in units of 0.5 Mbps */ | ||
409 | pAd->CommonCfg.DesireRate[1] = 18; /* 9 mbps, in units of 0.5 Mbps */ | ||
410 | pAd->CommonCfg.DesireRate[2] = 24; /* 12 mbps, in units of 0.5 Mbps */ | ||
411 | pAd->CommonCfg.DesireRate[3] = 36; /* 18 mbps, in units of 0.5 Mbps */ | ||
412 | pAd->CommonCfg.DesireRate[4] = 48; /* 24 mbps, in units of 0.5 Mbps */ | ||
413 | pAd->CommonCfg.DesireRate[5] = 72; /* 36 mbps, in units of 0.5 Mbps */ | ||
414 | pAd->CommonCfg.DesireRate[6] = 96; /* 48 mbps, in units of 0.5 Mbps */ | ||
415 | pAd->CommonCfg.DesireRate[7] = 108; /* 54 mbps, in units of 0.5 Mbps */ | ||
416 | /*pAd->CommonCfg.HTPhyMode.field.MODE = MODE_OFDM; // This MODE is only FYI. not use */ | ||
417 | break; | ||
418 | |||
419 | default: | ||
420 | break; | ||
421 | } | ||
422 | |||
423 | pAd->CommonCfg.BandState = UNKNOWN_BAND; | ||
424 | } | ||
425 | |||
426 | /* | ||
427 | ======================================================================== | ||
428 | Routine Description: | ||
429 | Caller ensures we has 802.11n support. | ||
430 | Calls at setting HT from AP/STASetinformation | ||
431 | |||
432 | Arguments: | ||
433 | pAd - Pointer to our adapter | ||
434 | phymode - | ||
435 | |||
436 | ======================================================================== | ||
437 | */ | ||
438 | void RTMPSetHT(struct rt_rtmp_adapter *pAd, struct rt_oid_set_ht_phymode *pHTPhyMode) | ||
439 | { | ||
440 | /*unsigned long *pmcs; */ | ||
441 | u32 Value = 0; | ||
442 | u8 BBPValue = 0; | ||
443 | u8 BBP3Value = 0; | ||
444 | u8 RxStream = pAd->CommonCfg.RxStream; | ||
445 | |||
446 | DBGPRINT(RT_DEBUG_TRACE, | ||
447 | ("RTMPSetHT : HT_mode(%d), ExtOffset(%d), MCS(%d), BW(%d), STBC(%d), SHORTGI(%d)\n", | ||
448 | pHTPhyMode->HtMode, pHTPhyMode->ExtOffset, pHTPhyMode->MCS, | ||
449 | pHTPhyMode->BW, pHTPhyMode->STBC, pHTPhyMode->SHORTGI)); | ||
450 | |||
451 | /* Don't zero supportedHyPhy structure. */ | ||
452 | RTMPZeroMemory(&pAd->CommonCfg.HtCapability, | ||
453 | sizeof(pAd->CommonCfg.HtCapability)); | ||
454 | RTMPZeroMemory(&pAd->CommonCfg.AddHTInfo, | ||
455 | sizeof(pAd->CommonCfg.AddHTInfo)); | ||
456 | RTMPZeroMemory(&pAd->CommonCfg.NewExtChanOffset, | ||
457 | sizeof(pAd->CommonCfg.NewExtChanOffset)); | ||
458 | RTMPZeroMemory(&pAd->CommonCfg.DesiredHtPhy, | ||
459 | sizeof(pAd->CommonCfg.DesiredHtPhy)); | ||
460 | |||
461 | if (pAd->CommonCfg.bRdg) { | ||
462 | pAd->CommonCfg.HtCapability.ExtHtCapInfo.PlusHTC = 1; | ||
463 | pAd->CommonCfg.HtCapability.ExtHtCapInfo.RDGSupport = 1; | ||
464 | } else { | ||
465 | pAd->CommonCfg.HtCapability.ExtHtCapInfo.PlusHTC = 0; | ||
466 | pAd->CommonCfg.HtCapability.ExtHtCapInfo.RDGSupport = 0; | ||
467 | } | ||
468 | |||
469 | pAd->CommonCfg.HtCapability.HtCapParm.MaxRAmpduFactor = 3; | ||
470 | pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor = 3; | ||
471 | |||
472 | DBGPRINT(RT_DEBUG_TRACE, | ||
473 | ("RTMPSetHT : RxBAWinLimit = %d\n", | ||
474 | pAd->CommonCfg.BACapability.field.RxBAWinLimit)); | ||
475 | |||
476 | /* Mimo power save, A-MSDU size, */ | ||
477 | pAd->CommonCfg.DesiredHtPhy.AmsduEnable = | ||
478 | (u16)pAd->CommonCfg.BACapability.field.AmsduEnable; | ||
479 | pAd->CommonCfg.DesiredHtPhy.AmsduSize = | ||
480 | (u8)pAd->CommonCfg.BACapability.field.AmsduSize; | ||
481 | pAd->CommonCfg.DesiredHtPhy.MimoPs = | ||
482 | (u8)pAd->CommonCfg.BACapability.field.MMPSmode; | ||
483 | pAd->CommonCfg.DesiredHtPhy.MpduDensity = | ||
484 | (u8)pAd->CommonCfg.BACapability.field.MpduDensity; | ||
485 | |||
486 | pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize = | ||
487 | (u16)pAd->CommonCfg.BACapability.field.AmsduSize; | ||
488 | pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs = | ||
489 | (u16)pAd->CommonCfg.BACapability.field.MMPSmode; | ||
490 | pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity = | ||
491 | (u8)pAd->CommonCfg.BACapability.field.MpduDensity; | ||
492 | |||
493 | DBGPRINT(RT_DEBUG_TRACE, | ||
494 | ("RTMPSetHT : AMsduSize = %d, MimoPs = %d, MpduDensity = %d, MaxRAmpduFactor = %d\n", | ||
495 | pAd->CommonCfg.DesiredHtPhy.AmsduSize, | ||
496 | pAd->CommonCfg.DesiredHtPhy.MimoPs, | ||
497 | pAd->CommonCfg.DesiredHtPhy.MpduDensity, | ||
498 | pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor)); | ||
499 | |||
500 | if (pHTPhyMode->HtMode == HTMODE_GF) { | ||
501 | pAd->CommonCfg.HtCapability.HtCapInfo.GF = 1; | ||
502 | pAd->CommonCfg.DesiredHtPhy.GF = 1; | ||
503 | } else | ||
504 | pAd->CommonCfg.DesiredHtPhy.GF = 0; | ||
505 | |||
506 | /* Decide Rx MCSSet */ | ||
507 | switch (RxStream) { | ||
508 | case 1: | ||
509 | pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff; | ||
510 | pAd->CommonCfg.HtCapability.MCSSet[1] = 0x00; | ||
511 | break; | ||
512 | |||
513 | case 2: | ||
514 | pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff; | ||
515 | pAd->CommonCfg.HtCapability.MCSSet[1] = 0xff; | ||
516 | break; | ||
517 | |||
518 | case 3: /* 3*3 */ | ||
519 | pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff; | ||
520 | pAd->CommonCfg.HtCapability.MCSSet[1] = 0xff; | ||
521 | pAd->CommonCfg.HtCapability.MCSSet[2] = 0xff; | ||
522 | break; | ||
523 | } | ||
524 | |||
525 | if (pAd->CommonCfg.bForty_Mhz_Intolerant | ||
526 | && (pAd->CommonCfg.Channel <= 14) && (pHTPhyMode->BW == BW_40)) { | ||
527 | pHTPhyMode->BW = BW_20; | ||
528 | pAd->CommonCfg.HtCapability.HtCapInfo.Forty_Mhz_Intolerant = 1; | ||
529 | } | ||
530 | |||
531 | if (pHTPhyMode->BW == BW_40) { | ||
532 | pAd->CommonCfg.HtCapability.MCSSet[4] = 0x1; /* MCS 32 */ | ||
533 | pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = 1; | ||
534 | if (pAd->CommonCfg.Channel <= 14) | ||
535 | pAd->CommonCfg.HtCapability.HtCapInfo.CCKmodein40 = 1; | ||
536 | |||
537 | pAd->CommonCfg.DesiredHtPhy.ChannelWidth = 1; | ||
538 | pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 1; | ||
539 | pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = | ||
540 | (pHTPhyMode->ExtOffset == | ||
541 | EXTCHA_BELOW) ? (EXTCHA_BELOW) : EXTCHA_ABOVE; | ||
542 | /* Set Regsiter for extension channel position. */ | ||
543 | RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); | ||
544 | RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBP3Value); | ||
545 | if ((pHTPhyMode->ExtOffset == EXTCHA_BELOW)) { | ||
546 | Value |= 0x1; | ||
547 | BBP3Value |= (0x20); | ||
548 | RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); | ||
549 | } else if ((pHTPhyMode->ExtOffset == EXTCHA_ABOVE)) { | ||
550 | Value &= 0xfe; | ||
551 | BBP3Value &= (~0x20); | ||
552 | RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); | ||
553 | } | ||
554 | /* Turn on BBP 40MHz mode now only as AP . */ | ||
555 | /* Sta can turn on BBP 40MHz after connection with 40MHz AP. Sta only broadcast 40MHz capability before connection. */ | ||
556 | if ((pAd->OpMode == OPMODE_AP) || INFRA_ON(pAd) || ADHOC_ON(pAd) | ||
557 | ) { | ||
558 | RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); | ||
559 | BBPValue &= (~0x18); | ||
560 | BBPValue |= 0x10; | ||
561 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); | ||
562 | |||
563 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBP3Value); | ||
564 | pAd->CommonCfg.BBPCurrentBW = BW_40; | ||
565 | } | ||
566 | } else { | ||
567 | pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = 0; | ||
568 | pAd->CommonCfg.DesiredHtPhy.ChannelWidth = 0; | ||
569 | pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0; | ||
570 | pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = EXTCHA_NONE; | ||
571 | pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; | ||
572 | /* Turn on BBP 20MHz mode by request here. */ | ||
573 | { | ||
574 | RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); | ||
575 | BBPValue &= (~0x18); | ||
576 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); | ||
577 | pAd->CommonCfg.BBPCurrentBW = BW_20; | ||
578 | } | ||
579 | } | ||
580 | |||
581 | if (pHTPhyMode->STBC == STBC_USE) { | ||
582 | pAd->CommonCfg.HtCapability.HtCapInfo.TxSTBC = 1; | ||
583 | pAd->CommonCfg.DesiredHtPhy.TxSTBC = 1; | ||
584 | pAd->CommonCfg.HtCapability.HtCapInfo.RxSTBC = 1; | ||
585 | pAd->CommonCfg.DesiredHtPhy.RxSTBC = 1; | ||
586 | } else { | ||
587 | pAd->CommonCfg.DesiredHtPhy.TxSTBC = 0; | ||
588 | pAd->CommonCfg.DesiredHtPhy.RxSTBC = 0; | ||
589 | } | ||
590 | |||
591 | if (pHTPhyMode->SHORTGI == GI_400) { | ||
592 | pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor20 = 1; | ||
593 | pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor40 = 1; | ||
594 | pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 = 1; | ||
595 | pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 = 1; | ||
596 | } else { | ||
597 | pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor20 = 0; | ||
598 | pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor40 = 0; | ||
599 | pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 = 0; | ||
600 | pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 = 0; | ||
601 | } | ||
602 | |||
603 | /* We support link adaptation for unsolicit MCS feedback, set to 2. */ | ||
604 | pAd->CommonCfg.HtCapability.ExtHtCapInfo.MCSFeedback = MCSFBK_NONE; /*MCSFBK_UNSOLICIT; */ | ||
605 | pAd->CommonCfg.AddHTInfo.ControlChan = pAd->CommonCfg.Channel; | ||
606 | /* 1, the extension channel above the control channel. */ | ||
607 | |||
608 | /* EDCA parameters used for AP's own transmission */ | ||
609 | if (pAd->CommonCfg.APEdcaParm.bValid == FALSE) { | ||
610 | pAd->CommonCfg.APEdcaParm.bValid = TRUE; | ||
611 | pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3; | ||
612 | pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7; | ||
613 | pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1; | ||
614 | pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1; | ||
615 | |||
616 | pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4; | ||
617 | pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4; | ||
618 | pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3; | ||
619 | pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2; | ||
620 | |||
621 | pAd->CommonCfg.APEdcaParm.Cwmax[0] = 6; | ||
622 | pAd->CommonCfg.APEdcaParm.Cwmax[1] = 10; | ||
623 | pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4; | ||
624 | pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3; | ||
625 | |||
626 | pAd->CommonCfg.APEdcaParm.Txop[0] = 0; | ||
627 | pAd->CommonCfg.APEdcaParm.Txop[1] = 0; | ||
628 | pAd->CommonCfg.APEdcaParm.Txop[2] = 94; | ||
629 | pAd->CommonCfg.APEdcaParm.Txop[3] = 47; | ||
630 | } | ||
631 | AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); | ||
632 | |||
633 | { | ||
634 | RTMPSetIndividualHT(pAd, 0); | ||
635 | } | ||
636 | |||
637 | } | ||
638 | |||
639 | /* | ||
640 | ======================================================================== | ||
641 | Routine Description: | ||
642 | Caller ensures we has 802.11n support. | ||
643 | Calls at setting HT from AP/STASetinformation | ||
644 | |||
645 | Arguments: | ||
646 | pAd - Pointer to our adapter | ||
647 | phymode - | ||
648 | |||
649 | ======================================================================== | ||
650 | */ | ||
651 | void RTMPSetIndividualHT(struct rt_rtmp_adapter *pAd, u8 apidx) | ||
652 | { | ||
653 | struct rt_ht_phy_info *pDesired_ht_phy = NULL; | ||
654 | u8 TxStream = pAd->CommonCfg.TxStream; | ||
655 | u8 DesiredMcs = MCS_AUTO; | ||
656 | |||
657 | do { | ||
658 | { | ||
659 | pDesired_ht_phy = &pAd->StaCfg.DesiredHtPhyInfo; | ||
660 | DesiredMcs = | ||
661 | pAd->StaCfg.DesiredTransmitSetting.field.MCS; | ||
662 | /*pAd->StaCfg.bAutoTxRateSwitch = (DesiredMcs == MCS_AUTO) ? TRUE : FALSE; */ | ||
663 | break; | ||
664 | } | ||
665 | } while (FALSE); | ||
666 | |||
667 | if (pDesired_ht_phy == NULL) { | ||
668 | DBGPRINT(RT_DEBUG_ERROR, | ||
669 | ("RTMPSetIndividualHT: invalid apidx(%d)\n", apidx)); | ||
670 | return; | ||
671 | } | ||
672 | RTMPZeroMemory(pDesired_ht_phy, sizeof(struct rt_ht_phy_info)); | ||
673 | |||
674 | DBGPRINT(RT_DEBUG_TRACE, | ||
675 | ("RTMPSetIndividualHT : Desired MCS = %d\n", DesiredMcs)); | ||
676 | /* Check the validity of MCS */ | ||
677 | if ((TxStream == 1) | ||
678 | && ((DesiredMcs >= MCS_8) && (DesiredMcs <= MCS_15))) { | ||
679 | DBGPRINT(RT_DEBUG_WARN, | ||
680 | ("RTMPSetIndividualHT: MCS(%d) is invalid in 1S, reset it as MCS_7\n", | ||
681 | DesiredMcs)); | ||
682 | DesiredMcs = MCS_7; | ||
683 | } | ||
684 | |||
685 | if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BW_20) | ||
686 | && (DesiredMcs == MCS_32)) { | ||
687 | DBGPRINT(RT_DEBUG_WARN, | ||
688 | ("RTMPSetIndividualHT: MCS_32 is only supported in 40-MHz, reset it as MCS_0\n")); | ||
689 | DesiredMcs = MCS_0; | ||
690 | } | ||
691 | |||
692 | pDesired_ht_phy->bHtEnable = TRUE; | ||
693 | |||
694 | /* Decide desired Tx MCS */ | ||
695 | switch (TxStream) { | ||
696 | case 1: | ||
697 | if (DesiredMcs == MCS_AUTO) { | ||
698 | pDesired_ht_phy->MCSSet[0] = 0xff; | ||
699 | pDesired_ht_phy->MCSSet[1] = 0x00; | ||
700 | } else if (DesiredMcs <= MCS_7) { | ||
701 | pDesired_ht_phy->MCSSet[0] = 1 << DesiredMcs; | ||
702 | pDesired_ht_phy->MCSSet[1] = 0x00; | ||
703 | } | ||
704 | break; | ||
705 | |||
706 | case 2: | ||
707 | if (DesiredMcs == MCS_AUTO) { | ||
708 | pDesired_ht_phy->MCSSet[0] = 0xff; | ||
709 | pDesired_ht_phy->MCSSet[1] = 0xff; | ||
710 | } else if (DesiredMcs <= MCS_15) { | ||
711 | unsigned long mode; | ||
712 | |||
713 | mode = DesiredMcs / 8; | ||
714 | if (mode < 2) | ||
715 | pDesired_ht_phy->MCSSet[mode] = | ||
716 | (1 << (DesiredMcs - mode * 8)); | ||
717 | } | ||
718 | break; | ||
719 | |||
720 | case 3: /* 3*3 */ | ||
721 | if (DesiredMcs == MCS_AUTO) { | ||
722 | /* MCS0 ~ MCS23, 3 bytes */ | ||
723 | pDesired_ht_phy->MCSSet[0] = 0xff; | ||
724 | pDesired_ht_phy->MCSSet[1] = 0xff; | ||
725 | pDesired_ht_phy->MCSSet[2] = 0xff; | ||
726 | } else if (DesiredMcs <= MCS_23) { | ||
727 | unsigned long mode; | ||
728 | |||
729 | mode = DesiredMcs / 8; | ||
730 | if (mode < 3) | ||
731 | pDesired_ht_phy->MCSSet[mode] = | ||
732 | (1 << (DesiredMcs - mode * 8)); | ||
733 | } | ||
734 | break; | ||
735 | } | ||
736 | |||
737 | if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BW_40) { | ||
738 | if (DesiredMcs == MCS_AUTO || DesiredMcs == MCS_32) | ||
739 | pDesired_ht_phy->MCSSet[4] = 0x1; | ||
740 | } | ||
741 | /* update HT Rate setting */ | ||
742 | if (pAd->OpMode == OPMODE_STA) | ||
743 | MlmeUpdateHtTxRates(pAd, BSS0); | ||
744 | else | ||
745 | MlmeUpdateHtTxRates(pAd, apidx); | ||
746 | } | ||
747 | |||
748 | /* | ||
749 | ======================================================================== | ||
750 | Routine Description: | ||
751 | Update HT IE from our capability. | ||
752 | |||
753 | Arguments: | ||
754 | Send all HT IE in beacon/probe rsp/assoc rsp/action frame. | ||
755 | |||
756 | ======================================================================== | ||
757 | */ | ||
758 | void RTMPUpdateHTIE(struct rt_ht_capability *pRtHt, | ||
759 | u8 * pMcsSet, | ||
760 | struct rt_ht_capability_ie * pHtCapability, | ||
761 | struct rt_add_ht_info_ie * pAddHtInfo) | ||
762 | { | ||
763 | RTMPZeroMemory(pHtCapability, sizeof(struct rt_ht_capability_ie)); | ||
764 | RTMPZeroMemory(pAddHtInfo, sizeof(struct rt_add_ht_info_ie)); | ||
765 | |||
766 | pHtCapability->HtCapInfo.ChannelWidth = pRtHt->ChannelWidth; | ||
767 | pHtCapability->HtCapInfo.MimoPs = pRtHt->MimoPs; | ||
768 | pHtCapability->HtCapInfo.GF = pRtHt->GF; | ||
769 | pHtCapability->HtCapInfo.ShortGIfor20 = pRtHt->ShortGIfor20; | ||
770 | pHtCapability->HtCapInfo.ShortGIfor40 = pRtHt->ShortGIfor40; | ||
771 | pHtCapability->HtCapInfo.TxSTBC = pRtHt->TxSTBC; | ||
772 | pHtCapability->HtCapInfo.RxSTBC = pRtHt->RxSTBC; | ||
773 | pHtCapability->HtCapInfo.AMsduSize = pRtHt->AmsduSize; | ||
774 | pHtCapability->HtCapParm.MaxRAmpduFactor = pRtHt->MaxRAmpduFactor; | ||
775 | pHtCapability->HtCapParm.MpduDensity = pRtHt->MpduDensity; | ||
776 | |||
777 | pAddHtInfo->AddHtInfo.ExtChanOffset = pRtHt->ExtChanOffset; | ||
778 | pAddHtInfo->AddHtInfo.RecomWidth = pRtHt->RecomWidth; | ||
779 | pAddHtInfo->AddHtInfo2.OperaionMode = pRtHt->OperaionMode; | ||
780 | pAddHtInfo->AddHtInfo2.NonGfPresent = pRtHt->NonGfPresent; | ||
781 | RTMPMoveMemory(pAddHtInfo->MCSSet, /*pRtHt->MCSSet */ pMcsSet, 4); /* rt2860 only support MCS max=32, no need to copy all 16 uchar. */ | ||
782 | |||
783 | DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateHTIE <== \n")); | ||
784 | } | ||
785 | |||
786 | /* | ||
787 | ======================================================================== | ||
788 | Description: | ||
789 | Add Client security information into ASIC WCID table and IVEIV table. | ||
790 | Return: | ||
791 | ======================================================================== | ||
792 | */ | ||
793 | void RTMPAddWcidAttributeEntry(struct rt_rtmp_adapter *pAd, | ||
794 | u8 BssIdx, | ||
795 | u8 KeyIdx, | ||
796 | u8 CipherAlg, struct rt_mac_table_entry *pEntry) | ||
797 | { | ||
798 | u32 WCIDAttri = 0; | ||
799 | u16 offset; | ||
800 | u8 IVEIV = 0; | ||
801 | u16 Wcid = 0; | ||
802 | |||
803 | { | ||
804 | { | ||
805 | if (BssIdx > BSS0) { | ||
806 | DBGPRINT(RT_DEBUG_ERROR, | ||
807 | ("RTMPAddWcidAttributeEntry: The BSS-index(%d) is out of range for Infra link. \n", | ||
808 | BssIdx)); | ||
809 | return; | ||
810 | } | ||
811 | /* 1. In ADHOC mode, the AID is wcid number. And NO mesh link exists. */ | ||
812 | /* 2. In Infra mode, the AID:1 MUST be wcid of infra STA. */ | ||
813 | /* the AID:2~ assign to mesh link entry. */ | ||
814 | if (pEntry) | ||
815 | Wcid = pEntry->Aid; | ||
816 | else | ||
817 | Wcid = MCAST_WCID; | ||
818 | } | ||
819 | } | ||
820 | |||
821 | /* Update WCID attribute table */ | ||
822 | offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE); | ||
823 | |||
824 | { | ||
825 | if (pEntry && pEntry->ValidAsMesh) | ||
826 | WCIDAttri = (CipherAlg << 1) | PAIRWISEKEYTABLE; | ||
827 | else | ||
828 | WCIDAttri = (CipherAlg << 1) | SHAREDKEYTABLE; | ||
829 | } | ||
830 | |||
831 | RTMP_IO_WRITE32(pAd, offset, WCIDAttri); | ||
832 | |||
833 | /* Update IV/EIV table */ | ||
834 | offset = MAC_IVEIV_TABLE_BASE + (Wcid * HW_IVEIV_ENTRY_SIZE); | ||
835 | |||
836 | /* WPA mode */ | ||
837 | if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) | ||
838 | || (CipherAlg == CIPHER_AES)) { | ||
839 | /* Eiv bit on. keyid always is 0 for pairwise key */ | ||
840 | IVEIV = (KeyIdx << 6) | 0x20; | ||
841 | } else { | ||
842 | /* WEP KeyIdx is default tx key. */ | ||
843 | IVEIV = (KeyIdx << 6); | ||
844 | } | ||
845 | |||
846 | /* For key index and ext IV bit, so only need to update the position(offset+3). */ | ||
847 | #ifdef RTMP_MAC_PCI | ||
848 | RTMP_IO_WRITE8(pAd, offset + 3, IVEIV); | ||
849 | #endif /* RTMP_MAC_PCI // */ | ||
850 | #ifdef RTMP_MAC_USB | ||
851 | RTUSBMultiWrite_OneByte(pAd, offset + 3, &IVEIV); | ||
852 | #endif /* RTMP_MAC_USB // */ | ||
853 | |||
854 | DBGPRINT(RT_DEBUG_TRACE, | ||
855 | ("RTMPAddWcidAttributeEntry: WCID #%d, KeyIndex #%d, Alg=%s\n", | ||
856 | Wcid, KeyIdx, CipherName[CipherAlg])); | ||
857 | DBGPRINT(RT_DEBUG_TRACE, (" WCIDAttri = 0x%x \n", WCIDAttri)); | ||
858 | |||
859 | } | ||
860 | |||
861 | /* | ||
862 | ========================================================================== | ||
863 | Description: | ||
864 | Parse encryption type | ||
865 | Arguments: | ||
866 | pAdapter Pointer to our adapter | ||
867 | wrq Pointer to the ioctl argument | ||
868 | |||
869 | Return Value: | ||
870 | None | ||
871 | |||
872 | Note: | ||
873 | ========================================================================== | ||
874 | */ | ||
875 | char *GetEncryptType(char enc) | ||
876 | { | ||
877 | if (enc == Ndis802_11WEPDisabled) | ||
878 | return "NONE"; | ||
879 | if (enc == Ndis802_11WEPEnabled) | ||
880 | return "WEP"; | ||
881 | if (enc == Ndis802_11Encryption2Enabled) | ||
882 | return "TKIP"; | ||
883 | if (enc == Ndis802_11Encryption3Enabled) | ||
884 | return "AES"; | ||
885 | if (enc == Ndis802_11Encryption4Enabled) | ||
886 | return "TKIPAES"; | ||
887 | else | ||
888 | return "UNKNOW"; | ||
889 | } | ||
890 | |||
891 | char *GetAuthMode(char auth) | ||
892 | { | ||
893 | if (auth == Ndis802_11AuthModeOpen) | ||
894 | return "OPEN"; | ||
895 | if (auth == Ndis802_11AuthModeShared) | ||
896 | return "SHARED"; | ||
897 | if (auth == Ndis802_11AuthModeAutoSwitch) | ||
898 | return "AUTOWEP"; | ||
899 | if (auth == Ndis802_11AuthModeWPA) | ||
900 | return "WPA"; | ||
901 | if (auth == Ndis802_11AuthModeWPAPSK) | ||
902 | return "WPAPSK"; | ||
903 | if (auth == Ndis802_11AuthModeWPANone) | ||
904 | return "WPANONE"; | ||
905 | if (auth == Ndis802_11AuthModeWPA2) | ||
906 | return "WPA2"; | ||
907 | if (auth == Ndis802_11AuthModeWPA2PSK) | ||
908 | return "WPA2PSK"; | ||
909 | if (auth == Ndis802_11AuthModeWPA1WPA2) | ||
910 | return "WPA1WPA2"; | ||
911 | if (auth == Ndis802_11AuthModeWPA1PSKWPA2PSK) | ||
912 | return "WPA1PSKWPA2PSK"; | ||
913 | |||
914 | return "UNKNOW"; | ||
915 | } | ||
916 | |||
917 | int SetCommonHT(struct rt_rtmp_adapter *pAd) | ||
918 | { | ||
919 | struct rt_oid_set_ht_phymode SetHT; | ||
920 | |||
921 | if (pAd->CommonCfg.PhyMode < PHY_11ABGN_MIXED) | ||
922 | return FALSE; | ||
923 | |||
924 | SetHT.PhyMode = pAd->CommonCfg.PhyMode; | ||
925 | SetHT.TransmitNo = ((u8)pAd->Antenna.field.TxPath); | ||
926 | SetHT.HtMode = (u8)pAd->CommonCfg.RegTransmitSetting.field.HTMODE; | ||
927 | SetHT.ExtOffset = | ||
928 | (u8)pAd->CommonCfg.RegTransmitSetting.field.EXTCHA; | ||
929 | SetHT.MCS = MCS_AUTO; | ||
930 | SetHT.BW = (u8)pAd->CommonCfg.RegTransmitSetting.field.BW; | ||
931 | SetHT.STBC = (u8)pAd->CommonCfg.RegTransmitSetting.field.STBC; | ||
932 | SetHT.SHORTGI = (u8)pAd->CommonCfg.RegTransmitSetting.field.ShortGI; | ||
933 | |||
934 | RTMPSetHT(pAd, &SetHT); | ||
935 | |||
936 | return TRUE; | ||
937 | } | ||
938 | |||
939 | char *RTMPGetRalinkEncryModeStr(u16 encryMode) | ||
940 | { | ||
941 | switch (encryMode) { | ||
942 | case Ndis802_11WEPDisabled: | ||
943 | return "NONE"; | ||
944 | case Ndis802_11WEPEnabled: | ||
945 | return "WEP"; | ||
946 | case Ndis802_11Encryption2Enabled: | ||
947 | return "TKIP"; | ||
948 | case Ndis802_11Encryption3Enabled: | ||
949 | return "AES"; | ||
950 | case Ndis802_11Encryption4Enabled: | ||
951 | return "TKIPAES"; | ||
952 | default: | ||
953 | return "UNKNOW"; | ||
954 | } | ||
955 | } | ||
diff --git a/drivers/staging/rt2860/common/cmm_mac_pci.c b/drivers/staging/rt2860/common/cmm_mac_pci.c deleted file mode 100644 index d06f0a6dc37..00000000000 --- a/drivers/staging/rt2860/common/cmm_mac_pci.c +++ /dev/null | |||
@@ -1,1661 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | */ | ||
27 | |||
28 | #ifdef RTMP_MAC_PCI | ||
29 | #include "../rt_config.h" | ||
30 | |||
31 | /* | ||
32 | ======================================================================== | ||
33 | |||
34 | Routine Description: | ||
35 | Allocate DMA memory blocks for send, receive | ||
36 | |||
37 | Arguments: | ||
38 | Adapter Pointer to our adapter | ||
39 | |||
40 | Return Value: | ||
41 | NDIS_STATUS_SUCCESS | ||
42 | NDIS_STATUS_FAILURE | ||
43 | NDIS_STATUS_RESOURCES | ||
44 | |||
45 | IRQL = PASSIVE_LEVEL | ||
46 | |||
47 | Note: | ||
48 | |||
49 | ======================================================================== | ||
50 | */ | ||
51 | int RTMPAllocTxRxRingMemory(struct rt_rtmp_adapter *pAd) | ||
52 | { | ||
53 | int Status = NDIS_STATUS_SUCCESS; | ||
54 | unsigned long RingBasePaHigh; | ||
55 | unsigned long RingBasePaLow; | ||
56 | void *RingBaseVa; | ||
57 | int index, num; | ||
58 | struct rt_txd * pTxD; | ||
59 | struct rt_rxd * pRxD; | ||
60 | unsigned long ErrorValue = 0; | ||
61 | struct rt_rtmp_tx_ring *pTxRing; | ||
62 | struct rt_rtmp_dmabuf *pDmaBuf; | ||
63 | void *pPacket; | ||
64 | /* PRTMP_REORDERBUF pReorderBuf; */ | ||
65 | |||
66 | DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n")); | ||
67 | do { | ||
68 | /* */ | ||
69 | /* Allocate all ring descriptors, include TxD, RxD, MgmtD. */ | ||
70 | /* Although each size is different, to prevent cacheline and alignment */ | ||
71 | /* issue, I intentional set them all to 64 bytes. */ | ||
72 | /* */ | ||
73 | for (num = 0; num < NUM_OF_TX_RING; num++) { | ||
74 | unsigned long BufBasePaHigh; | ||
75 | unsigned long BufBasePaLow; | ||
76 | void *BufBaseVa; | ||
77 | |||
78 | /* */ | ||
79 | /* Allocate Tx ring descriptor's memory (5 TX rings = 4 ACs + 1 HCCA) */ | ||
80 | /* */ | ||
81 | pAd->TxDescRing[num].AllocSize = | ||
82 | TX_RING_SIZE * TXD_SIZE; | ||
83 | RTMP_AllocateTxDescMemory(pAd, num, | ||
84 | pAd->TxDescRing[num]. | ||
85 | AllocSize, FALSE, | ||
86 | &pAd->TxDescRing[num].AllocVa, | ||
87 | &pAd->TxDescRing[num]. | ||
88 | AllocPa); | ||
89 | |||
90 | if (pAd->TxDescRing[num].AllocVa == NULL) { | ||
91 | ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; | ||
92 | DBGPRINT_ERR("Failed to allocate a big buffer\n"); | ||
93 | Status = NDIS_STATUS_RESOURCES; | ||
94 | break; | ||
95 | } | ||
96 | /* Zero init this memory block */ | ||
97 | NdisZeroMemory(pAd->TxDescRing[num].AllocVa, | ||
98 | pAd->TxDescRing[num].AllocSize); | ||
99 | |||
100 | /* Save PA & VA for further operation */ | ||
101 | RingBasePaHigh = | ||
102 | RTMP_GetPhysicalAddressHigh(pAd->TxDescRing[num]. | ||
103 | AllocPa); | ||
104 | RingBasePaLow = | ||
105 | RTMP_GetPhysicalAddressLow(pAd->TxDescRing[num]. | ||
106 | AllocPa); | ||
107 | RingBaseVa = pAd->TxDescRing[num].AllocVa; | ||
108 | |||
109 | /* */ | ||
110 | /* Allocate all 1st TXBuf's memory for this TxRing */ | ||
111 | /* */ | ||
112 | pAd->TxBufSpace[num].AllocSize = | ||
113 | TX_RING_SIZE * TX_DMA_1ST_BUFFER_SIZE; | ||
114 | RTMP_AllocateFirstTxBuffer(pAd, num, | ||
115 | pAd->TxBufSpace[num]. | ||
116 | AllocSize, FALSE, | ||
117 | &pAd->TxBufSpace[num]. | ||
118 | AllocVa, | ||
119 | &pAd->TxBufSpace[num]. | ||
120 | AllocPa); | ||
121 | |||
122 | if (pAd->TxBufSpace[num].AllocVa == NULL) { | ||
123 | ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; | ||
124 | DBGPRINT_ERR("Failed to allocate a big buffer\n"); | ||
125 | Status = NDIS_STATUS_RESOURCES; | ||
126 | break; | ||
127 | } | ||
128 | /* Zero init this memory block */ | ||
129 | NdisZeroMemory(pAd->TxBufSpace[num].AllocVa, | ||
130 | pAd->TxBufSpace[num].AllocSize); | ||
131 | |||
132 | /* Save PA & VA for further operation */ | ||
133 | BufBasePaHigh = | ||
134 | RTMP_GetPhysicalAddressHigh(pAd->TxBufSpace[num]. | ||
135 | AllocPa); | ||
136 | BufBasePaLow = | ||
137 | RTMP_GetPhysicalAddressLow(pAd->TxBufSpace[num]. | ||
138 | AllocPa); | ||
139 | BufBaseVa = pAd->TxBufSpace[num].AllocVa; | ||
140 | |||
141 | /* */ | ||
142 | /* Initialize Tx Ring Descriptor and associated buffer memory */ | ||
143 | /* */ | ||
144 | pTxRing = &pAd->TxRing[num]; | ||
145 | for (index = 0; index < TX_RING_SIZE; index++) { | ||
146 | pTxRing->Cell[index].pNdisPacket = NULL; | ||
147 | pTxRing->Cell[index].pNextNdisPacket = NULL; | ||
148 | /* Init Tx Ring Size, Va, Pa variables */ | ||
149 | pTxRing->Cell[index].AllocSize = TXD_SIZE; | ||
150 | pTxRing->Cell[index].AllocVa = RingBaseVa; | ||
151 | RTMP_SetPhysicalAddressHigh(pTxRing-> | ||
152 | Cell[index].AllocPa, | ||
153 | RingBasePaHigh); | ||
154 | RTMP_SetPhysicalAddressLow(pTxRing->Cell[index]. | ||
155 | AllocPa, | ||
156 | RingBasePaLow); | ||
157 | |||
158 | /* Setup Tx Buffer size & address. only 802.11 header will store in this space */ | ||
159 | pDmaBuf = &pTxRing->Cell[index].DmaBuf; | ||
160 | pDmaBuf->AllocSize = TX_DMA_1ST_BUFFER_SIZE; | ||
161 | pDmaBuf->AllocVa = BufBaseVa; | ||
162 | RTMP_SetPhysicalAddressHigh(pDmaBuf->AllocPa, | ||
163 | BufBasePaHigh); | ||
164 | RTMP_SetPhysicalAddressLow(pDmaBuf->AllocPa, | ||
165 | BufBasePaLow); | ||
166 | |||
167 | /* link the pre-allocated TxBuf to TXD */ | ||
168 | pTxD = | ||
169 | (struct rt_txd *) pTxRing->Cell[index].AllocVa; | ||
170 | pTxD->SDPtr0 = BufBasePaLow; | ||
171 | /* advance to next ring descriptor address */ | ||
172 | pTxD->DMADONE = 1; | ||
173 | RingBasePaLow += TXD_SIZE; | ||
174 | RingBaseVa = (u8 *)RingBaseVa + TXD_SIZE; | ||
175 | |||
176 | /* advance to next TxBuf address */ | ||
177 | BufBasePaLow += TX_DMA_1ST_BUFFER_SIZE; | ||
178 | BufBaseVa = | ||
179 | (u8 *)BufBaseVa + TX_DMA_1ST_BUFFER_SIZE; | ||
180 | } | ||
181 | DBGPRINT(RT_DEBUG_TRACE, | ||
182 | ("TxRing[%d]: total %d entry allocated\n", num, | ||
183 | index)); | ||
184 | } | ||
185 | if (Status == NDIS_STATUS_RESOURCES) | ||
186 | break; | ||
187 | |||
188 | /* */ | ||
189 | /* Allocate MGMT ring descriptor's memory except Tx ring which allocated eariler */ | ||
190 | /* */ | ||
191 | pAd->MgmtDescRing.AllocSize = MGMT_RING_SIZE * TXD_SIZE; | ||
192 | RTMP_AllocateMgmtDescMemory(pAd, | ||
193 | pAd->MgmtDescRing.AllocSize, | ||
194 | FALSE, | ||
195 | &pAd->MgmtDescRing.AllocVa, | ||
196 | &pAd->MgmtDescRing.AllocPa); | ||
197 | |||
198 | if (pAd->MgmtDescRing.AllocVa == NULL) { | ||
199 | ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; | ||
200 | DBGPRINT_ERR("Failed to allocate a big buffer\n"); | ||
201 | Status = NDIS_STATUS_RESOURCES; | ||
202 | break; | ||
203 | } | ||
204 | /* Zero init this memory block */ | ||
205 | NdisZeroMemory(pAd->MgmtDescRing.AllocVa, | ||
206 | pAd->MgmtDescRing.AllocSize); | ||
207 | |||
208 | /* Save PA & VA for further operation */ | ||
209 | RingBasePaHigh = | ||
210 | RTMP_GetPhysicalAddressHigh(pAd->MgmtDescRing.AllocPa); | ||
211 | RingBasePaLow = | ||
212 | RTMP_GetPhysicalAddressLow(pAd->MgmtDescRing.AllocPa); | ||
213 | RingBaseVa = pAd->MgmtDescRing.AllocVa; | ||
214 | |||
215 | /* */ | ||
216 | /* Initialize MGMT Ring and associated buffer memory */ | ||
217 | /* */ | ||
218 | for (index = 0; index < MGMT_RING_SIZE; index++) { | ||
219 | pAd->MgmtRing.Cell[index].pNdisPacket = NULL; | ||
220 | pAd->MgmtRing.Cell[index].pNextNdisPacket = NULL; | ||
221 | /* Init MGMT Ring Size, Va, Pa variables */ | ||
222 | pAd->MgmtRing.Cell[index].AllocSize = TXD_SIZE; | ||
223 | pAd->MgmtRing.Cell[index].AllocVa = RingBaseVa; | ||
224 | RTMP_SetPhysicalAddressHigh(pAd->MgmtRing.Cell[index]. | ||
225 | AllocPa, RingBasePaHigh); | ||
226 | RTMP_SetPhysicalAddressLow(pAd->MgmtRing.Cell[index]. | ||
227 | AllocPa, RingBasePaLow); | ||
228 | |||
229 | /* Offset to next ring descriptor address */ | ||
230 | RingBasePaLow += TXD_SIZE; | ||
231 | RingBaseVa = (u8 *)RingBaseVa + TXD_SIZE; | ||
232 | |||
233 | /* link the pre-allocated TxBuf to TXD */ | ||
234 | pTxD = (struct rt_txd *) pAd->MgmtRing.Cell[index].AllocVa; | ||
235 | pTxD->DMADONE = 1; | ||
236 | |||
237 | /* no pre-allocated buffer required in MgmtRing for scatter-gather case */ | ||
238 | } | ||
239 | DBGPRINT(RT_DEBUG_TRACE, | ||
240 | ("MGMT Ring: total %d entry allocated\n", index)); | ||
241 | |||
242 | /* */ | ||
243 | /* Allocate RX ring descriptor's memory except Tx ring which allocated eariler */ | ||
244 | /* */ | ||
245 | pAd->RxDescRing.AllocSize = RX_RING_SIZE * RXD_SIZE; | ||
246 | RTMP_AllocateRxDescMemory(pAd, | ||
247 | pAd->RxDescRing.AllocSize, | ||
248 | FALSE, | ||
249 | &pAd->RxDescRing.AllocVa, | ||
250 | &pAd->RxDescRing.AllocPa); | ||
251 | |||
252 | if (pAd->RxDescRing.AllocVa == NULL) { | ||
253 | ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; | ||
254 | DBGPRINT_ERR("Failed to allocate a big buffer\n"); | ||
255 | Status = NDIS_STATUS_RESOURCES; | ||
256 | break; | ||
257 | } | ||
258 | /* Zero init this memory block */ | ||
259 | NdisZeroMemory(pAd->RxDescRing.AllocVa, | ||
260 | pAd->RxDescRing.AllocSize); | ||
261 | |||
262 | DBGPRINT(RT_DEBUG_OFF, | ||
263 | ("RX DESC %p size = %ld\n", pAd->RxDescRing.AllocVa, | ||
264 | pAd->RxDescRing.AllocSize)); | ||
265 | |||
266 | /* Save PA & VA for further operation */ | ||
267 | RingBasePaHigh = | ||
268 | RTMP_GetPhysicalAddressHigh(pAd->RxDescRing.AllocPa); | ||
269 | RingBasePaLow = | ||
270 | RTMP_GetPhysicalAddressLow(pAd->RxDescRing.AllocPa); | ||
271 | RingBaseVa = pAd->RxDescRing.AllocVa; | ||
272 | |||
273 | /* */ | ||
274 | /* Initialize Rx Ring and associated buffer memory */ | ||
275 | /* */ | ||
276 | for (index = 0; index < RX_RING_SIZE; index++) { | ||
277 | /* Init RX Ring Size, Va, Pa variables */ | ||
278 | pAd->RxRing.Cell[index].AllocSize = RXD_SIZE; | ||
279 | pAd->RxRing.Cell[index].AllocVa = RingBaseVa; | ||
280 | RTMP_SetPhysicalAddressHigh(pAd->RxRing.Cell[index]. | ||
281 | AllocPa, RingBasePaHigh); | ||
282 | RTMP_SetPhysicalAddressLow(pAd->RxRing.Cell[index]. | ||
283 | AllocPa, RingBasePaLow); | ||
284 | |||
285 | /*NdisZeroMemory(RingBaseVa, RXD_SIZE); */ | ||
286 | |||
287 | /* Offset to next ring descriptor address */ | ||
288 | RingBasePaLow += RXD_SIZE; | ||
289 | RingBaseVa = (u8 *)RingBaseVa + RXD_SIZE; | ||
290 | |||
291 | /* Setup Rx associated Buffer size & allocate share memory */ | ||
292 | pDmaBuf = &pAd->RxRing.Cell[index].DmaBuf; | ||
293 | pDmaBuf->AllocSize = RX_BUFFER_AGGRESIZE; | ||
294 | pPacket = RTMP_AllocateRxPacketBuffer(pAd, | ||
295 | pDmaBuf-> | ||
296 | AllocSize, FALSE, | ||
297 | &pDmaBuf->AllocVa, | ||
298 | &pDmaBuf-> | ||
299 | AllocPa); | ||
300 | |||
301 | /* keep allocated rx packet */ | ||
302 | pAd->RxRing.Cell[index].pNdisPacket = pPacket; | ||
303 | |||
304 | /* Error handling */ | ||
305 | if (pDmaBuf->AllocVa == NULL) { | ||
306 | ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; | ||
307 | DBGPRINT_ERR("Failed to allocate RxRing's 1st buffer\n"); | ||
308 | Status = NDIS_STATUS_RESOURCES; | ||
309 | break; | ||
310 | } | ||
311 | /* Zero init this memory block */ | ||
312 | NdisZeroMemory(pDmaBuf->AllocVa, pDmaBuf->AllocSize); | ||
313 | |||
314 | /* Write RxD buffer address & allocated buffer length */ | ||
315 | pRxD = (struct rt_rxd *) pAd->RxRing.Cell[index].AllocVa; | ||
316 | pRxD->SDP0 = | ||
317 | RTMP_GetPhysicalAddressLow(pDmaBuf->AllocPa); | ||
318 | pRxD->DDONE = 0; | ||
319 | |||
320 | } | ||
321 | |||
322 | DBGPRINT(RT_DEBUG_TRACE, | ||
323 | ("Rx Ring: total %d entry allocated\n", index)); | ||
324 | |||
325 | } while (FALSE); | ||
326 | |||
327 | NdisZeroMemory(&pAd->FragFrame, sizeof(struct rt_fragment_frame)); | ||
328 | pAd->FragFrame.pFragPacket = | ||
329 | RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); | ||
330 | |||
331 | if (pAd->FragFrame.pFragPacket == NULL) { | ||
332 | Status = NDIS_STATUS_RESOURCES; | ||
333 | } | ||
334 | |||
335 | if (Status != NDIS_STATUS_SUCCESS) { | ||
336 | /* Log error inforamtion */ | ||
337 | NdisWriteErrorLogEntry(pAd->AdapterHandle, | ||
338 | NDIS_ERROR_CODE_OUT_OF_RESOURCES, | ||
339 | 1, ErrorValue); | ||
340 | } | ||
341 | /* Following code segment get from original func:NICInitTxRxRingAndBacklogQueue(), now should integrate it to here. */ | ||
342 | { | ||
343 | DBGPRINT(RT_DEBUG_TRACE, | ||
344 | ("--> NICInitTxRxRingAndBacklogQueue\n")); | ||
345 | |||
346 | /* | ||
347 | // Disable DMA. | ||
348 | RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); | ||
349 | GloCfg.word &= 0xff0; | ||
350 | GloCfg.field.EnTXWriteBackDDONE =1; | ||
351 | RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); | ||
352 | */ | ||
353 | |||
354 | /* Initialize all transmit related software queues */ | ||
355 | for (index = 0; index < NUM_OF_TX_RING; index++) { | ||
356 | InitializeQueueHeader(&pAd->TxSwQueue[index]); | ||
357 | /* Init TX rings index pointer */ | ||
358 | pAd->TxRing[index].TxSwFreeIdx = 0; | ||
359 | pAd->TxRing[index].TxCpuIdx = 0; | ||
360 | /*RTMP_IO_WRITE32(pAd, (TX_CTX_IDX0 + i * 0x10) , pAd->TxRing[i].TX_CTX_IDX); */ | ||
361 | } | ||
362 | |||
363 | /* Init RX Ring index pointer */ | ||
364 | pAd->RxRing.RxSwReadIdx = 0; | ||
365 | pAd->RxRing.RxCpuIdx = RX_RING_SIZE - 1; | ||
366 | /*RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RX_CRX_IDX0); */ | ||
367 | |||
368 | /* init MGMT ring index pointer */ | ||
369 | pAd->MgmtRing.TxSwFreeIdx = 0; | ||
370 | pAd->MgmtRing.TxCpuIdx = 0; | ||
371 | |||
372 | pAd->PrivateInfo.TxRingFullCnt = 0; | ||
373 | |||
374 | DBGPRINT(RT_DEBUG_TRACE, | ||
375 | ("<-- NICInitTxRxRingAndBacklogQueue\n")); | ||
376 | } | ||
377 | |||
378 | DBGPRINT_S(Status, | ||
379 | ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status)); | ||
380 | return Status; | ||
381 | } | ||
382 | |||
383 | /* | ||
384 | ======================================================================== | ||
385 | |||
386 | Routine Description: | ||
387 | Reset NIC Asics. Call after rest DMA. So reset TX_CTX_IDX to zero. | ||
388 | |||
389 | Arguments: | ||
390 | Adapter Pointer to our adapter | ||
391 | |||
392 | Return Value: | ||
393 | None | ||
394 | |||
395 | IRQL = PASSIVE_LEVEL | ||
396 | IRQL = DISPATCH_LEVEL | ||
397 | |||
398 | Note: | ||
399 | Reset NIC to initial state AS IS system boot up time. | ||
400 | |||
401 | ======================================================================== | ||
402 | */ | ||
403 | void RTMPRingCleanUp(struct rt_rtmp_adapter *pAd, u8 RingType) | ||
404 | { | ||
405 | struct rt_txd * pTxD; | ||
406 | struct rt_rxd * pRxD; | ||
407 | struct rt_queue_entry *pEntry; | ||
408 | void *pPacket; | ||
409 | int i; | ||
410 | struct rt_rtmp_tx_ring *pTxRing; | ||
411 | unsigned long IrqFlags; | ||
412 | /*u32 RxSwReadIdx; */ | ||
413 | |||
414 | DBGPRINT(RT_DEBUG_TRACE, | ||
415 | ("RTMPRingCleanUp(RingIdx=%d, Pending-NDIS=%ld)\n", RingType, | ||
416 | pAd->RalinkCounters.PendingNdisPacketCount)); | ||
417 | switch (RingType) { | ||
418 | case QID_AC_BK: | ||
419 | case QID_AC_BE: | ||
420 | case QID_AC_VI: | ||
421 | case QID_AC_VO: | ||
422 | |||
423 | pTxRing = &pAd->TxRing[RingType]; | ||
424 | |||
425 | RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); | ||
426 | /* We have to clean all descriptors in case some error happened with reset */ | ||
427 | for (i = 0; i < TX_RING_SIZE; i++) /* We have to scan all TX ring */ | ||
428 | { | ||
429 | pTxD = (struct rt_txd *) pTxRing->Cell[i].AllocVa; | ||
430 | |||
431 | pPacket = (void *)pTxRing->Cell[i].pNdisPacket; | ||
432 | /* release scatter-and-gather char */ | ||
433 | if (pPacket) { | ||
434 | RELEASE_NDIS_PACKET(pAd, pPacket, | ||
435 | NDIS_STATUS_FAILURE); | ||
436 | pTxRing->Cell[i].pNdisPacket = NULL; | ||
437 | } | ||
438 | |||
439 | pPacket = | ||
440 | (void *)pTxRing->Cell[i].pNextNdisPacket; | ||
441 | /* release scatter-and-gather char */ | ||
442 | if (pPacket) { | ||
443 | RELEASE_NDIS_PACKET(pAd, pPacket, | ||
444 | NDIS_STATUS_FAILURE); | ||
445 | pTxRing->Cell[i].pNextNdisPacket = NULL; | ||
446 | } | ||
447 | } | ||
448 | |||
449 | RTMP_IO_READ32(pAd, TX_DTX_IDX0 + RingType * 0x10, | ||
450 | &pTxRing->TxDmaIdx); | ||
451 | pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx; | ||
452 | pTxRing->TxCpuIdx = pTxRing->TxDmaIdx; | ||
453 | RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + RingType * 0x10, | ||
454 | pTxRing->TxCpuIdx); | ||
455 | |||
456 | RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); | ||
457 | |||
458 | RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); | ||
459 | while (pAd->TxSwQueue[RingType].Head != NULL) { | ||
460 | pEntry = RemoveHeadQueue(&pAd->TxSwQueue[RingType]); | ||
461 | pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); | ||
462 | RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); | ||
463 | DBGPRINT(RT_DEBUG_TRACE, | ||
464 | ("Release 1 NDIS packet from s/w backlog queue\n")); | ||
465 | } | ||
466 | RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); | ||
467 | break; | ||
468 | |||
469 | case QID_MGMT: | ||
470 | /* We have to clean all descriptors in case some error happened with reset */ | ||
471 | NdisAcquireSpinLock(&pAd->MgmtRingLock); | ||
472 | |||
473 | for (i = 0; i < MGMT_RING_SIZE; i++) { | ||
474 | pTxD = (struct rt_txd *) pAd->MgmtRing.Cell[i].AllocVa; | ||
475 | |||
476 | pPacket = | ||
477 | (void *)pAd->MgmtRing.Cell[i].pNdisPacket; | ||
478 | /* rlease scatter-and-gather char */ | ||
479 | if (pPacket) { | ||
480 | PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, | ||
481 | pTxD->SDLen0, | ||
482 | PCI_DMA_TODEVICE); | ||
483 | RELEASE_NDIS_PACKET(pAd, pPacket, | ||
484 | NDIS_STATUS_FAILURE); | ||
485 | } | ||
486 | pAd->MgmtRing.Cell[i].pNdisPacket = NULL; | ||
487 | |||
488 | pPacket = | ||
489 | (void *)pAd->MgmtRing.Cell[i]. | ||
490 | pNextNdisPacket; | ||
491 | /* release scatter-and-gather char */ | ||
492 | if (pPacket) { | ||
493 | PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, | ||
494 | pTxD->SDLen1, | ||
495 | PCI_DMA_TODEVICE); | ||
496 | RELEASE_NDIS_PACKET(pAd, pPacket, | ||
497 | NDIS_STATUS_FAILURE); | ||
498 | } | ||
499 | pAd->MgmtRing.Cell[i].pNextNdisPacket = NULL; | ||
500 | |||
501 | } | ||
502 | |||
503 | RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pAd->MgmtRing.TxDmaIdx); | ||
504 | pAd->MgmtRing.TxSwFreeIdx = pAd->MgmtRing.TxDmaIdx; | ||
505 | pAd->MgmtRing.TxCpuIdx = pAd->MgmtRing.TxDmaIdx; | ||
506 | RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx); | ||
507 | |||
508 | NdisReleaseSpinLock(&pAd->MgmtRingLock); | ||
509 | pAd->RalinkCounters.MgmtRingFullCount = 0; | ||
510 | break; | ||
511 | |||
512 | case QID_RX: | ||
513 | /* We have to clean all descriptors in case some error happened with reset */ | ||
514 | NdisAcquireSpinLock(&pAd->RxRingLock); | ||
515 | |||
516 | for (i = 0; i < RX_RING_SIZE; i++) { | ||
517 | pRxD = (struct rt_rxd *) pAd->RxRing.Cell[i].AllocVa; | ||
518 | pRxD->DDONE = 0; | ||
519 | } | ||
520 | |||
521 | RTMP_IO_READ32(pAd, RX_DRX_IDX, &pAd->RxRing.RxDmaIdx); | ||
522 | pAd->RxRing.RxSwReadIdx = pAd->RxRing.RxDmaIdx; | ||
523 | pAd->RxRing.RxCpuIdx = | ||
524 | ((pAd->RxRing.RxDmaIdx == | ||
525 | 0) ? (RX_RING_SIZE - 1) : (pAd->RxRing.RxDmaIdx - 1)); | ||
526 | RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); | ||
527 | |||
528 | NdisReleaseSpinLock(&pAd->RxRingLock); | ||
529 | break; | ||
530 | |||
531 | default: | ||
532 | break; | ||
533 | } | ||
534 | } | ||
535 | |||
536 | void RTMPFreeTxRxRingMemory(struct rt_rtmp_adapter *pAd) | ||
537 | { | ||
538 | int index, num, j; | ||
539 | struct rt_rtmp_tx_ring *pTxRing; | ||
540 | struct rt_txd * pTxD; | ||
541 | void *pPacket; | ||
542 | unsigned int IrqFlags; | ||
543 | |||
544 | /*struct os_cookie *pObj =(struct os_cookie *)pAd->OS_Cookie; */ | ||
545 | |||
546 | DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPFreeTxRxRingMemory\n")); | ||
547 | |||
548 | /* Free TxSwQueue Packet */ | ||
549 | for (index = 0; index < NUM_OF_TX_RING; index++) { | ||
550 | struct rt_queue_entry *pEntry; | ||
551 | void *pPacket; | ||
552 | struct rt_queue_header *pQueue; | ||
553 | |||
554 | RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); | ||
555 | pQueue = &pAd->TxSwQueue[index]; | ||
556 | while (pQueue->Head) { | ||
557 | pEntry = RemoveHeadQueue(pQueue); | ||
558 | pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); | ||
559 | RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); | ||
560 | } | ||
561 | RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); | ||
562 | } | ||
563 | |||
564 | /* Free Tx Ring Packet */ | ||
565 | for (index = 0; index < NUM_OF_TX_RING; index++) { | ||
566 | pTxRing = &pAd->TxRing[index]; | ||
567 | |||
568 | for (j = 0; j < TX_RING_SIZE; j++) { | ||
569 | pTxD = (struct rt_txd *) (pTxRing->Cell[j].AllocVa); | ||
570 | pPacket = pTxRing->Cell[j].pNdisPacket; | ||
571 | |||
572 | if (pPacket) { | ||
573 | PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, | ||
574 | pTxD->SDLen0, | ||
575 | PCI_DMA_TODEVICE); | ||
576 | RELEASE_NDIS_PACKET(pAd, pPacket, | ||
577 | NDIS_STATUS_SUCCESS); | ||
578 | } | ||
579 | /*Always assign pNdisPacket as NULL after clear */ | ||
580 | pTxRing->Cell[j].pNdisPacket = NULL; | ||
581 | |||
582 | pPacket = pTxRing->Cell[j].pNextNdisPacket; | ||
583 | |||
584 | if (pPacket) { | ||
585 | PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, | ||
586 | pTxD->SDLen1, | ||
587 | PCI_DMA_TODEVICE); | ||
588 | RELEASE_NDIS_PACKET(pAd, pPacket, | ||
589 | NDIS_STATUS_SUCCESS); | ||
590 | } | ||
591 | /*Always assign pNextNdisPacket as NULL after clear */ | ||
592 | pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = | ||
593 | NULL; | ||
594 | |||
595 | } | ||
596 | } | ||
597 | |||
598 | for (index = RX_RING_SIZE - 1; index >= 0; index--) { | ||
599 | if ((pAd->RxRing.Cell[index].DmaBuf.AllocVa) | ||
600 | && (pAd->RxRing.Cell[index].pNdisPacket)) { | ||
601 | PCI_UNMAP_SINGLE(pAd, | ||
602 | pAd->RxRing.Cell[index].DmaBuf.AllocPa, | ||
603 | pAd->RxRing.Cell[index].DmaBuf. | ||
604 | AllocSize, PCI_DMA_FROMDEVICE); | ||
605 | RELEASE_NDIS_PACKET(pAd, | ||
606 | pAd->RxRing.Cell[index].pNdisPacket, | ||
607 | NDIS_STATUS_SUCCESS); | ||
608 | } | ||
609 | } | ||
610 | NdisZeroMemory(pAd->RxRing.Cell, RX_RING_SIZE * sizeof(struct rt_rtmp_dmacb)); | ||
611 | |||
612 | if (pAd->RxDescRing.AllocVa) { | ||
613 | RTMP_FreeDescMemory(pAd, pAd->RxDescRing.AllocSize, | ||
614 | pAd->RxDescRing.AllocVa, | ||
615 | pAd->RxDescRing.AllocPa); | ||
616 | } | ||
617 | NdisZeroMemory(&pAd->RxDescRing, sizeof(struct rt_rtmp_dmabuf)); | ||
618 | |||
619 | if (pAd->MgmtDescRing.AllocVa) { | ||
620 | RTMP_FreeDescMemory(pAd, pAd->MgmtDescRing.AllocSize, | ||
621 | pAd->MgmtDescRing.AllocVa, | ||
622 | pAd->MgmtDescRing.AllocPa); | ||
623 | } | ||
624 | NdisZeroMemory(&pAd->MgmtDescRing, sizeof(struct rt_rtmp_dmabuf)); | ||
625 | |||
626 | for (num = 0; num < NUM_OF_TX_RING; num++) { | ||
627 | if (pAd->TxBufSpace[num].AllocVa) { | ||
628 | RTMP_FreeFirstTxBuffer(pAd, | ||
629 | pAd->TxBufSpace[num].AllocSize, | ||
630 | FALSE, | ||
631 | pAd->TxBufSpace[num].AllocVa, | ||
632 | pAd->TxBufSpace[num].AllocPa); | ||
633 | } | ||
634 | NdisZeroMemory(&pAd->TxBufSpace[num], sizeof(struct rt_rtmp_dmabuf)); | ||
635 | |||
636 | if (pAd->TxDescRing[num].AllocVa) { | ||
637 | RTMP_FreeDescMemory(pAd, pAd->TxDescRing[num].AllocSize, | ||
638 | pAd->TxDescRing[num].AllocVa, | ||
639 | pAd->TxDescRing[num].AllocPa); | ||
640 | } | ||
641 | NdisZeroMemory(&pAd->TxDescRing[num], sizeof(struct rt_rtmp_dmabuf)); | ||
642 | } | ||
643 | |||
644 | if (pAd->FragFrame.pFragPacket) | ||
645 | RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, | ||
646 | NDIS_STATUS_SUCCESS); | ||
647 | |||
648 | DBGPRINT(RT_DEBUG_TRACE, ("<-- RTMPFreeTxRxRingMemory\n")); | ||
649 | } | ||
650 | |||
651 | /*************************************************************************** | ||
652 | * | ||
653 | * register related procedures. | ||
654 | * | ||
655 | **************************************************************************/ | ||
656 | /* | ||
657 | ======================================================================== | ||
658 | Routine Description: | ||
659 | Disable DMA. | ||
660 | |||
661 | Arguments: | ||
662 | *pAd the raxx interface data pointer | ||
663 | |||
664 | Return Value: | ||
665 | None | ||
666 | |||
667 | Note: | ||
668 | ======================================================================== | ||
669 | */ | ||
670 | void RT28XXDMADisable(struct rt_rtmp_adapter *pAd) | ||
671 | { | ||
672 | WPDMA_GLO_CFG_STRUC GloCfg; | ||
673 | |||
674 | RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); | ||
675 | GloCfg.word &= 0xff0; | ||
676 | GloCfg.field.EnTXWriteBackDDONE = 1; | ||
677 | RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); | ||
678 | } | ||
679 | |||
680 | /* | ||
681 | ======================================================================== | ||
682 | Routine Description: | ||
683 | Enable DMA. | ||
684 | |||
685 | Arguments: | ||
686 | *pAd the raxx interface data pointer | ||
687 | |||
688 | Return Value: | ||
689 | None | ||
690 | |||
691 | Note: | ||
692 | ======================================================================== | ||
693 | */ | ||
694 | void RT28XXDMAEnable(struct rt_rtmp_adapter *pAd) | ||
695 | { | ||
696 | WPDMA_GLO_CFG_STRUC GloCfg; | ||
697 | int i = 0; | ||
698 | |||
699 | RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4); | ||
700 | do { | ||
701 | RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); | ||
702 | if ((GloCfg.field.TxDMABusy == 0) | ||
703 | && (GloCfg.field.RxDMABusy == 0)) | ||
704 | break; | ||
705 | |||
706 | DBGPRINT(RT_DEBUG_TRACE, ("==> DMABusy\n")); | ||
707 | RTMPusecDelay(1000); | ||
708 | i++; | ||
709 | } while (i < 200); | ||
710 | |||
711 | RTMPusecDelay(50); | ||
712 | |||
713 | GloCfg.field.EnTXWriteBackDDONE = 1; | ||
714 | GloCfg.field.WPDMABurstSIZE = 2; | ||
715 | GloCfg.field.EnableRxDMA = 1; | ||
716 | GloCfg.field.EnableTxDMA = 1; | ||
717 | |||
718 | DBGPRINT(RT_DEBUG_TRACE, | ||
719 | ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word)); | ||
720 | RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); | ||
721 | |||
722 | } | ||
723 | |||
724 | BOOLEAN AsicCheckCommanOk(struct rt_rtmp_adapter *pAd, u8 Command) | ||
725 | { | ||
726 | u32 CmdStatus = 0, CID = 0, i; | ||
727 | u32 ThisCIDMask = 0; | ||
728 | |||
729 | i = 0; | ||
730 | do { | ||
731 | RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID); | ||
732 | /* Find where the command is. Because this is randomly specified by firmware. */ | ||
733 | if ((CID & CID0MASK) == Command) { | ||
734 | ThisCIDMask = CID0MASK; | ||
735 | break; | ||
736 | } else if ((((CID & CID1MASK) >> 8) & 0xff) == Command) { | ||
737 | ThisCIDMask = CID1MASK; | ||
738 | break; | ||
739 | } else if ((((CID & CID2MASK) >> 16) & 0xff) == Command) { | ||
740 | ThisCIDMask = CID2MASK; | ||
741 | break; | ||
742 | } else if ((((CID & CID3MASK) >> 24) & 0xff) == Command) { | ||
743 | ThisCIDMask = CID3MASK; | ||
744 | break; | ||
745 | } | ||
746 | |||
747 | RTMPusecDelay(100); | ||
748 | i++; | ||
749 | } while (i < 200); | ||
750 | |||
751 | /* Get CommandStatus Value */ | ||
752 | RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus); | ||
753 | |||
754 | /* This command's status is at the same position as command. So AND command position's bitmask to read status. */ | ||
755 | if (i < 200) { | ||
756 | /* If Status is 1, the command is success. */ | ||
757 | if (((CmdStatus & ThisCIDMask) == 0x1) | ||
758 | || ((CmdStatus & ThisCIDMask) == 0x100) | ||
759 | || ((CmdStatus & ThisCIDMask) == 0x10000) | ||
760 | || ((CmdStatus & ThisCIDMask) == 0x1000000)) { | ||
761 | DBGPRINT(RT_DEBUG_TRACE, | ||
762 | ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", | ||
763 | CID, CmdStatus)); | ||
764 | RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff); | ||
765 | RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff); | ||
766 | return TRUE; | ||
767 | } | ||
768 | DBGPRINT(RT_DEBUG_TRACE, | ||
769 | ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", | ||
770 | CID, CmdStatus)); | ||
771 | } else { | ||
772 | DBGPRINT(RT_DEBUG_TRACE, | ||
773 | ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", | ||
774 | Command, CmdStatus)); | ||
775 | } | ||
776 | /* Clear Command and Status. */ | ||
777 | RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff); | ||
778 | RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff); | ||
779 | |||
780 | return FALSE; | ||
781 | } | ||
782 | |||
783 | /* | ||
784 | ======================================================================== | ||
785 | Routine Description: | ||
786 | Write Beacon buffer to Asic. | ||
787 | |||
788 | Arguments: | ||
789 | *pAd the raxx interface data pointer | ||
790 | |||
791 | Return Value: | ||
792 | None | ||
793 | |||
794 | Note: | ||
795 | ======================================================================== | ||
796 | */ | ||
797 | void RT28xx_UpdateBeaconToAsic(struct rt_rtmp_adapter *pAd, | ||
798 | int apidx, | ||
799 | unsigned long FrameLen, unsigned long UpdatePos) | ||
800 | { | ||
801 | unsigned long CapInfoPos = 0; | ||
802 | u8 *ptr, *ptr_update, *ptr_capinfo; | ||
803 | u32 i; | ||
804 | BOOLEAN bBcnReq = FALSE; | ||
805 | u8 bcn_idx = 0; | ||
806 | |||
807 | { | ||
808 | DBGPRINT(RT_DEBUG_ERROR, | ||
809 | ("%s() : No valid Interface be found.\n", __func__)); | ||
810 | return; | ||
811 | } | ||
812 | |||
813 | /*if ((pAd->WdsTab.Mode == WDS_BRIDGE_MODE) */ | ||
814 | /* || ((pAd->ApCfg.MBSSID[apidx].MSSIDDev == NULL) */ | ||
815 | /* || !(pAd->ApCfg.MBSSID[apidx].MSSIDDev->flags & IFF_UP)) */ | ||
816 | /* ) */ | ||
817 | if (bBcnReq == FALSE) { | ||
818 | /* when the ra interface is down, do not send its beacon frame */ | ||
819 | /* clear all zero */ | ||
820 | for (i = 0; i < TXWI_SIZE; i += 4) | ||
821 | RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, | ||
822 | 0x00); | ||
823 | } else { | ||
824 | ptr = (u8 *)& pAd->BeaconTxWI; | ||
825 | for (i = 0; i < TXWI_SIZE; i += 4) /* 16-byte TXWI field */ | ||
826 | { | ||
827 | u32 longptr = | ||
828 | *ptr + (*(ptr + 1) << 8) + (*(ptr + 2) << 16) + | ||
829 | (*(ptr + 3) << 24); | ||
830 | RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, | ||
831 | longptr); | ||
832 | ptr += 4; | ||
833 | } | ||
834 | |||
835 | /* Update CapabilityInfo in Beacon */ | ||
836 | for (i = CapInfoPos; i < (CapInfoPos + 2); i++) { | ||
837 | RTMP_IO_WRITE8(pAd, | ||
838 | pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + | ||
839 | i, *ptr_capinfo); | ||
840 | ptr_capinfo++; | ||
841 | } | ||
842 | |||
843 | if (FrameLen > UpdatePos) { | ||
844 | for (i = UpdatePos; i < (FrameLen); i++) { | ||
845 | RTMP_IO_WRITE8(pAd, | ||
846 | pAd->BeaconOffset[bcn_idx] + | ||
847 | TXWI_SIZE + i, *ptr_update); | ||
848 | ptr_update++; | ||
849 | } | ||
850 | } | ||
851 | |||
852 | } | ||
853 | |||
854 | } | ||
855 | |||
856 | void RT28xxPciStaAsicForceWakeup(struct rt_rtmp_adapter *pAd, IN BOOLEAN bFromTx) | ||
857 | { | ||
858 | AUTO_WAKEUP_STRUC AutoWakeupCfg; | ||
859 | |||
860 | if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) | ||
861 | return; | ||
862 | |||
863 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW)) { | ||
864 | DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n")); | ||
865 | return; | ||
866 | } | ||
867 | |||
868 | OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WAKEUP_NOW); | ||
869 | |||
870 | RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW); | ||
871 | |||
872 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) | ||
873 | && pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) { | ||
874 | /* Support PCIe Advance Power Save */ | ||
875 | if (bFromTx == TRUE && (pAd->Mlme.bPsPollTimerRunning == TRUE)) { | ||
876 | pAd->Mlme.bPsPollTimerRunning = FALSE; | ||
877 | RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); | ||
878 | RTMPusecDelay(3000); | ||
879 | DBGPRINT(RT_DEBUG_TRACE, | ||
880 | ("=======AsicForceWakeup===bFromTx\n")); | ||
881 | } | ||
882 | |||
883 | AutoWakeupCfg.word = 0; | ||
884 | RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); | ||
885 | |||
886 | if (RT28xxPciAsicRadioOn(pAd, DOT11POWERSAVE)) { | ||
887 | #ifdef PCIE_PS_SUPPORT | ||
888 | /* add by johnli, RF power sequence setup, load RF normal operation-mode setup */ | ||
889 | if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) | ||
890 | && IS_VERSION_AFTER_F(pAd)) { | ||
891 | struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps; | ||
892 | |||
893 | if (pChipOps->AsicReverseRfFromSleepMode) | ||
894 | pChipOps-> | ||
895 | AsicReverseRfFromSleepMode(pAd); | ||
896 | } else | ||
897 | #endif /* PCIE_PS_SUPPORT // */ | ||
898 | { | ||
899 | /* end johnli */ | ||
900 | /* In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. */ | ||
901 | if (INFRA_ON(pAd) | ||
902 | && (pAd->CommonCfg.CentralChannel != | ||
903 | pAd->CommonCfg.Channel) | ||
904 | && (pAd->MlmeAux.HtCapability.HtCapInfo. | ||
905 | ChannelWidth == BW_40)) { | ||
906 | /* Must using 40MHz. */ | ||
907 | AsicSwitchChannel(pAd, | ||
908 | pAd->CommonCfg. | ||
909 | CentralChannel, | ||
910 | FALSE); | ||
911 | AsicLockChannel(pAd, | ||
912 | pAd->CommonCfg. | ||
913 | CentralChannel); | ||
914 | } else { | ||
915 | /* Must using 20MHz. */ | ||
916 | AsicSwitchChannel(pAd, | ||
917 | pAd->CommonCfg. | ||
918 | Channel, FALSE); | ||
919 | AsicLockChannel(pAd, | ||
920 | pAd->CommonCfg.Channel); | ||
921 | } | ||
922 | } | ||
923 | } | ||
924 | #ifdef PCIE_PS_SUPPORT | ||
925 | /* 3090 MCU Wakeup command needs more time to be stable. */ | ||
926 | /* Before stable, don't issue other MCU command to prevent from firmware error. */ | ||
927 | if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) | ||
928 | && IS_VERSION_AFTER_F(pAd)) && IS_VERSION_AFTER_F(pAd) | ||
929 | && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) | ||
930 | && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) { | ||
931 | DBGPRINT(RT_DEBUG_TRACE, | ||
932 | ("<==RT28xxPciStaAsicForceWakeup::Release the MCU Lock(3090)\n")); | ||
933 | RTMP_SEM_LOCK(&pAd->McuCmdLock); | ||
934 | pAd->brt30xxBanMcuCmd = FALSE; | ||
935 | RTMP_SEM_UNLOCK(&pAd->McuCmdLock); | ||
936 | } | ||
937 | #endif /* PCIE_PS_SUPPORT // */ | ||
938 | } else { | ||
939 | /* PCI, 2860-PCIe */ | ||
940 | DBGPRINT(RT_DEBUG_TRACE, | ||
941 | ("<==RT28xxPciStaAsicForceWakeup::Original PCI Power Saving\n")); | ||
942 | AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02); | ||
943 | AutoWakeupCfg.word = 0; | ||
944 | RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); | ||
945 | } | ||
946 | |||
947 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); | ||
948 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WAKEUP_NOW); | ||
949 | DBGPRINT(RT_DEBUG_TRACE, ("<=======RT28xxPciStaAsicForceWakeup\n")); | ||
950 | } | ||
951 | |||
952 | void RT28xxPciStaAsicSleepThenAutoWakeup(struct rt_rtmp_adapter *pAd, | ||
953 | u16 TbttNumToNextWakeUp) | ||
954 | { | ||
955 | BOOLEAN brc; | ||
956 | |||
957 | if (pAd->StaCfg.bRadio == FALSE) { | ||
958 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); | ||
959 | return; | ||
960 | } | ||
961 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) | ||
962 | && pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) { | ||
963 | unsigned long Now = 0; | ||
964 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW)) { | ||
965 | DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n")); | ||
966 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); | ||
967 | return; | ||
968 | } | ||
969 | |||
970 | NdisGetSystemUpTime(&Now); | ||
971 | /* If last send NULL fram time is too close to this receiving beacon (within 8ms), don't go to sleep for this DTM. */ | ||
972 | /* Because Some AP can't queuing outgoing frames immediately. */ | ||
973 | if (((pAd->Mlme.LastSendNULLpsmTime + 8) >= Now) | ||
974 | && (pAd->Mlme.LastSendNULLpsmTime <= Now)) { | ||
975 | DBGPRINT(RT_DEBUG_TRACE, | ||
976 | ("Now = %lu, LastSendNULLpsmTime=%lu : RxCountSinceLastNULL = %lu. \n", | ||
977 | Now, pAd->Mlme.LastSendNULLpsmTime, | ||
978 | pAd->RalinkCounters.RxCountSinceLastNULL)); | ||
979 | return; | ||
980 | } else if ((pAd->RalinkCounters.RxCountSinceLastNULL > 0) | ||
981 | && | ||
982 | ((pAd->Mlme.LastSendNULLpsmTime + | ||
983 | pAd->CommonCfg.BeaconPeriod) >= Now)) { | ||
984 | DBGPRINT(RT_DEBUG_TRACE, | ||
985 | ("Now = %lu, LastSendNULLpsmTime=%lu: RxCountSinceLastNULL = %lu > 0 \n", | ||
986 | Now, pAd->Mlme.LastSendNULLpsmTime, | ||
987 | pAd->RalinkCounters.RxCountSinceLastNULL)); | ||
988 | return; | ||
989 | } | ||
990 | |||
991 | brc = | ||
992 | RT28xxPciAsicRadioOff(pAd, DOT11POWERSAVE, | ||
993 | TbttNumToNextWakeUp); | ||
994 | if (brc == TRUE) | ||
995 | OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE); | ||
996 | } else { | ||
997 | AUTO_WAKEUP_STRUC AutoWakeupCfg; | ||
998 | /* we have decided to SLEEP, so at least do it for a BEACON period. */ | ||
999 | if (TbttNumToNextWakeUp == 0) | ||
1000 | TbttNumToNextWakeUp = 1; | ||
1001 | |||
1002 | /*RTMP_IO_WRITE32(pAd, INT_MASK_CSR, AutoWakeupInt); */ | ||
1003 | |||
1004 | AutoWakeupCfg.word = 0; | ||
1005 | RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); | ||
1006 | AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1; | ||
1007 | AutoWakeupCfg.field.EnableAutoWakeup = 1; | ||
1008 | AutoWakeupCfg.field.AutoLeadTime = 5; | ||
1009 | RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); | ||
1010 | AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x00); /* send POWER-SAVE command to MCU. Timeout 40us. */ | ||
1011 | OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE); | ||
1012 | DBGPRINT(RT_DEBUG_TRACE, | ||
1013 | ("<-- %s, TbttNumToNextWakeUp=%d \n", __func__, | ||
1014 | TbttNumToNextWakeUp)); | ||
1015 | } | ||
1016 | |||
1017 | } | ||
1018 | |||
1019 | void PsPollWakeExec(void *SystemSpecific1, | ||
1020 | void *FunctionContext, | ||
1021 | void *SystemSpecific2, void *SystemSpecific3) | ||
1022 | { | ||
1023 | struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; | ||
1024 | unsigned long flags; | ||
1025 | |||
1026 | DBGPRINT(RT_DEBUG_TRACE, ("-->PsPollWakeExec \n")); | ||
1027 | RTMP_INT_LOCK(&pAd->irq_lock, flags); | ||
1028 | if (pAd->Mlme.bPsPollTimerRunning) { | ||
1029 | RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); | ||
1030 | } | ||
1031 | pAd->Mlme.bPsPollTimerRunning = FALSE; | ||
1032 | RTMP_INT_UNLOCK(&pAd->irq_lock, flags); | ||
1033 | #ifdef PCIE_PS_SUPPORT | ||
1034 | /* For rt30xx power solution 3, Use software timer to wake up in psm. So call */ | ||
1035 | /* AsicForceWakeup here instead of handling twakeup interrupt. */ | ||
1036 | if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) | ||
1037 | && IS_VERSION_AFTER_F(pAd)) | ||
1038 | && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) | ||
1039 | && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) { | ||
1040 | DBGPRINT(RT_DEBUG_TRACE, | ||
1041 | ("<--PsPollWakeExec::3090 calls AsicForceWakeup(pAd, DOT11POWERSAVE) in advance \n")); | ||
1042 | AsicForceWakeup(pAd, DOT11POWERSAVE); | ||
1043 | } | ||
1044 | #endif /* PCIE_PS_SUPPORT // */ | ||
1045 | } | ||
1046 | |||
1047 | void RadioOnExec(void *SystemSpecific1, | ||
1048 | void *FunctionContext, | ||
1049 | void *SystemSpecific2, void *SystemSpecific3) | ||
1050 | { | ||
1051 | struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; | ||
1052 | struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps; | ||
1053 | WPDMA_GLO_CFG_STRUC DmaCfg; | ||
1054 | BOOLEAN Cancelled; | ||
1055 | |||
1056 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) { | ||
1057 | DBGPRINT(RT_DEBUG_TRACE, | ||
1058 | ("-->RadioOnExec() return on fOP_STATUS_DOZE == TRUE; \n")); | ||
1059 | /*KH Debug: Add the compile flag "RT2860 and condition */ | ||
1060 | #ifdef RTMP_PCI_SUPPORT | ||
1061 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) | ||
1062 | && pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) | ||
1063 | RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10); | ||
1064 | #endif /* RTMP_PCI_SUPPORT // */ | ||
1065 | return; | ||
1066 | } | ||
1067 | |||
1068 | if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) { | ||
1069 | DBGPRINT(RT_DEBUG_TRACE, | ||
1070 | ("-->RadioOnExec() return on SCAN_IN_PROGRESS; \n")); | ||
1071 | #ifdef RTMP_PCI_SUPPORT | ||
1072 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) | ||
1073 | && pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) | ||
1074 | RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10); | ||
1075 | #endif /* RTMP_PCI_SUPPORT // */ | ||
1076 | return; | ||
1077 | } | ||
1078 | /*KH Debug: need to check. I add the compile flag "CONFIG_STA_SUPPORT" to enclose the following codes. */ | ||
1079 | #ifdef RTMP_PCI_SUPPORT | ||
1080 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) | ||
1081 | && pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) { | ||
1082 | pAd->Mlme.bPsPollTimerRunning = FALSE; | ||
1083 | RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); | ||
1084 | } | ||
1085 | #endif /* RTMP_PCI_SUPPORT // */ | ||
1086 | if (pAd->StaCfg.bRadio == TRUE) { | ||
1087 | pAd->bPCIclkOff = FALSE; | ||
1088 | RTMPRingCleanUp(pAd, QID_AC_BK); | ||
1089 | RTMPRingCleanUp(pAd, QID_AC_BE); | ||
1090 | RTMPRingCleanUp(pAd, QID_AC_VI); | ||
1091 | RTMPRingCleanUp(pAd, QID_AC_VO); | ||
1092 | RTMPRingCleanUp(pAd, QID_MGMT); | ||
1093 | RTMPRingCleanUp(pAd, QID_RX); | ||
1094 | |||
1095 | /* 2. Send wake up command. */ | ||
1096 | AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02); | ||
1097 | /* 2-1. wait command ok. */ | ||
1098 | AsicCheckCommanOk(pAd, PowerWakeCID); | ||
1099 | |||
1100 | /* When PCI clock is off, don't want to service interrupt. So when back to clock on, enable interrupt. */ | ||
1101 | /*RTMP_IO_WRITE32(pAd, INT_MASK_CSR, (DELAYINTMASK|RxINT)); */ | ||
1102 | RTMP_ASIC_INTERRUPT_ENABLE(pAd); | ||
1103 | |||
1104 | /* 3. Enable Tx DMA. */ | ||
1105 | RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word); | ||
1106 | DmaCfg.field.EnableTxDMA = 1; | ||
1107 | RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word); | ||
1108 | |||
1109 | /* In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. */ | ||
1110 | if (INFRA_ON(pAd) | ||
1111 | && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) | ||
1112 | && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == | ||
1113 | BW_40)) { | ||
1114 | /* Must using 40MHz. */ | ||
1115 | AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, | ||
1116 | FALSE); | ||
1117 | AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); | ||
1118 | } else { | ||
1119 | /* Must using 20MHz. */ | ||
1120 | AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); | ||
1121 | AsicLockChannel(pAd, pAd->CommonCfg.Channel); | ||
1122 | } | ||
1123 | |||
1124 | /*KH Debug:The following codes should be enclosed by RT3090 compile flag */ | ||
1125 | if (pChipOps->AsicReverseRfFromSleepMode) | ||
1126 | pChipOps->AsicReverseRfFromSleepMode(pAd); | ||
1127 | |||
1128 | #ifdef PCIE_PS_SUPPORT | ||
1129 | /* 3090 MCU Wakeup command needs more time to be stable. */ | ||
1130 | /* Before stable, don't issue other MCU command to prevent from firmware error. */ | ||
1131 | if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) | ||
1132 | && IS_VERSION_AFTER_F(pAd) | ||
1133 | && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) | ||
1134 | && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) { | ||
1135 | RTMP_SEM_LOCK(&pAd->McuCmdLock); | ||
1136 | pAd->brt30xxBanMcuCmd = FALSE; | ||
1137 | RTMP_SEM_UNLOCK(&pAd->McuCmdLock); | ||
1138 | } | ||
1139 | #endif /* PCIE_PS_SUPPORT // */ | ||
1140 | |||
1141 | /* Clear Radio off flag */ | ||
1142 | RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); | ||
1143 | |||
1144 | /* Set LED */ | ||
1145 | RTMPSetLED(pAd, LED_RADIO_ON); | ||
1146 | |||
1147 | if (pAd->StaCfg.Psm == PWR_ACTIVE) { | ||
1148 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, | ||
1149 | pAd->StaCfg.BBPR3); | ||
1150 | } | ||
1151 | } else { | ||
1152 | RT28xxPciAsicRadioOff(pAd, GUIRADIO_OFF, 0); | ||
1153 | } | ||
1154 | } | ||
1155 | |||
1156 | /* | ||
1157 | ========================================================================== | ||
1158 | Description: | ||
1159 | This routine sends command to firmware and turn our chip to wake up mode from power save mode. | ||
1160 | Both RadioOn and .11 power save function needs to call this routine. | ||
1161 | Input: | ||
1162 | Level = GUIRADIO_OFF : call this function is from Radio Off to Radio On. Need to restore PCI host value. | ||
1163 | Level = other value : normal wake up function. | ||
1164 | |||
1165 | ========================================================================== | ||
1166 | */ | ||
1167 | BOOLEAN RT28xxPciAsicRadioOn(struct rt_rtmp_adapter *pAd, u8 Level) | ||
1168 | { | ||
1169 | /*WPDMA_GLO_CFG_STRUC DmaCfg; */ | ||
1170 | BOOLEAN Cancelled; | ||
1171 | /*u32 MACValue; */ | ||
1172 | |||
1173 | if (pAd->OpMode == OPMODE_AP && Level == DOT11POWERSAVE) | ||
1174 | return FALSE; | ||
1175 | |||
1176 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) { | ||
1177 | if (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) { | ||
1178 | pAd->Mlme.bPsPollTimerRunning = FALSE; | ||
1179 | RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); | ||
1180 | } | ||
1181 | if ((pAd->StaCfg.PSControl.field.EnableNewPS == TRUE && | ||
1182 | (Level == GUIRADIO_OFF || Level == GUI_IDLE_POWER_SAVE)) || | ||
1183 | RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND)) { | ||
1184 | /* Some chips don't need to delay 6ms, so copy RTMPPCIePowerLinkCtrlRestore */ | ||
1185 | /* return condition here. */ | ||
1186 | /* | ||
1187 | if (((pAd->MACVersion&0xffff0000) != 0x28600000) | ||
1188 | && ((pAd->DeviceID == NIC2860_PCIe_DEVICE_ID) | ||
1189 | ||(pAd->DeviceID == NIC2790_PCIe_DEVICE_ID))) | ||
1190 | */ | ||
1191 | { | ||
1192 | DBGPRINT(RT_DEBUG_TRACE, | ||
1193 | ("RT28xxPciAsicRadioOn ()\n")); | ||
1194 | /* 1. Set PCI Link Control in Configuration Space. */ | ||
1195 | RTMPPCIeLinkCtrlValueRestore(pAd, | ||
1196 | RESTORE_WAKEUP); | ||
1197 | RTMPusecDelay(6000); | ||
1198 | } | ||
1199 | } | ||
1200 | } | ||
1201 | #ifdef PCIE_PS_SUPPORT | ||
1202 | if (! | ||
1203 | (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) | ||
1204 | && IS_VERSION_AFTER_F(pAd) | ||
1205 | && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) | ||
1206 | && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)))) | ||
1207 | #endif /* PCIE_PS_SUPPORT // */ | ||
1208 | { | ||
1209 | pAd->bPCIclkOff = FALSE; | ||
1210 | DBGPRINT(RT_DEBUG_TRACE, | ||
1211 | ("PSM :309xbPCIclkOff == %d\n", pAd->bPCIclkOff)); | ||
1212 | } | ||
1213 | /* 2. Send wake up command. */ | ||
1214 | AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02); | ||
1215 | pAd->bPCIclkOff = FALSE; | ||
1216 | /* 2-1. wait command ok. */ | ||
1217 | AsicCheckCommanOk(pAd, PowerWakeCID); | ||
1218 | RTMP_ASIC_INTERRUPT_ENABLE(pAd); | ||
1219 | |||
1220 | RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); | ||
1221 | if (Level == GUI_IDLE_POWER_SAVE) { | ||
1222 | #ifdef PCIE_PS_SUPPORT | ||
1223 | |||
1224 | /* add by johnli, RF power sequence setup, load RF normal operation-mode setup */ | ||
1225 | if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))) { | ||
1226 | struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps; | ||
1227 | |||
1228 | if (pChipOps->AsicReverseRfFromSleepMode) | ||
1229 | pChipOps->AsicReverseRfFromSleepMode(pAd); | ||
1230 | /* 3090 MCU Wakeup command needs more time to be stable. */ | ||
1231 | /* Before stable, don't issue other MCU command to prevent from firmware error. */ | ||
1232 | if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) | ||
1233 | && IS_VERSION_AFTER_F(pAd) | ||
1234 | && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == | ||
1235 | 3) | ||
1236 | && (pAd->StaCfg.PSControl.field.EnableNewPS == | ||
1237 | TRUE)) { | ||
1238 | RTMP_SEM_LOCK(&pAd->McuCmdLock); | ||
1239 | pAd->brt30xxBanMcuCmd = FALSE; | ||
1240 | RTMP_SEM_UNLOCK(&pAd->McuCmdLock); | ||
1241 | } | ||
1242 | } else | ||
1243 | /* end johnli */ | ||
1244 | #endif /* PCIE_PS_SUPPORT // */ | ||
1245 | { | ||
1246 | /* In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. */ | ||
1247 | { | ||
1248 | if (INFRA_ON(pAd) | ||
1249 | && (pAd->CommonCfg.CentralChannel != | ||
1250 | pAd->CommonCfg.Channel) | ||
1251 | && (pAd->MlmeAux.HtCapability.HtCapInfo. | ||
1252 | ChannelWidth == BW_40)) { | ||
1253 | /* Must using 40MHz. */ | ||
1254 | AsicSwitchChannel(pAd, | ||
1255 | pAd->CommonCfg. | ||
1256 | CentralChannel, | ||
1257 | FALSE); | ||
1258 | AsicLockChannel(pAd, | ||
1259 | pAd->CommonCfg. | ||
1260 | CentralChannel); | ||
1261 | } else { | ||
1262 | /* Must using 20MHz. */ | ||
1263 | AsicSwitchChannel(pAd, | ||
1264 | pAd->CommonCfg. | ||
1265 | Channel, FALSE); | ||
1266 | AsicLockChannel(pAd, | ||
1267 | pAd->CommonCfg.Channel); | ||
1268 | } | ||
1269 | } | ||
1270 | |||
1271 | } | ||
1272 | } | ||
1273 | return TRUE; | ||
1274 | |||
1275 | } | ||
1276 | |||
1277 | /* | ||
1278 | ========================================================================== | ||
1279 | Description: | ||
1280 | This routine sends command to firmware and turn our chip to power save mode. | ||
1281 | Both RadioOff and .11 power save function needs to call this routine. | ||
1282 | Input: | ||
1283 | Level = GUIRADIO_OFF : GUI Radio Off mode | ||
1284 | Level = DOT11POWERSAVE : 802.11 power save mode | ||
1285 | Level = RTMP_HALT : When Disable device. | ||
1286 | |||
1287 | ========================================================================== | ||
1288 | */ | ||
1289 | BOOLEAN RT28xxPciAsicRadioOff(struct rt_rtmp_adapter *pAd, | ||
1290 | u8 Level, u16 TbttNumToNextWakeUp) | ||
1291 | { | ||
1292 | WPDMA_GLO_CFG_STRUC DmaCfg; | ||
1293 | u8 i, tempBBP_R3 = 0; | ||
1294 | BOOLEAN brc = FALSE, Cancelled; | ||
1295 | u32 TbTTTime = 0; | ||
1296 | u32 PsPollTime = 0 /*, MACValue */ ; | ||
1297 | unsigned long BeaconPeriodTime; | ||
1298 | u32 RxDmaIdx, RxCpuIdx; | ||
1299 | DBGPRINT(RT_DEBUG_TRACE, | ||
1300 | ("AsicRadioOff ===> Lv= %d, TxCpuIdx = %d, TxDmaIdx = %d. RxCpuIdx = %d, RxDmaIdx = %d.\n", | ||
1301 | Level, pAd->TxRing[0].TxCpuIdx, pAd->TxRing[0].TxDmaIdx, | ||
1302 | pAd->RxRing.RxCpuIdx, pAd->RxRing.RxDmaIdx)); | ||
1303 | |||
1304 | if (pAd->OpMode == OPMODE_AP && Level == DOT11POWERSAVE) | ||
1305 | return FALSE; | ||
1306 | |||
1307 | /* Check Rx DMA busy status, if more than half is occupied, give up this radio off. */ | ||
1308 | RTMP_IO_READ32(pAd, RX_DRX_IDX, &RxDmaIdx); | ||
1309 | RTMP_IO_READ32(pAd, RX_CRX_IDX, &RxCpuIdx); | ||
1310 | if ((RxDmaIdx > RxCpuIdx) && ((RxDmaIdx - RxCpuIdx) > RX_RING_SIZE / 3)) { | ||
1311 | DBGPRINT(RT_DEBUG_TRACE, | ||
1312 | ("AsicRadioOff ===> return1. RxDmaIdx = %d , RxCpuIdx = %d. \n", | ||
1313 | RxDmaIdx, RxCpuIdx)); | ||
1314 | return FALSE; | ||
1315 | } else if ((RxCpuIdx >= RxDmaIdx) | ||
1316 | && ((RxCpuIdx - RxDmaIdx) < RX_RING_SIZE / 3)) { | ||
1317 | DBGPRINT(RT_DEBUG_TRACE, | ||
1318 | ("AsicRadioOff ===> return2. RxCpuIdx = %d. RxDmaIdx = %d , \n", | ||
1319 | RxCpuIdx, RxDmaIdx)); | ||
1320 | return FALSE; | ||
1321 | } | ||
1322 | /* Once go into this function, disable tx because don't want too many packets in queue to prevent HW stops. */ | ||
1323 | /*pAd->bPCIclkOffDisableTx = TRUE; */ | ||
1324 | RTMP_SET_PSFLAG(pAd, fRTMP_PS_DISABLE_TX); | ||
1325 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) | ||
1326 | && pAd->OpMode == OPMODE_STA | ||
1327 | && pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) { | ||
1328 | RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); | ||
1329 | RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); | ||
1330 | |||
1331 | if (Level == DOT11POWERSAVE) { | ||
1332 | RTMP_IO_READ32(pAd, TBTT_TIMER, &TbTTTime); | ||
1333 | TbTTTime &= 0x1ffff; | ||
1334 | /* 00. check if need to do sleep in this DTIM period. If next beacon will arrive within 30ms , ...doesn't necessarily sleep. */ | ||
1335 | /* TbTTTime uint = 64us, LEAD_TIME unit = 1024us, PsPollTime unit = 1ms */ | ||
1336 | if (((64 * TbTTTime) < ((LEAD_TIME * 1024) + 40000)) | ||
1337 | && (TbttNumToNextWakeUp == 0)) { | ||
1338 | DBGPRINT(RT_DEBUG_TRACE, | ||
1339 | ("TbTTTime = 0x%x , give up this sleep. \n", | ||
1340 | TbTTTime)); | ||
1341 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); | ||
1342 | /*pAd->bPCIclkOffDisableTx = FALSE; */ | ||
1343 | RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX); | ||
1344 | return FALSE; | ||
1345 | } else { | ||
1346 | PsPollTime = | ||
1347 | (64 * TbTTTime - LEAD_TIME * 1024) / 1000; | ||
1348 | #ifdef PCIE_PS_SUPPORT | ||
1349 | if ((IS_RT3090(pAd) || IS_RT3572(pAd) | ||
1350 | || IS_RT3390(pAd)) | ||
1351 | && IS_VERSION_AFTER_F(pAd) | ||
1352 | && (pAd->StaCfg.PSControl.field. | ||
1353 | rt30xxPowerMode == 3) | ||
1354 | && (pAd->StaCfg.PSControl.field. | ||
1355 | EnableNewPS == TRUE)) { | ||
1356 | PsPollTime -= 5; | ||
1357 | } else | ||
1358 | #endif /* PCIE_PS_SUPPORT // */ | ||
1359 | PsPollTime -= 3; | ||
1360 | |||
1361 | BeaconPeriodTime = | ||
1362 | pAd->CommonCfg.BeaconPeriod * 102 / 100; | ||
1363 | if (TbttNumToNextWakeUp > 0) | ||
1364 | PsPollTime += | ||
1365 | ((TbttNumToNextWakeUp - | ||
1366 | 1) * BeaconPeriodTime); | ||
1367 | |||
1368 | pAd->Mlme.bPsPollTimerRunning = TRUE; | ||
1369 | RTMPSetTimer(&pAd->Mlme.PsPollTimer, | ||
1370 | PsPollTime); | ||
1371 | } | ||
1372 | } | ||
1373 | } else { | ||
1374 | DBGPRINT(RT_DEBUG_TRACE, | ||
1375 | ("RT28xxPciAsicRadioOff::Level!=DOT11POWERSAVE \n")); | ||
1376 | } | ||
1377 | |||
1378 | pAd->bPCIclkOffDisableTx = FALSE; | ||
1379 | |||
1380 | RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); | ||
1381 | |||
1382 | /* Set to 1R. */ | ||
1383 | if (pAd->Antenna.field.RxPath > 1 && pAd->OpMode == OPMODE_STA) { | ||
1384 | tempBBP_R3 = (pAd->StaCfg.BBPR3 & 0xE7); | ||
1385 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, tempBBP_R3); | ||
1386 | } | ||
1387 | /* In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. */ | ||
1388 | if ((INFRA_ON(pAd) || pAd->OpMode == OPMODE_AP) | ||
1389 | && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) | ||
1390 | && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) { | ||
1391 | /* Must using 40MHz. */ | ||
1392 | AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel); | ||
1393 | } else { | ||
1394 | /* Must using 20MHz. */ | ||
1395 | AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel); | ||
1396 | } | ||
1397 | |||
1398 | if (Level != RTMP_HALT) { | ||
1399 | /* Change Interrupt bitmask. */ | ||
1400 | /* When PCI clock is off, don't want to service interrupt. */ | ||
1401 | RTMP_IO_WRITE32(pAd, INT_MASK_CSR, AutoWakeupInt); | ||
1402 | } else { | ||
1403 | RTMP_ASIC_INTERRUPT_DISABLE(pAd); | ||
1404 | } | ||
1405 | |||
1406 | RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); | ||
1407 | /* 2. Send Sleep command */ | ||
1408 | RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff); | ||
1409 | RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff); | ||
1410 | /* send POWER-SAVE command to MCU. high-byte = 1 save power as much as possible. high byte = 0 save less power */ | ||
1411 | AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x1); | ||
1412 | /* 2-1. Wait command success */ | ||
1413 | /* Status = 1 : success, Status = 2, already sleep, Status = 3, Maybe MAC is busy so can't finish this task. */ | ||
1414 | brc = AsicCheckCommanOk(pAd, PowerSafeCID); | ||
1415 | |||
1416 | /* 3. After 0x30 command is ok, send radio off command. lowbyte = 0 for power safe. */ | ||
1417 | /* If 0x30 command is not ok this time, we can ignore 0x35 command. It will make sure not cause firmware'r problem. */ | ||
1418 | if ((Level == DOT11POWERSAVE) && (brc == TRUE)) { | ||
1419 | AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 0, 0x00); /* lowbyte = 0 means to do power safe, NOT turn off radio. */ | ||
1420 | /* 3-1. Wait command success */ | ||
1421 | AsicCheckCommanOk(pAd, PowerRadioOffCID); | ||
1422 | } else if (brc == TRUE) { | ||
1423 | AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 1, 0x00); /* lowbyte = 0 means to do power safe, NOT turn off radio. */ | ||
1424 | /* 3-1. Wait command success */ | ||
1425 | AsicCheckCommanOk(pAd, PowerRadioOffCID); | ||
1426 | } | ||
1427 | /* 1. Wait DMA not busy */ | ||
1428 | i = 0; | ||
1429 | do { | ||
1430 | RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word); | ||
1431 | if ((DmaCfg.field.RxDMABusy == 0) | ||
1432 | && (DmaCfg.field.TxDMABusy == 0)) | ||
1433 | break; | ||
1434 | RTMPusecDelay(20); | ||
1435 | i++; | ||
1436 | } while (i < 50); | ||
1437 | |||
1438 | /* | ||
1439 | if (i >= 50) | ||
1440 | { | ||
1441 | pAd->CheckDmaBusyCount++; | ||
1442 | DBGPRINT(RT_DEBUG_TRACE, ("DMA Rx keeps busy. return on AsicRadioOff () CheckDmaBusyCount = %d \n", pAd->CheckDmaBusyCount)); | ||
1443 | } | ||
1444 | else | ||
1445 | { | ||
1446 | pAd->CheckDmaBusyCount = 0; | ||
1447 | } | ||
1448 | */ | ||
1449 | /*KH Debug:My original codes have the following codes, but currecnt codes do not have it. */ | ||
1450 | /* Disable for stability. If PCIE Link Control is modified for advance power save, re-covery this code segment. */ | ||
1451 | RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x1280); | ||
1452 | /*OPSTATUS_SET_FLAG(pAd, fOP_STATUS_CLKSELECT_40MHZ); */ | ||
1453 | |||
1454 | #ifdef PCIE_PS_SUPPORT | ||
1455 | if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) | ||
1456 | && IS_VERSION_AFTER_F(pAd) | ||
1457 | && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) | ||
1458 | && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) { | ||
1459 | DBGPRINT(RT_DEBUG_TRACE, | ||
1460 | ("RT28xxPciAsicRadioOff::3090 return to skip the following TbttNumToNextWakeUp setting for 279x\n")); | ||
1461 | pAd->bPCIclkOff = TRUE; | ||
1462 | RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX); | ||
1463 | /* For this case, doesn't need to below actions, so return here. */ | ||
1464 | return brc; | ||
1465 | } | ||
1466 | #endif /* PCIE_PS_SUPPORT // */ | ||
1467 | |||
1468 | if (Level == DOT11POWERSAVE) { | ||
1469 | AUTO_WAKEUP_STRUC AutoWakeupCfg; | ||
1470 | /*RTMPSetTimer(&pAd->Mlme.PsPollTimer, 90); */ | ||
1471 | |||
1472 | /* we have decided to SLEEP, so at least do it for a BEACON period. */ | ||
1473 | if (TbttNumToNextWakeUp == 0) | ||
1474 | TbttNumToNextWakeUp = 1; | ||
1475 | |||
1476 | AutoWakeupCfg.word = 0; | ||
1477 | RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); | ||
1478 | |||
1479 | /* 1. Set auto wake up timer. */ | ||
1480 | AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1; | ||
1481 | AutoWakeupCfg.field.EnableAutoWakeup = 1; | ||
1482 | AutoWakeupCfg.field.AutoLeadTime = LEAD_TIME; | ||
1483 | RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); | ||
1484 | } | ||
1485 | /* 4-1. If it's to disable our device. Need to restore PCI Configuration Space to its original value. */ | ||
1486 | if (Level == RTMP_HALT && pAd->OpMode == OPMODE_STA) { | ||
1487 | if ((brc == TRUE) && (i < 50)) | ||
1488 | RTMPPCIeLinkCtrlSetting(pAd, 1); | ||
1489 | } | ||
1490 | /* 4. Set PCI configuration Space Link Comtrol fields. Only Radio Off needs to call this function */ | ||
1491 | else if (pAd->OpMode == OPMODE_STA) { | ||
1492 | if ((brc == TRUE) && (i < 50)) | ||
1493 | RTMPPCIeLinkCtrlSetting(pAd, 3); | ||
1494 | } | ||
1495 | /*pAd->bPCIclkOffDisableTx = FALSE; */ | ||
1496 | RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX); | ||
1497 | return TRUE; | ||
1498 | } | ||
1499 | |||
1500 | void RT28xxPciMlmeRadioOn(struct rt_rtmp_adapter *pAd) | ||
1501 | { | ||
1502 | if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) | ||
1503 | return; | ||
1504 | |||
1505 | DBGPRINT(RT_DEBUG_TRACE, ("%s===>\n", __func__)); | ||
1506 | |||
1507 | if ((pAd->OpMode == OPMODE_AP) || ((pAd->OpMode == OPMODE_STA) | ||
1508 | && | ||
1509 | (!OPSTATUS_TEST_FLAG | ||
1510 | (pAd, fOP_STATUS_PCIE_DEVICE) | ||
1511 | || pAd->StaCfg.PSControl.field. | ||
1512 | EnableNewPS == FALSE))) { | ||
1513 | RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); | ||
1514 | /*NICResetFromError(pAd); */ | ||
1515 | |||
1516 | RTMPRingCleanUp(pAd, QID_AC_BK); | ||
1517 | RTMPRingCleanUp(pAd, QID_AC_BE); | ||
1518 | RTMPRingCleanUp(pAd, QID_AC_VI); | ||
1519 | RTMPRingCleanUp(pAd, QID_AC_VO); | ||
1520 | RTMPRingCleanUp(pAd, QID_MGMT); | ||
1521 | RTMPRingCleanUp(pAd, QID_RX); | ||
1522 | |||
1523 | /* Enable Tx/Rx */ | ||
1524 | RTMPEnableRxTx(pAd); | ||
1525 | |||
1526 | /* Clear Radio off flag */ | ||
1527 | RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); | ||
1528 | |||
1529 | RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); | ||
1530 | |||
1531 | /* Set LED */ | ||
1532 | RTMPSetLED(pAd, LED_RADIO_ON); | ||
1533 | } | ||
1534 | |||
1535 | if ((pAd->OpMode == OPMODE_STA) && | ||
1536 | (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) | ||
1537 | && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) { | ||
1538 | BOOLEAN Cancelled; | ||
1539 | |||
1540 | RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); | ||
1541 | |||
1542 | pAd->Mlme.bPsPollTimerRunning = FALSE; | ||
1543 | RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); | ||
1544 | RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); | ||
1545 | RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 40); | ||
1546 | } | ||
1547 | } | ||
1548 | |||
1549 | void RT28xxPciMlmeRadioOFF(struct rt_rtmp_adapter *pAd) | ||
1550 | { | ||
1551 | BOOLEAN brc = TRUE; | ||
1552 | |||
1553 | if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) | ||
1554 | return; | ||
1555 | |||
1556 | /* Link down first if any association exists */ | ||
1557 | if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) { | ||
1558 | if (INFRA_ON(pAd) || ADHOC_ON(pAd)) { | ||
1559 | struct rt_mlme_disassoc_req DisReq; | ||
1560 | struct rt_mlme_queue_elem *pMsgElem = | ||
1561 | kmalloc(sizeof(struct rt_mlme_queue_elem), | ||
1562 | MEM_ALLOC_FLAG); | ||
1563 | |||
1564 | if (pMsgElem) { | ||
1565 | COPY_MAC_ADDR(&DisReq.Addr, | ||
1566 | pAd->CommonCfg.Bssid); | ||
1567 | DisReq.Reason = REASON_DISASSOC_STA_LEAVING; | ||
1568 | |||
1569 | pMsgElem->Machine = ASSOC_STATE_MACHINE; | ||
1570 | pMsgElem->MsgType = MT2_MLME_DISASSOC_REQ; | ||
1571 | pMsgElem->MsgLen = | ||
1572 | sizeof(struct rt_mlme_disassoc_req); | ||
1573 | NdisMoveMemory(pMsgElem->Msg, &DisReq, | ||
1574 | sizeof | ||
1575 | (struct rt_mlme_disassoc_req)); | ||
1576 | |||
1577 | MlmeDisassocReqAction(pAd, pMsgElem); | ||
1578 | kfree(pMsgElem); | ||
1579 | |||
1580 | RTMPusecDelay(1000); | ||
1581 | } | ||
1582 | } | ||
1583 | } | ||
1584 | |||
1585 | DBGPRINT(RT_DEBUG_TRACE, ("%s===>\n", __func__)); | ||
1586 | |||
1587 | /* Set Radio off flag */ | ||
1588 | RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); | ||
1589 | |||
1590 | { | ||
1591 | BOOLEAN Cancelled; | ||
1592 | if (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) { | ||
1593 | if (RTMP_TEST_FLAG | ||
1594 | (pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) { | ||
1595 | RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, | ||
1596 | &Cancelled); | ||
1597 | RTMP_CLEAR_FLAG(pAd, | ||
1598 | fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); | ||
1599 | } | ||
1600 | /* If during power safe mode. */ | ||
1601 | if (pAd->StaCfg.bRadio == TRUE) { | ||
1602 | DBGPRINT(RT_DEBUG_TRACE, | ||
1603 | ("-->MlmeRadioOff() return on bRadio == TRUE; \n")); | ||
1604 | return; | ||
1605 | } | ||
1606 | /* Always radio on since the NIC needs to set the MCU command (LED_RADIO_OFF). */ | ||
1607 | if (IDLE_ON(pAd) && | ||
1608 | (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) | ||
1609 | { | ||
1610 | RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); | ||
1611 | } | ||
1612 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) { | ||
1613 | BOOLEAN Cancelled; | ||
1614 | pAd->Mlme.bPsPollTimerRunning = FALSE; | ||
1615 | RTMPCancelTimer(&pAd->Mlme.PsPollTimer, | ||
1616 | &Cancelled); | ||
1617 | RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, | ||
1618 | &Cancelled); | ||
1619 | } | ||
1620 | } | ||
1621 | /* Link down first if any association exists */ | ||
1622 | if (INFRA_ON(pAd) || ADHOC_ON(pAd)) | ||
1623 | LinkDown(pAd, FALSE); | ||
1624 | RTMPusecDelay(10000); | ||
1625 | /*========================================== */ | ||
1626 | /* Clean up old bss table */ | ||
1627 | BssTableInit(&pAd->ScanTab); | ||
1628 | |||
1629 | /* | ||
1630 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) | ||
1631 | { | ||
1632 | RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10); | ||
1633 | return; | ||
1634 | } | ||
1635 | */ | ||
1636 | } | ||
1637 | |||
1638 | /* Set LED.Move to here for fixing LED bug. This flag must be called after LinkDown */ | ||
1639 | RTMPSetLED(pAd, LED_RADIO_OFF); | ||
1640 | |||
1641 | /*KH Debug:All PCIe devices need to use timer to execute radio off function, or the PCIe&&EnableNewPS needs. */ | ||
1642 | /*KH Ans:It is right, because only when the PCIe and EnableNewPs is true, we need to delay the RadioOffTimer */ | ||
1643 | /*to avoid the deadlock with PCIe Power saving function. */ | ||
1644 | if (pAd->OpMode == OPMODE_STA && | ||
1645 | OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) && | ||
1646 | pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) { | ||
1647 | RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10); | ||
1648 | } else { | ||
1649 | brc = RT28xxPciAsicRadioOff(pAd, GUIRADIO_OFF, 0); | ||
1650 | |||
1651 | if (brc == FALSE) { | ||
1652 | DBGPRINT(RT_DEBUG_ERROR, | ||
1653 | ("%s call RT28xxPciAsicRadioOff fail!\n", | ||
1654 | __func__)); | ||
1655 | } | ||
1656 | } | ||
1657 | /* | ||
1658 | */ | ||
1659 | } | ||
1660 | |||
1661 | #endif /* RTMP_MAC_PCI // */ | ||
diff --git a/drivers/staging/rt2860/common/cmm_mac_usb.c b/drivers/staging/rt2860/common/cmm_mac_usb.c deleted file mode 100644 index 64a65a460c2..00000000000 --- a/drivers/staging/rt2860/common/cmm_mac_usb.c +++ /dev/null | |||
@@ -1,1162 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | */ | ||
27 | |||
28 | #ifdef RTMP_MAC_USB | ||
29 | |||
30 | #include "../rt_config.h" | ||
31 | |||
32 | /* | ||
33 | ======================================================================== | ||
34 | Routine Description: | ||
35 | Initialize receive data structures. | ||
36 | |||
37 | Arguments: | ||
38 | pAd Pointer to our adapter | ||
39 | |||
40 | Return Value: | ||
41 | NDIS_STATUS_SUCCESS | ||
42 | NDIS_STATUS_RESOURCES | ||
43 | |||
44 | Note: | ||
45 | Initialize all receive releated private buffer, include those define | ||
46 | in struct rt_rtmp_adapter structure and all private data structures. The mahor | ||
47 | work is to allocate buffer for each packet and chain buffer to | ||
48 | NDIS packet descriptor. | ||
49 | ======================================================================== | ||
50 | */ | ||
51 | int NICInitRecv(struct rt_rtmp_adapter *pAd) | ||
52 | { | ||
53 | u8 i; | ||
54 | int Status = NDIS_STATUS_SUCCESS; | ||
55 | struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie; | ||
56 | |||
57 | DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitRecv\n")); | ||
58 | pObj = pObj; | ||
59 | |||
60 | /*InterlockedExchange(&pAd->PendingRx, 0); */ | ||
61 | pAd->PendingRx = 0; | ||
62 | pAd->NextRxBulkInReadIndex = 0; /* Next Rx Read index */ | ||
63 | pAd->NextRxBulkInIndex = 0; /*RX_RING_SIZE -1; // Rx Bulk pointer */ | ||
64 | pAd->NextRxBulkInPosition = 0; | ||
65 | |||
66 | for (i = 0; i < (RX_RING_SIZE); i++) { | ||
67 | struct rt_rx_context *pRxContext = &(pAd->RxContext[i]); | ||
68 | |||
69 | /*Allocate URB */ | ||
70 | pRxContext->pUrb = RTUSB_ALLOC_URB(0); | ||
71 | if (pRxContext->pUrb == NULL) { | ||
72 | Status = NDIS_STATUS_RESOURCES; | ||
73 | goto out1; | ||
74 | } | ||
75 | /* Allocate transfer buffer */ | ||
76 | pRxContext->TransferBuffer = | ||
77 | RTUSB_URB_ALLOC_BUFFER(pObj->pUsb_Dev, MAX_RXBULK_SIZE, | ||
78 | &pRxContext->data_dma); | ||
79 | if (pRxContext->TransferBuffer == NULL) { | ||
80 | Status = NDIS_STATUS_RESOURCES; | ||
81 | goto out1; | ||
82 | } | ||
83 | |||
84 | NdisZeroMemory(pRxContext->TransferBuffer, MAX_RXBULK_SIZE); | ||
85 | |||
86 | pRxContext->pAd = pAd; | ||
87 | pRxContext->pIrp = NULL; | ||
88 | pRxContext->InUse = FALSE; | ||
89 | pRxContext->IRPPending = FALSE; | ||
90 | pRxContext->Readable = FALSE; | ||
91 | /*pRxContext->ReorderInUse = FALSE; */ | ||
92 | pRxContext->bRxHandling = FALSE; | ||
93 | pRxContext->BulkInOffset = 0; | ||
94 | } | ||
95 | |||
96 | DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitRecv(Status=%d)\n", Status)); | ||
97 | return Status; | ||
98 | |||
99 | out1: | ||
100 | for (i = 0; i < (RX_RING_SIZE); i++) { | ||
101 | struct rt_rx_context *pRxContext = &(pAd->RxContext[i]); | ||
102 | |||
103 | if (NULL != pRxContext->TransferBuffer) { | ||
104 | RTUSB_URB_FREE_BUFFER(pObj->pUsb_Dev, MAX_RXBULK_SIZE, | ||
105 | pRxContext->TransferBuffer, | ||
106 | pRxContext->data_dma); | ||
107 | pRxContext->TransferBuffer = NULL; | ||
108 | } | ||
109 | |||
110 | if (NULL != pRxContext->pUrb) { | ||
111 | RTUSB_UNLINK_URB(pRxContext->pUrb); | ||
112 | RTUSB_FREE_URB(pRxContext->pUrb); | ||
113 | pRxContext->pUrb = NULL; | ||
114 | } | ||
115 | } | ||
116 | |||
117 | return Status; | ||
118 | } | ||
119 | |||
120 | /* | ||
121 | ======================================================================== | ||
122 | Routine Description: | ||
123 | Initialize transmit data structures. | ||
124 | |||
125 | Arguments: | ||
126 | pAd Pointer to our adapter | ||
127 | |||
128 | Return Value: | ||
129 | NDIS_STATUS_SUCCESS | ||
130 | NDIS_STATUS_RESOURCES | ||
131 | |||
132 | Note: | ||
133 | ======================================================================== | ||
134 | */ | ||
135 | int NICInitTransmit(struct rt_rtmp_adapter *pAd) | ||
136 | { | ||
137 | #define LM_USB_ALLOC(pObj, Context, TB_Type, BufferSize, Status, msg1, err1, msg2, err2) \ | ||
138 | Context->pUrb = RTUSB_ALLOC_URB(0); \ | ||
139 | if (Context->pUrb == NULL) { \ | ||
140 | DBGPRINT(RT_DEBUG_ERROR, msg1); \ | ||
141 | Status = NDIS_STATUS_RESOURCES; \ | ||
142 | goto err1; } \ | ||
143 | \ | ||
144 | Context->TransferBuffer = \ | ||
145 | (TB_Type)RTUSB_URB_ALLOC_BUFFER(pObj->pUsb_Dev, BufferSize, &Context->data_dma); \ | ||
146 | if (Context->TransferBuffer == NULL) { \ | ||
147 | DBGPRINT(RT_DEBUG_ERROR, msg2); \ | ||
148 | Status = NDIS_STATUS_RESOURCES; \ | ||
149 | goto err2; } | ||
150 | |||
151 | #define LM_URB_FREE(pObj, Context, BufferSize) \ | ||
152 | if (NULL != Context->pUrb) { \ | ||
153 | RTUSB_UNLINK_URB(Context->pUrb); \ | ||
154 | RTUSB_FREE_URB(Context->pUrb); \ | ||
155 | Context->pUrb = NULL; } \ | ||
156 | if (NULL != Context->TransferBuffer) { \ | ||
157 | RTUSB_URB_FREE_BUFFER(pObj->pUsb_Dev, BufferSize, \ | ||
158 | Context->TransferBuffer, \ | ||
159 | Context->data_dma); \ | ||
160 | Context->TransferBuffer = NULL; } | ||
161 | |||
162 | u8 i, acidx; | ||
163 | int Status = NDIS_STATUS_SUCCESS; | ||
164 | struct rt_tx_context *pNullContext = &(pAd->NullContext); | ||
165 | struct rt_tx_context *pPsPollContext = &(pAd->PsPollContext); | ||
166 | struct rt_tx_context *pRTSContext = &(pAd->RTSContext); | ||
167 | struct rt_tx_context *pMLMEContext = NULL; | ||
168 | /* struct rt_ht_tx_context *pHTTXContext = NULL; */ | ||
169 | struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie; | ||
170 | void *RingBaseVa; | ||
171 | /* struct rt_rtmp_tx_ring *pTxRing; */ | ||
172 | struct rt_rtmp_mgmt_ring *pMgmtRing; | ||
173 | |||
174 | DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitTransmit\n")); | ||
175 | pObj = pObj; | ||
176 | |||
177 | /* Init 4 set of Tx parameters */ | ||
178 | for (acidx = 0; acidx < NUM_OF_TX_RING; acidx++) { | ||
179 | /* Initialize all Transmit releated queues */ | ||
180 | InitializeQueueHeader(&pAd->TxSwQueue[acidx]); | ||
181 | |||
182 | /* Next Local tx ring pointer waiting for buck out */ | ||
183 | pAd->NextBulkOutIndex[acidx] = acidx; | ||
184 | pAd->BulkOutPending[acidx] = FALSE; /* Buck Out control flag */ | ||
185 | /*pAd->DataBulkDoneIdx[acidx] = 0; */ | ||
186 | } | ||
187 | |||
188 | /*pAd->NextMLMEIndex = 0; */ | ||
189 | /*pAd->PushMgmtIndex = 0; */ | ||
190 | /*pAd->PopMgmtIndex = 0; */ | ||
191 | /*InterlockedExchange(&pAd->MgmtQueueSize, 0); */ | ||
192 | /*InterlockedExchange(&pAd->TxCount, 0); */ | ||
193 | |||
194 | /*pAd->PrioRingFirstIndex = 0; */ | ||
195 | /*pAd->PrioRingTxCnt = 0; */ | ||
196 | |||
197 | do { | ||
198 | /* */ | ||
199 | /* TX_RING_SIZE, 4 ACs */ | ||
200 | /* */ | ||
201 | for (acidx = 0; acidx < 4; acidx++) { | ||
202 | struct rt_ht_tx_context *pHTTXContext = &(pAd->TxContext[acidx]); | ||
203 | |||
204 | NdisZeroMemory(pHTTXContext, sizeof(struct rt_ht_tx_context)); | ||
205 | /*Allocate URB */ | ||
206 | LM_USB_ALLOC(pObj, pHTTXContext, struct rt_httx_buffer *, | ||
207 | sizeof(struct rt_httx_buffer), Status, | ||
208 | ("<-- ERROR in Alloc TX TxContext[%d] urb!\n", | ||
209 | acidx), done, | ||
210 | ("<-- ERROR in Alloc TX TxContext[%d] struct rt_httx_buffer!\n", | ||
211 | acidx), out1); | ||
212 | |||
213 | NdisZeroMemory(pHTTXContext->TransferBuffer-> | ||
214 | Aggregation, 4); | ||
215 | pHTTXContext->pAd = pAd; | ||
216 | pHTTXContext->pIrp = NULL; | ||
217 | pHTTXContext->IRPPending = FALSE; | ||
218 | pHTTXContext->NextBulkOutPosition = 0; | ||
219 | pHTTXContext->ENextBulkOutPosition = 0; | ||
220 | pHTTXContext->CurWritePosition = 0; | ||
221 | pHTTXContext->CurWriteRealPos = 0; | ||
222 | pHTTXContext->BulkOutSize = 0; | ||
223 | pHTTXContext->BulkOutPipeId = acidx; | ||
224 | pHTTXContext->bRingEmpty = TRUE; | ||
225 | pHTTXContext->bCopySavePad = FALSE; | ||
226 | pAd->BulkOutPending[acidx] = FALSE; | ||
227 | } | ||
228 | |||
229 | /* */ | ||
230 | /* MGMT_RING_SIZE */ | ||
231 | /* */ | ||
232 | |||
233 | /* Allocate MGMT ring descriptor's memory */ | ||
234 | pAd->MgmtDescRing.AllocSize = | ||
235 | MGMT_RING_SIZE * sizeof(struct rt_tx_context); | ||
236 | os_alloc_mem(pAd, (u8 **) (&pAd->MgmtDescRing.AllocVa), | ||
237 | pAd->MgmtDescRing.AllocSize); | ||
238 | if (pAd->MgmtDescRing.AllocVa == NULL) { | ||
239 | DBGPRINT_ERR("Failed to allocate a big buffer for MgmtDescRing!\n"); | ||
240 | Status = NDIS_STATUS_RESOURCES; | ||
241 | goto out1; | ||
242 | } | ||
243 | NdisZeroMemory(pAd->MgmtDescRing.AllocVa, | ||
244 | pAd->MgmtDescRing.AllocSize); | ||
245 | RingBaseVa = pAd->MgmtDescRing.AllocVa; | ||
246 | |||
247 | /* Initialize MGMT Ring and associated buffer memory */ | ||
248 | pMgmtRing = &pAd->MgmtRing; | ||
249 | for (i = 0; i < MGMT_RING_SIZE; i++) { | ||
250 | /* link the pre-allocated Mgmt buffer to MgmtRing.Cell */ | ||
251 | pMgmtRing->Cell[i].AllocSize = sizeof(struct rt_tx_context); | ||
252 | pMgmtRing->Cell[i].AllocVa = RingBaseVa; | ||
253 | pMgmtRing->Cell[i].pNdisPacket = NULL; | ||
254 | pMgmtRing->Cell[i].pNextNdisPacket = NULL; | ||
255 | |||
256 | /*Allocate URB for MLMEContext */ | ||
257 | pMLMEContext = | ||
258 | (struct rt_tx_context *)pAd->MgmtRing.Cell[i].AllocVa; | ||
259 | pMLMEContext->pUrb = RTUSB_ALLOC_URB(0); | ||
260 | if (pMLMEContext->pUrb == NULL) { | ||
261 | DBGPRINT(RT_DEBUG_ERROR, | ||
262 | ("<-- ERROR in Alloc TX MLMEContext[%d] urb!\n", | ||
263 | i)); | ||
264 | Status = NDIS_STATUS_RESOURCES; | ||
265 | goto out2; | ||
266 | } | ||
267 | pMLMEContext->pAd = pAd; | ||
268 | pMLMEContext->pIrp = NULL; | ||
269 | pMLMEContext->TransferBuffer = NULL; | ||
270 | pMLMEContext->InUse = FALSE; | ||
271 | pMLMEContext->IRPPending = FALSE; | ||
272 | pMLMEContext->bWaitingBulkOut = FALSE; | ||
273 | pMLMEContext->BulkOutSize = 0; | ||
274 | pMLMEContext->SelfIdx = i; | ||
275 | |||
276 | /* Offset to next ring descriptor address */ | ||
277 | RingBaseVa = (u8 *)RingBaseVa + sizeof(struct rt_tx_context); | ||
278 | } | ||
279 | DBGPRINT(RT_DEBUG_TRACE, | ||
280 | ("MGMT Ring: total %d entry allocated\n", i)); | ||
281 | |||
282 | /*pAd->MgmtRing.TxSwFreeIdx = (MGMT_RING_SIZE - 1); */ | ||
283 | pAd->MgmtRing.TxSwFreeIdx = MGMT_RING_SIZE; | ||
284 | pAd->MgmtRing.TxCpuIdx = 0; | ||
285 | pAd->MgmtRing.TxDmaIdx = 0; | ||
286 | |||
287 | /* */ | ||
288 | /* BEACON_RING_SIZE */ | ||
289 | /* */ | ||
290 | for (i = 0; i < BEACON_RING_SIZE; i++) /* 2 */ | ||
291 | { | ||
292 | struct rt_tx_context *pBeaconContext = &(pAd->BeaconContext[i]); | ||
293 | |||
294 | NdisZeroMemory(pBeaconContext, sizeof(struct rt_tx_context)); | ||
295 | |||
296 | /*Allocate URB */ | ||
297 | LM_USB_ALLOC(pObj, pBeaconContext, struct rt_tx_buffer *, | ||
298 | sizeof(struct rt_tx_buffer), Status, | ||
299 | ("<-- ERROR in Alloc TX BeaconContext[%d] urb!\n", | ||
300 | i), out2, | ||
301 | ("<-- ERROR in Alloc TX BeaconContext[%d] struct rt_tx_buffer!\n", | ||
302 | i), out3); | ||
303 | |||
304 | pBeaconContext->pAd = pAd; | ||
305 | pBeaconContext->pIrp = NULL; | ||
306 | pBeaconContext->InUse = FALSE; | ||
307 | pBeaconContext->IRPPending = FALSE; | ||
308 | } | ||
309 | |||
310 | /* */ | ||
311 | /* NullContext */ | ||
312 | /* */ | ||
313 | NdisZeroMemory(pNullContext, sizeof(struct rt_tx_context)); | ||
314 | |||
315 | /*Allocate URB */ | ||
316 | LM_USB_ALLOC(pObj, pNullContext, struct rt_tx_buffer *, sizeof(struct rt_tx_buffer), | ||
317 | Status, | ||
318 | ("<-- ERROR in Alloc TX NullContext urb!\n"), | ||
319 | out3, | ||
320 | ("<-- ERROR in Alloc TX NullContext struct rt_tx_buffer!\n"), | ||
321 | out4); | ||
322 | |||
323 | pNullContext->pAd = pAd; | ||
324 | pNullContext->pIrp = NULL; | ||
325 | pNullContext->InUse = FALSE; | ||
326 | pNullContext->IRPPending = FALSE; | ||
327 | |||
328 | /* */ | ||
329 | /* RTSContext */ | ||
330 | /* */ | ||
331 | NdisZeroMemory(pRTSContext, sizeof(struct rt_tx_context)); | ||
332 | |||
333 | /*Allocate URB */ | ||
334 | LM_USB_ALLOC(pObj, pRTSContext, struct rt_tx_buffer *, sizeof(struct rt_tx_buffer), | ||
335 | Status, | ||
336 | ("<-- ERROR in Alloc TX RTSContext urb!\n"), | ||
337 | out4, | ||
338 | ("<-- ERROR in Alloc TX RTSContext struct rt_tx_buffer!\n"), | ||
339 | out5); | ||
340 | |||
341 | pRTSContext->pAd = pAd; | ||
342 | pRTSContext->pIrp = NULL; | ||
343 | pRTSContext->InUse = FALSE; | ||
344 | pRTSContext->IRPPending = FALSE; | ||
345 | |||
346 | /* */ | ||
347 | /* PsPollContext */ | ||
348 | /* */ | ||
349 | /*NdisZeroMemory(pPsPollContext, sizeof(struct rt_tx_context)); */ | ||
350 | /*Allocate URB */ | ||
351 | LM_USB_ALLOC(pObj, pPsPollContext, struct rt_tx_buffer *, | ||
352 | sizeof(struct rt_tx_buffer), Status, | ||
353 | ("<-- ERROR in Alloc TX PsPollContext urb!\n"), | ||
354 | out5, | ||
355 | ("<-- ERROR in Alloc TX PsPollContext struct rt_tx_buffer!\n"), | ||
356 | out6); | ||
357 | |||
358 | pPsPollContext->pAd = pAd; | ||
359 | pPsPollContext->pIrp = NULL; | ||
360 | pPsPollContext->InUse = FALSE; | ||
361 | pPsPollContext->IRPPending = FALSE; | ||
362 | pPsPollContext->bAggregatible = FALSE; | ||
363 | pPsPollContext->LastOne = TRUE; | ||
364 | |||
365 | } while (FALSE); | ||
366 | |||
367 | done: | ||
368 | DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitTransmit(Status=%d)\n", Status)); | ||
369 | |||
370 | return Status; | ||
371 | |||
372 | /* --------------------------- ERROR HANDLE --------------------------- */ | ||
373 | out6: | ||
374 | LM_URB_FREE(pObj, pPsPollContext, sizeof(struct rt_tx_buffer)); | ||
375 | |||
376 | out5: | ||
377 | LM_URB_FREE(pObj, pRTSContext, sizeof(struct rt_tx_buffer)); | ||
378 | |||
379 | out4: | ||
380 | LM_URB_FREE(pObj, pNullContext, sizeof(struct rt_tx_buffer)); | ||
381 | |||
382 | out3: | ||
383 | for (i = 0; i < BEACON_RING_SIZE; i++) { | ||
384 | struct rt_tx_context *pBeaconContext = &(pAd->BeaconContext[i]); | ||
385 | if (pBeaconContext) | ||
386 | LM_URB_FREE(pObj, pBeaconContext, sizeof(struct rt_tx_buffer)); | ||
387 | } | ||
388 | |||
389 | out2: | ||
390 | if (pAd->MgmtDescRing.AllocVa) { | ||
391 | pMgmtRing = &pAd->MgmtRing; | ||
392 | for (i = 0; i < MGMT_RING_SIZE; i++) { | ||
393 | pMLMEContext = | ||
394 | (struct rt_tx_context *)pAd->MgmtRing.Cell[i].AllocVa; | ||
395 | if (pMLMEContext) | ||
396 | LM_URB_FREE(pObj, pMLMEContext, | ||
397 | sizeof(struct rt_tx_buffer)); | ||
398 | } | ||
399 | os_free_mem(pAd, pAd->MgmtDescRing.AllocVa); | ||
400 | pAd->MgmtDescRing.AllocVa = NULL; | ||
401 | } | ||
402 | |||
403 | out1: | ||
404 | for (acidx = 0; acidx < 4; acidx++) { | ||
405 | struct rt_ht_tx_context *pTxContext = &(pAd->TxContext[acidx]); | ||
406 | if (pTxContext) | ||
407 | LM_URB_FREE(pObj, pTxContext, sizeof(struct rt_httx_buffer)); | ||
408 | } | ||
409 | |||
410 | /* Here we didn't have any pre-allocated memory need to free. */ | ||
411 | |||
412 | return Status; | ||
413 | } | ||
414 | |||
415 | /* | ||
416 | ======================================================================== | ||
417 | Routine Description: | ||
418 | Allocate DMA memory blocks for send, receive. | ||
419 | |||
420 | Arguments: | ||
421 | pAd Pointer to our adapter | ||
422 | |||
423 | Return Value: | ||
424 | NDIS_STATUS_SUCCESS | ||
425 | NDIS_STATUS_FAILURE | ||
426 | NDIS_STATUS_RESOURCES | ||
427 | |||
428 | Note: | ||
429 | ======================================================================== | ||
430 | */ | ||
431 | int RTMPAllocTxRxRingMemory(struct rt_rtmp_adapter *pAd) | ||
432 | { | ||
433 | /* struct rt_counter_802_11 pCounter = &pAd->WlanCounters; */ | ||
434 | int Status; | ||
435 | int num; | ||
436 | |||
437 | DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n")); | ||
438 | |||
439 | do { | ||
440 | /* Init the struct rt_cmdq and CmdQLock */ | ||
441 | NdisAllocateSpinLock(&pAd->CmdQLock); | ||
442 | NdisAcquireSpinLock(&pAd->CmdQLock); | ||
443 | RTUSBInitializeCmdQ(&pAd->CmdQ); | ||
444 | NdisReleaseSpinLock(&pAd->CmdQLock); | ||
445 | |||
446 | NdisAllocateSpinLock(&pAd->MLMEBulkOutLock); | ||
447 | /*NdisAllocateSpinLock(&pAd->MLMEWaitQueueLock); */ | ||
448 | NdisAllocateSpinLock(&pAd->BulkOutLock[0]); | ||
449 | NdisAllocateSpinLock(&pAd->BulkOutLock[1]); | ||
450 | NdisAllocateSpinLock(&pAd->BulkOutLock[2]); | ||
451 | NdisAllocateSpinLock(&pAd->BulkOutLock[3]); | ||
452 | NdisAllocateSpinLock(&pAd->BulkOutLock[4]); | ||
453 | NdisAllocateSpinLock(&pAd->BulkOutLock[5]); | ||
454 | NdisAllocateSpinLock(&pAd->BulkInLock); | ||
455 | |||
456 | for (num = 0; num < NUM_OF_TX_RING; num++) { | ||
457 | NdisAllocateSpinLock(&pAd->TxContextQueueLock[num]); | ||
458 | } | ||
459 | |||
460 | /* NdisAllocateSpinLock(&pAd->MemLock); // Not used in RT28XX */ | ||
461 | |||
462 | /* NdisAllocateSpinLock(&pAd->MacTabLock); // init it in UserCfgInit() */ | ||
463 | /* NdisAllocateSpinLock(&pAd->BATabLock); // init it in BATableInit() */ | ||
464 | |||
465 | /* for(num=0; num<MAX_LEN_OF_BA_REC_TABLE; num++) */ | ||
466 | /* { */ | ||
467 | /* NdisAllocateSpinLock(&pAd->BATable.BARecEntry[num].RxReRingLock); */ | ||
468 | /* } */ | ||
469 | |||
470 | /* */ | ||
471 | /* Init Mac Table */ | ||
472 | /* */ | ||
473 | /* MacTableInitialize(pAd); */ | ||
474 | |||
475 | /* */ | ||
476 | /* Init send data structures and related parameters */ | ||
477 | /* */ | ||
478 | Status = NICInitTransmit(pAd); | ||
479 | if (Status != NDIS_STATUS_SUCCESS) | ||
480 | break; | ||
481 | |||
482 | /* */ | ||
483 | /* Init receive data structures and related parameters */ | ||
484 | /* */ | ||
485 | Status = NICInitRecv(pAd); | ||
486 | if (Status != NDIS_STATUS_SUCCESS) | ||
487 | break; | ||
488 | |||
489 | pAd->PendingIoCount = 1; | ||
490 | |||
491 | } while (FALSE); | ||
492 | |||
493 | NdisZeroMemory(&pAd->FragFrame, sizeof(struct rt_fragment_frame)); | ||
494 | pAd->FragFrame.pFragPacket = | ||
495 | RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); | ||
496 | |||
497 | if (pAd->FragFrame.pFragPacket == NULL) { | ||
498 | Status = NDIS_STATUS_RESOURCES; | ||
499 | } | ||
500 | |||
501 | DBGPRINT_S(Status, | ||
502 | ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status)); | ||
503 | return Status; | ||
504 | } | ||
505 | |||
506 | /* | ||
507 | ======================================================================== | ||
508 | Routine Description: | ||
509 | Calls USB_InterfaceStop and frees memory allocated for the URBs | ||
510 | calls NdisMDeregisterDevice and frees the memory | ||
511 | allocated in VNetInitialize for the Adapter Object | ||
512 | |||
513 | Arguments: | ||
514 | *pAd the raxx interface data pointer | ||
515 | |||
516 | Return Value: | ||
517 | None | ||
518 | |||
519 | Note: | ||
520 | ======================================================================== | ||
521 | */ | ||
522 | void RTMPFreeTxRxRingMemory(struct rt_rtmp_adapter *pAd) | ||
523 | { | ||
524 | #define LM_URB_FREE(pObj, Context, BufferSize) \ | ||
525 | if (NULL != Context->pUrb) { \ | ||
526 | RTUSB_UNLINK_URB(Context->pUrb); \ | ||
527 | RTUSB_FREE_URB(Context->pUrb); \ | ||
528 | Context->pUrb = NULL; } \ | ||
529 | if (NULL != Context->TransferBuffer) { \ | ||
530 | RTUSB_URB_FREE_BUFFER(pObj->pUsb_Dev, BufferSize, \ | ||
531 | Context->TransferBuffer, \ | ||
532 | Context->data_dma); \ | ||
533 | Context->TransferBuffer = NULL; } | ||
534 | |||
535 | u32 i, acidx; | ||
536 | struct rt_tx_context *pNullContext = &pAd->NullContext; | ||
537 | struct rt_tx_context *pPsPollContext = &pAd->PsPollContext; | ||
538 | struct rt_tx_context *pRTSContext = &pAd->RTSContext; | ||
539 | /* struct rt_ht_tx_context *pHTTXContext; */ | ||
540 | /*PRTMP_REORDERBUF pReorderBuf; */ | ||
541 | struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie; | ||
542 | /* struct rt_rtmp_tx_ring *pTxRing; */ | ||
543 | |||
544 | DBGPRINT(RT_DEBUG_ERROR, ("---> RTMPFreeTxRxRingMemory\n")); | ||
545 | pObj = pObj; | ||
546 | |||
547 | /* Free all resources for the RECEIVE buffer queue. */ | ||
548 | for (i = 0; i < (RX_RING_SIZE); i++) { | ||
549 | struct rt_rx_context *pRxContext = &(pAd->RxContext[i]); | ||
550 | if (pRxContext) | ||
551 | LM_URB_FREE(pObj, pRxContext, MAX_RXBULK_SIZE); | ||
552 | } | ||
553 | |||
554 | /* Free PsPoll frame resource */ | ||
555 | LM_URB_FREE(pObj, pPsPollContext, sizeof(struct rt_tx_buffer)); | ||
556 | |||
557 | /* Free NULL frame resource */ | ||
558 | LM_URB_FREE(pObj, pNullContext, sizeof(struct rt_tx_buffer)); | ||
559 | |||
560 | /* Free RTS frame resource */ | ||
561 | LM_URB_FREE(pObj, pRTSContext, sizeof(struct rt_tx_buffer)); | ||
562 | |||
563 | /* Free beacon frame resource */ | ||
564 | for (i = 0; i < BEACON_RING_SIZE; i++) { | ||
565 | struct rt_tx_context *pBeaconContext = &(pAd->BeaconContext[i]); | ||
566 | if (pBeaconContext) | ||
567 | LM_URB_FREE(pObj, pBeaconContext, sizeof(struct rt_tx_buffer)); | ||
568 | } | ||
569 | |||
570 | /* Free mgmt frame resource */ | ||
571 | for (i = 0; i < MGMT_RING_SIZE; i++) { | ||
572 | struct rt_tx_context *pMLMEContext = | ||
573 | (struct rt_tx_context *)pAd->MgmtRing.Cell[i].AllocVa; | ||
574 | /*LM_URB_FREE(pObj, pMLMEContext, sizeof(struct rt_tx_buffer)); */ | ||
575 | if (NULL != pAd->MgmtRing.Cell[i].pNdisPacket) { | ||
576 | RTMPFreeNdisPacket(pAd, | ||
577 | pAd->MgmtRing.Cell[i].pNdisPacket); | ||
578 | pAd->MgmtRing.Cell[i].pNdisPacket = NULL; | ||
579 | pMLMEContext->TransferBuffer = NULL; | ||
580 | } | ||
581 | |||
582 | if (pMLMEContext) { | ||
583 | if (NULL != pMLMEContext->pUrb) { | ||
584 | RTUSB_UNLINK_URB(pMLMEContext->pUrb); | ||
585 | RTUSB_FREE_URB(pMLMEContext->pUrb); | ||
586 | pMLMEContext->pUrb = NULL; | ||
587 | } | ||
588 | } | ||
589 | } | ||
590 | if (pAd->MgmtDescRing.AllocVa) | ||
591 | os_free_mem(pAd, pAd->MgmtDescRing.AllocVa); | ||
592 | |||
593 | /* Free Tx frame resource */ | ||
594 | for (acidx = 0; acidx < 4; acidx++) { | ||
595 | struct rt_ht_tx_context *pHTTXContext = &(pAd->TxContext[acidx]); | ||
596 | if (pHTTXContext) | ||
597 | LM_URB_FREE(pObj, pHTTXContext, sizeof(struct rt_httx_buffer)); | ||
598 | } | ||
599 | |||
600 | if (pAd->FragFrame.pFragPacket) | ||
601 | RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, | ||
602 | NDIS_STATUS_SUCCESS); | ||
603 | |||
604 | for (i = 0; i < 6; i++) { | ||
605 | NdisFreeSpinLock(&pAd->BulkOutLock[i]); | ||
606 | } | ||
607 | |||
608 | NdisFreeSpinLock(&pAd->BulkInLock); | ||
609 | NdisFreeSpinLock(&pAd->MLMEBulkOutLock); | ||
610 | |||
611 | NdisFreeSpinLock(&pAd->CmdQLock); | ||
612 | /* Clear all pending bulk-out request flags. */ | ||
613 | RTUSB_CLEAR_BULK_FLAG(pAd, 0xffffffff); | ||
614 | |||
615 | /* NdisFreeSpinLock(&pAd->MacTabLock); */ | ||
616 | |||
617 | /* for(i=0; i<MAX_LEN_OF_BA_REC_TABLE; i++) */ | ||
618 | /* { */ | ||
619 | /* NdisFreeSpinLock(&pAd->BATable.BARecEntry[i].RxReRingLock); */ | ||
620 | /* } */ | ||
621 | |||
622 | DBGPRINT(RT_DEBUG_ERROR, ("<--- RTMPFreeTxRxRingMemory\n")); | ||
623 | } | ||
624 | |||
625 | /* | ||
626 | ======================================================================== | ||
627 | Routine Description: | ||
628 | Write WLAN MAC address to USB 2870. | ||
629 | |||
630 | Arguments: | ||
631 | pAd Pointer to our adapter | ||
632 | |||
633 | Return Value: | ||
634 | NDIS_STATUS_SUCCESS | ||
635 | |||
636 | Note: | ||
637 | ======================================================================== | ||
638 | */ | ||
639 | int RTUSBWriteHWMACAddress(struct rt_rtmp_adapter *pAd) | ||
640 | { | ||
641 | MAC_DW0_STRUC StaMacReg0; | ||
642 | MAC_DW1_STRUC StaMacReg1; | ||
643 | int Status = NDIS_STATUS_SUCCESS; | ||
644 | LARGE_INTEGER NOW; | ||
645 | |||
646 | /* initialize the random number generator */ | ||
647 | RTMP_GetCurrentSystemTime(&NOW); | ||
648 | |||
649 | if (pAd->bLocalAdminMAC != TRUE) { | ||
650 | pAd->CurrentAddress[0] = pAd->PermanentAddress[0]; | ||
651 | pAd->CurrentAddress[1] = pAd->PermanentAddress[1]; | ||
652 | pAd->CurrentAddress[2] = pAd->PermanentAddress[2]; | ||
653 | pAd->CurrentAddress[3] = pAd->PermanentAddress[3]; | ||
654 | pAd->CurrentAddress[4] = pAd->PermanentAddress[4]; | ||
655 | pAd->CurrentAddress[5] = pAd->PermanentAddress[5]; | ||
656 | } | ||
657 | /* Write New MAC address to MAC_CSR2 & MAC_CSR3 & let ASIC know our new MAC */ | ||
658 | StaMacReg0.field.Byte0 = pAd->CurrentAddress[0]; | ||
659 | StaMacReg0.field.Byte1 = pAd->CurrentAddress[1]; | ||
660 | StaMacReg0.field.Byte2 = pAd->CurrentAddress[2]; | ||
661 | StaMacReg0.field.Byte3 = pAd->CurrentAddress[3]; | ||
662 | StaMacReg1.field.Byte4 = pAd->CurrentAddress[4]; | ||
663 | StaMacReg1.field.Byte5 = pAd->CurrentAddress[5]; | ||
664 | StaMacReg1.field.U2MeMask = 0xff; | ||
665 | DBGPRINT_RAW(RT_DEBUG_TRACE, | ||
666 | ("Local MAC = %pM\n", pAd->CurrentAddress)); | ||
667 | |||
668 | RTUSBWriteMACRegister(pAd, MAC_ADDR_DW0, StaMacReg0.word); | ||
669 | RTUSBWriteMACRegister(pAd, MAC_ADDR_DW1, StaMacReg1.word); | ||
670 | return Status; | ||
671 | } | ||
672 | |||
673 | /* | ||
674 | ======================================================================== | ||
675 | Routine Description: | ||
676 | Disable DMA. | ||
677 | |||
678 | Arguments: | ||
679 | *pAd the raxx interface data pointer | ||
680 | |||
681 | Return Value: | ||
682 | None | ||
683 | |||
684 | Note: | ||
685 | ======================================================================== | ||
686 | */ | ||
687 | void RT28XXDMADisable(struct rt_rtmp_adapter *pAd) | ||
688 | { | ||
689 | /* no use */ | ||
690 | } | ||
691 | |||
692 | /* | ||
693 | ======================================================================== | ||
694 | Routine Description: | ||
695 | Enable DMA. | ||
696 | |||
697 | Arguments: | ||
698 | *pAd the raxx interface data pointer | ||
699 | |||
700 | Return Value: | ||
701 | None | ||
702 | |||
703 | Note: | ||
704 | ======================================================================== | ||
705 | */ | ||
706 | void RT28XXDMAEnable(struct rt_rtmp_adapter *pAd) | ||
707 | { | ||
708 | WPDMA_GLO_CFG_STRUC GloCfg; | ||
709 | USB_DMA_CFG_STRUC UsbCfg; | ||
710 | int i = 0; | ||
711 | |||
712 | RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4); | ||
713 | do { | ||
714 | RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); | ||
715 | if ((GloCfg.field.TxDMABusy == 0) | ||
716 | && (GloCfg.field.RxDMABusy == 0)) | ||
717 | break; | ||
718 | |||
719 | DBGPRINT(RT_DEBUG_TRACE, ("==> DMABusy\n")); | ||
720 | RTMPusecDelay(1000); | ||
721 | i++; | ||
722 | } while (i < 200); | ||
723 | |||
724 | RTMPusecDelay(50); | ||
725 | GloCfg.field.EnTXWriteBackDDONE = 1; | ||
726 | GloCfg.field.EnableRxDMA = 1; | ||
727 | GloCfg.field.EnableTxDMA = 1; | ||
728 | DBGPRINT(RT_DEBUG_TRACE, | ||
729 | ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word)); | ||
730 | RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); | ||
731 | |||
732 | UsbCfg.word = 0; | ||
733 | UsbCfg.field.phyclear = 0; | ||
734 | /* usb version is 1.1,do not use bulk in aggregation */ | ||
735 | if (pAd->BulkInMaxPacketSize == 512) | ||
736 | UsbCfg.field.RxBulkAggEn = 1; | ||
737 | /* for last packet, PBF might use more than limited, so minus 2 to prevent from error */ | ||
738 | UsbCfg.field.RxBulkAggLmt = (MAX_RXBULK_SIZE / 1024) - 3; | ||
739 | UsbCfg.field.RxBulkAggTOut = 0x80; /* 2006-10-18 */ | ||
740 | UsbCfg.field.RxBulkEn = 1; | ||
741 | UsbCfg.field.TxBulkEn = 1; | ||
742 | |||
743 | RTUSBWriteMACRegister(pAd, USB_DMA_CFG, UsbCfg.word); | ||
744 | |||
745 | } | ||
746 | |||
747 | /******************************************************************** | ||
748 | * | ||
749 | * 2870 Beacon Update Related functions. | ||
750 | * | ||
751 | ********************************************************************/ | ||
752 | |||
753 | /* | ||
754 | ======================================================================== | ||
755 | Routine Description: | ||
756 | Write Beacon buffer to Asic. | ||
757 | |||
758 | Arguments: | ||
759 | *pAd the raxx interface data pointer | ||
760 | |||
761 | Return Value: | ||
762 | None | ||
763 | |||
764 | Note: | ||
765 | ======================================================================== | ||
766 | */ | ||
767 | void RT28xx_UpdateBeaconToAsic(struct rt_rtmp_adapter *pAd, | ||
768 | int apidx, | ||
769 | unsigned long FrameLen, unsigned long UpdatePos) | ||
770 | { | ||
771 | u8 *pBeaconFrame = NULL; | ||
772 | u8 *ptr; | ||
773 | u32 i, padding; | ||
774 | struct rt_beacon_sync *pBeaconSync = pAd->CommonCfg.pBeaconSync; | ||
775 | u32 longValue; | ||
776 | /* u16 shortValue; */ | ||
777 | BOOLEAN bBcnReq = FALSE; | ||
778 | u8 bcn_idx = 0; | ||
779 | |||
780 | if (pBeaconFrame == NULL) { | ||
781 | DBGPRINT(RT_DEBUG_ERROR, ("pBeaconFrame is NULL!\n")); | ||
782 | return; | ||
783 | } | ||
784 | |||
785 | if (pBeaconSync == NULL) { | ||
786 | DBGPRINT(RT_DEBUG_ERROR, ("pBeaconSync is NULL!\n")); | ||
787 | return; | ||
788 | } | ||
789 | /*if ((pAd->WdsTab.Mode == WDS_BRIDGE_MODE) || */ | ||
790 | /* ((pAd->ApCfg.MBSSID[apidx].MSSIDDev == NULL) || !(pAd->ApCfg.MBSSID[apidx].MSSIDDev->flags & IFF_UP)) */ | ||
791 | /* ) */ | ||
792 | if (bBcnReq == FALSE) { | ||
793 | /* when the ra interface is down, do not send its beacon frame */ | ||
794 | /* clear all zero */ | ||
795 | for (i = 0; i < TXWI_SIZE; i += 4) { | ||
796 | RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, | ||
797 | 0x00); | ||
798 | } | ||
799 | pBeaconSync->BeaconBitMap &= | ||
800 | (~(BEACON_BITMAP_MASK & (1 << bcn_idx))); | ||
801 | NdisZeroMemory(pBeaconSync->BeaconTxWI[bcn_idx], TXWI_SIZE); | ||
802 | } else { | ||
803 | ptr = (u8 *)& pAd->BeaconTxWI; | ||
804 | if (NdisEqualMemory(pBeaconSync->BeaconTxWI[bcn_idx], &pAd->BeaconTxWI, TXWI_SIZE) == FALSE) { /* If BeaconTxWI changed, we need to rewrite the TxWI for the Beacon frames. */ | ||
805 | pBeaconSync->BeaconBitMap &= | ||
806 | (~(BEACON_BITMAP_MASK & (1 << bcn_idx))); | ||
807 | NdisMoveMemory(pBeaconSync->BeaconTxWI[bcn_idx], | ||
808 | &pAd->BeaconTxWI, TXWI_SIZE); | ||
809 | } | ||
810 | |||
811 | if ((pBeaconSync->BeaconBitMap & (1 << bcn_idx)) != | ||
812 | (1 << bcn_idx)) { | ||
813 | for (i = 0; i < TXWI_SIZE; i += 4) /* 16-byte TXWI field */ | ||
814 | { | ||
815 | longValue = | ||
816 | *ptr + (*(ptr + 1) << 8) + | ||
817 | (*(ptr + 2) << 16) + (*(ptr + 3) << 24); | ||
818 | RTMP_IO_WRITE32(pAd, | ||
819 | pAd->BeaconOffset[bcn_idx] + i, | ||
820 | longValue); | ||
821 | ptr += 4; | ||
822 | } | ||
823 | } | ||
824 | |||
825 | ptr = pBeaconSync->BeaconBuf[bcn_idx]; | ||
826 | padding = (FrameLen & 0x01); | ||
827 | NdisZeroMemory((u8 *)(pBeaconFrame + FrameLen), padding); | ||
828 | FrameLen += padding; | ||
829 | for (i = 0; i < FrameLen /*HW_BEACON_OFFSET */ ; i += 2) { | ||
830 | if (NdisEqualMemory(ptr, pBeaconFrame, 2) == FALSE) { | ||
831 | NdisMoveMemory(ptr, pBeaconFrame, 2); | ||
832 | /*shortValue = *ptr + (*(ptr+1)<<8); */ | ||
833 | /*RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, shortValue); */ | ||
834 | RTUSBMultiWrite(pAd, | ||
835 | pAd->BeaconOffset[bcn_idx] + | ||
836 | TXWI_SIZE + i, ptr, 2); | ||
837 | } | ||
838 | ptr += 2; | ||
839 | pBeaconFrame += 2; | ||
840 | } | ||
841 | |||
842 | pBeaconSync->BeaconBitMap |= (1 << bcn_idx); | ||
843 | |||
844 | /* For AP interface, set the DtimBitOn so that we can send Bcast/Mcast frame out after this beacon frame. */ | ||
845 | } | ||
846 | |||
847 | } | ||
848 | |||
849 | void RTUSBBssBeaconStop(struct rt_rtmp_adapter *pAd) | ||
850 | { | ||
851 | struct rt_beacon_sync *pBeaconSync; | ||
852 | int i, offset; | ||
853 | BOOLEAN Cancelled = TRUE; | ||
854 | |||
855 | pBeaconSync = pAd->CommonCfg.pBeaconSync; | ||
856 | if (pBeaconSync && pBeaconSync->EnableBeacon) { | ||
857 | int NumOfBcn; | ||
858 | |||
859 | { | ||
860 | NumOfBcn = MAX_MESH_NUM; | ||
861 | } | ||
862 | |||
863 | RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled); | ||
864 | |||
865 | for (i = 0; i < NumOfBcn; i++) { | ||
866 | NdisZeroMemory(pBeaconSync->BeaconBuf[i], | ||
867 | HW_BEACON_OFFSET); | ||
868 | NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE); | ||
869 | |||
870 | for (offset = 0; offset < HW_BEACON_OFFSET; offset += 4) | ||
871 | RTMP_IO_WRITE32(pAd, | ||
872 | pAd->BeaconOffset[i] + offset, | ||
873 | 0x00); | ||
874 | |||
875 | pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0; | ||
876 | pBeaconSync->TimIELocationInBeacon[i] = 0; | ||
877 | } | ||
878 | pBeaconSync->BeaconBitMap = 0; | ||
879 | pBeaconSync->DtimBitOn = 0; | ||
880 | } | ||
881 | } | ||
882 | |||
883 | void RTUSBBssBeaconStart(struct rt_rtmp_adapter *pAd) | ||
884 | { | ||
885 | int apidx; | ||
886 | struct rt_beacon_sync *pBeaconSync; | ||
887 | /* LARGE_INTEGER tsfTime, deltaTime; */ | ||
888 | |||
889 | pBeaconSync = pAd->CommonCfg.pBeaconSync; | ||
890 | if (pBeaconSync && pBeaconSync->EnableBeacon) { | ||
891 | int NumOfBcn; | ||
892 | |||
893 | { | ||
894 | NumOfBcn = MAX_MESH_NUM; | ||
895 | } | ||
896 | |||
897 | for (apidx = 0; apidx < NumOfBcn; apidx++) { | ||
898 | u8 CapabilityInfoLocationInBeacon = 0; | ||
899 | u8 TimIELocationInBeacon = 0; | ||
900 | |||
901 | NdisZeroMemory(pBeaconSync->BeaconBuf[apidx], | ||
902 | HW_BEACON_OFFSET); | ||
903 | pBeaconSync->CapabilityInfoLocationInBeacon[apidx] = | ||
904 | CapabilityInfoLocationInBeacon; | ||
905 | pBeaconSync->TimIELocationInBeacon[apidx] = | ||
906 | TimIELocationInBeacon; | ||
907 | NdisZeroMemory(pBeaconSync->BeaconTxWI[apidx], | ||
908 | TXWI_SIZE); | ||
909 | } | ||
910 | pBeaconSync->BeaconBitMap = 0; | ||
911 | pBeaconSync->DtimBitOn = 0; | ||
912 | pAd->CommonCfg.BeaconUpdateTimer.Repeat = TRUE; | ||
913 | |||
914 | pAd->CommonCfg.BeaconAdjust = 0; | ||
915 | pAd->CommonCfg.BeaconFactor = | ||
916 | 0xffffffff / (pAd->CommonCfg.BeaconPeriod << 10); | ||
917 | pAd->CommonCfg.BeaconRemain = | ||
918 | (0xffffffff % (pAd->CommonCfg.BeaconPeriod << 10)) + 1; | ||
919 | DBGPRINT(RT_DEBUG_TRACE, | ||
920 | ("RTUSBBssBeaconStart:BeaconFactor=%d, BeaconRemain=%d!\n", | ||
921 | pAd->CommonCfg.BeaconFactor, | ||
922 | pAd->CommonCfg.BeaconRemain)); | ||
923 | RTMPSetTimer(&pAd->CommonCfg.BeaconUpdateTimer, | ||
924 | 10 /*pAd->CommonCfg.BeaconPeriod */ ); | ||
925 | |||
926 | } | ||
927 | } | ||
928 | |||
929 | void RTUSBBssBeaconInit(struct rt_rtmp_adapter *pAd) | ||
930 | { | ||
931 | struct rt_beacon_sync *pBeaconSync; | ||
932 | int i; | ||
933 | |||
934 | os_alloc_mem(pAd, (u8 **) (&pAd->CommonCfg.pBeaconSync), | ||
935 | sizeof(struct rt_beacon_sync)); | ||
936 | /*NdisAllocMemory(pAd->CommonCfg.pBeaconSync, sizeof(struct rt_beacon_sync), MEM_ALLOC_FLAG); */ | ||
937 | if (pAd->CommonCfg.pBeaconSync) { | ||
938 | pBeaconSync = pAd->CommonCfg.pBeaconSync; | ||
939 | NdisZeroMemory(pBeaconSync, sizeof(struct rt_beacon_sync)); | ||
940 | for (i = 0; i < HW_BEACON_MAX_COUNT; i++) { | ||
941 | NdisZeroMemory(pBeaconSync->BeaconBuf[i], | ||
942 | HW_BEACON_OFFSET); | ||
943 | pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0; | ||
944 | pBeaconSync->TimIELocationInBeacon[i] = 0; | ||
945 | NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE); | ||
946 | } | ||
947 | pBeaconSync->BeaconBitMap = 0; | ||
948 | |||
949 | /*RTMPInitTimer(pAd, &pAd->CommonCfg.BeaconUpdateTimer, GET_TIMER_FUNCTION(BeaconUpdateExec), pAd, TRUE); */ | ||
950 | pBeaconSync->EnableBeacon = TRUE; | ||
951 | } | ||
952 | } | ||
953 | |||
954 | void RTUSBBssBeaconExit(struct rt_rtmp_adapter *pAd) | ||
955 | { | ||
956 | struct rt_beacon_sync *pBeaconSync; | ||
957 | BOOLEAN Cancelled = TRUE; | ||
958 | int i; | ||
959 | |||
960 | if (pAd->CommonCfg.pBeaconSync) { | ||
961 | pBeaconSync = pAd->CommonCfg.pBeaconSync; | ||
962 | pBeaconSync->EnableBeacon = FALSE; | ||
963 | RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled); | ||
964 | pBeaconSync->BeaconBitMap = 0; | ||
965 | |||
966 | for (i = 0; i < HW_BEACON_MAX_COUNT; i++) { | ||
967 | NdisZeroMemory(pBeaconSync->BeaconBuf[i], | ||
968 | HW_BEACON_OFFSET); | ||
969 | pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0; | ||
970 | pBeaconSync->TimIELocationInBeacon[i] = 0; | ||
971 | NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE); | ||
972 | } | ||
973 | |||
974 | os_free_mem(pAd, pAd->CommonCfg.pBeaconSync); | ||
975 | pAd->CommonCfg.pBeaconSync = NULL; | ||
976 | } | ||
977 | } | ||
978 | |||
979 | /* | ||
980 | ======================================================================== | ||
981 | Routine Description: | ||
982 | For device work as AP mode but didn't have TBTT interrupt event, we need a mechanism | ||
983 | to update the beacon context in each Beacon interval. Here we use a periodical timer | ||
984 | to simulate the TBTT interrupt to handle the beacon context update. | ||
985 | |||
986 | Arguments: | ||
987 | SystemSpecific1 - Not used. | ||
988 | FunctionContext - Pointer to our Adapter context. | ||
989 | SystemSpecific2 - Not used. | ||
990 | SystemSpecific3 - Not used. | ||
991 | |||
992 | Return Value: | ||
993 | None | ||
994 | |||
995 | ======================================================================== | ||
996 | */ | ||
997 | void BeaconUpdateExec(void *SystemSpecific1, | ||
998 | void *FunctionContext, | ||
999 | void *SystemSpecific2, void *SystemSpecific3) | ||
1000 | { | ||
1001 | struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; | ||
1002 | LARGE_INTEGER tsfTime_a; /*, tsfTime_b, deltaTime_exp, deltaTime_ab; */ | ||
1003 | u32 delta, delta2MS, period2US, remain, remain_low, remain_high; | ||
1004 | /* BOOLEAN positive; */ | ||
1005 | |||
1006 | if (pAd->CommonCfg.IsUpdateBeacon == TRUE) { | ||
1007 | ReSyncBeaconTime(pAd); | ||
1008 | |||
1009 | } | ||
1010 | |||
1011 | RTMP_IO_READ32(pAd, TSF_TIMER_DW0, &tsfTime_a.u.LowPart); | ||
1012 | RTMP_IO_READ32(pAd, TSF_TIMER_DW1, &tsfTime_a.u.HighPart); | ||
1013 | |||
1014 | /*positive=getDeltaTime(tsfTime_a, expectedTime, &deltaTime_exp); */ | ||
1015 | period2US = (pAd->CommonCfg.BeaconPeriod << 10); | ||
1016 | remain_high = pAd->CommonCfg.BeaconRemain * tsfTime_a.u.HighPart; | ||
1017 | remain_low = tsfTime_a.u.LowPart % (pAd->CommonCfg.BeaconPeriod << 10); | ||
1018 | remain = | ||
1019 | (remain_high + remain_low) % (pAd->CommonCfg.BeaconPeriod << 10); | ||
1020 | delta = (pAd->CommonCfg.BeaconPeriod << 10) - remain; | ||
1021 | |||
1022 | delta2MS = (delta >> 10); | ||
1023 | if (delta2MS > 150) { | ||
1024 | pAd->CommonCfg.BeaconUpdateTimer.TimerValue = 100; | ||
1025 | pAd->CommonCfg.IsUpdateBeacon = FALSE; | ||
1026 | } else { | ||
1027 | pAd->CommonCfg.BeaconUpdateTimer.TimerValue = delta2MS + 10; | ||
1028 | pAd->CommonCfg.IsUpdateBeacon = TRUE; | ||
1029 | } | ||
1030 | |||
1031 | } | ||
1032 | |||
1033 | /******************************************************************** | ||
1034 | * | ||
1035 | * 2870 Radio on/off Related functions. | ||
1036 | * | ||
1037 | ********************************************************************/ | ||
1038 | void RT28xxUsbMlmeRadioOn(struct rt_rtmp_adapter *pAd) | ||
1039 | { | ||
1040 | struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps; | ||
1041 | |||
1042 | DBGPRINT(RT_DEBUG_TRACE, ("RT28xxUsbMlmeRadioOn()\n")); | ||
1043 | |||
1044 | if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) | ||
1045 | return; | ||
1046 | |||
1047 | { | ||
1048 | AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02); | ||
1049 | RTMPusecDelay(10000); | ||
1050 | } | ||
1051 | /*NICResetFromError(pAd); */ | ||
1052 | |||
1053 | /* Enable Tx/Rx */ | ||
1054 | RTMPEnableRxTx(pAd); | ||
1055 | |||
1056 | if (pChipOps->AsicReverseRfFromSleepMode) | ||
1057 | pChipOps->AsicReverseRfFromSleepMode(pAd); | ||
1058 | |||
1059 | /* Clear Radio off flag */ | ||
1060 | RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); | ||
1061 | |||
1062 | RTUSBBulkReceive(pAd); | ||
1063 | |||
1064 | /* Set LED */ | ||
1065 | RTMPSetLED(pAd, LED_RADIO_ON); | ||
1066 | } | ||
1067 | |||
1068 | void RT28xxUsbMlmeRadioOFF(struct rt_rtmp_adapter *pAd) | ||
1069 | { | ||
1070 | WPDMA_GLO_CFG_STRUC GloCfg; | ||
1071 | u32 Value, i; | ||
1072 | |||
1073 | DBGPRINT(RT_DEBUG_TRACE, ("RT28xxUsbMlmeRadioOFF()\n")); | ||
1074 | |||
1075 | if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) | ||
1076 | return; | ||
1077 | |||
1078 | /* Clear PMKID cache. */ | ||
1079 | pAd->StaCfg.SavedPMKNum = 0; | ||
1080 | RTMPZeroMemory(pAd->StaCfg.SavedPMK, (PMKID_NO * sizeof(struct rt_bssid_info))); | ||
1081 | |||
1082 | /* Link down first if any association exists */ | ||
1083 | if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) { | ||
1084 | if (INFRA_ON(pAd) || ADHOC_ON(pAd)) { | ||
1085 | struct rt_mlme_disassoc_req DisReq; | ||
1086 | struct rt_mlme_queue_elem *pMsgElem = | ||
1087 | kmalloc(sizeof(struct rt_mlme_queue_elem), | ||
1088 | MEM_ALLOC_FLAG); | ||
1089 | |||
1090 | if (pMsgElem) { | ||
1091 | COPY_MAC_ADDR(&DisReq.Addr, | ||
1092 | pAd->CommonCfg.Bssid); | ||
1093 | DisReq.Reason = REASON_DISASSOC_STA_LEAVING; | ||
1094 | |||
1095 | pMsgElem->Machine = ASSOC_STATE_MACHINE; | ||
1096 | pMsgElem->MsgType = MT2_MLME_DISASSOC_REQ; | ||
1097 | pMsgElem->MsgLen = | ||
1098 | sizeof(struct rt_mlme_disassoc_req); | ||
1099 | NdisMoveMemory(pMsgElem->Msg, &DisReq, | ||
1100 | sizeof | ||
1101 | (struct rt_mlme_disassoc_req)); | ||
1102 | |||
1103 | MlmeDisassocReqAction(pAd, pMsgElem); | ||
1104 | kfree(pMsgElem); | ||
1105 | |||
1106 | RTMPusecDelay(1000); | ||
1107 | } | ||
1108 | } | ||
1109 | } | ||
1110 | /* Set Radio off flag */ | ||
1111 | RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); | ||
1112 | |||
1113 | { | ||
1114 | /* Link down first if any association exists */ | ||
1115 | if (INFRA_ON(pAd) || ADHOC_ON(pAd)) | ||
1116 | LinkDown(pAd, FALSE); | ||
1117 | RTMPusecDelay(10000); | ||
1118 | |||
1119 | /*========================================== */ | ||
1120 | /* Clean up old bss table */ | ||
1121 | BssTableInit(&pAd->ScanTab); | ||
1122 | } | ||
1123 | |||
1124 | /* Set LED */ | ||
1125 | RTMPSetLED(pAd, LED_RADIO_OFF); | ||
1126 | |||
1127 | if (pAd->CommonCfg.BBPCurrentBW == BW_40) { | ||
1128 | /* Must using 40MHz. */ | ||
1129 | AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel); | ||
1130 | } else { | ||
1131 | /* Must using 20MHz. */ | ||
1132 | AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel); | ||
1133 | } | ||
1134 | |||
1135 | /* Disable Tx/Rx DMA */ | ||
1136 | RTUSBReadMACRegister(pAd, WPDMA_GLO_CFG, &GloCfg.word); /* disable DMA */ | ||
1137 | GloCfg.field.EnableTxDMA = 0; | ||
1138 | GloCfg.field.EnableRxDMA = 0; | ||
1139 | RTUSBWriteMACRegister(pAd, WPDMA_GLO_CFG, GloCfg.word); /* abort all TX rings */ | ||
1140 | |||
1141 | /* Waiting for DMA idle */ | ||
1142 | i = 0; | ||
1143 | do { | ||
1144 | RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); | ||
1145 | if ((GloCfg.field.TxDMABusy == 0) | ||
1146 | && (GloCfg.field.RxDMABusy == 0)) | ||
1147 | break; | ||
1148 | |||
1149 | RTMPusecDelay(1000); | ||
1150 | } while (i++ < 100); | ||
1151 | |||
1152 | /* Disable MAC Tx/Rx */ | ||
1153 | RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); | ||
1154 | Value &= (0xfffffff3); | ||
1155 | RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); | ||
1156 | |||
1157 | { | ||
1158 | AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02); | ||
1159 | } | ||
1160 | } | ||
1161 | |||
1162 | #endif /* RTMP_MAC_USB // */ | ||
diff --git a/drivers/staging/rt2860/common/cmm_sanity.c b/drivers/staging/rt2860/common/cmm_sanity.c deleted file mode 100644 index 3bfb4ad00c1..00000000000 --- a/drivers/staging/rt2860/common/cmm_sanity.c +++ /dev/null | |||
@@ -1,1205 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | |||
27 | Module Name: | ||
28 | sanity.c | ||
29 | |||
30 | Abstract: | ||
31 | |||
32 | Revision History: | ||
33 | Who When What | ||
34 | -------- ---------- ---------------------------------------------- | ||
35 | John Chang 2004-09-01 add WMM support | ||
36 | */ | ||
37 | #include "../rt_config.h" | ||
38 | |||
39 | extern u8 CISCO_OUI[]; | ||
40 | |||
41 | extern u8 WPA_OUI[]; | ||
42 | extern u8 RSN_OUI[]; | ||
43 | extern u8 WME_INFO_ELEM[]; | ||
44 | extern u8 WME_PARM_ELEM[]; | ||
45 | extern u8 Ccx2QosInfo[]; | ||
46 | extern u8 RALINK_OUI[]; | ||
47 | extern u8 BROADCOM_OUI[]; | ||
48 | extern u8 WPS_OUI[]; | ||
49 | |||
50 | /* | ||
51 | ========================================================================== | ||
52 | Description: | ||
53 | MLME message sanity check | ||
54 | Return: | ||
55 | TRUE if all parameters are OK, FALSE otherwise | ||
56 | |||
57 | IRQL = DISPATCH_LEVEL | ||
58 | |||
59 | ========================================================================== | ||
60 | */ | ||
61 | BOOLEAN MlmeAddBAReqSanity(struct rt_rtmp_adapter *pAd, | ||
62 | void * Msg, unsigned long MsgLen, u8 *pAddr2) | ||
63 | { | ||
64 | struct rt_mlme_addba_req *pInfo; | ||
65 | |||
66 | pInfo = (struct rt_mlme_addba_req *)Msg; | ||
67 | |||
68 | if ((MsgLen != sizeof(struct rt_mlme_addba_req))) { | ||
69 | DBGPRINT(RT_DEBUG_TRACE, | ||
70 | ("MlmeAddBAReqSanity fail - message length not correct.\n")); | ||
71 | return FALSE; | ||
72 | } | ||
73 | |||
74 | if ((pInfo->Wcid >= MAX_LEN_OF_MAC_TABLE)) { | ||
75 | DBGPRINT(RT_DEBUG_TRACE, | ||
76 | ("MlmeAddBAReqSanity fail - The peer Mac is not associated yet.\n")); | ||
77 | return FALSE; | ||
78 | } | ||
79 | |||
80 | if ((pInfo->pAddr[0] & 0x01) == 0x01) { | ||
81 | DBGPRINT(RT_DEBUG_TRACE, | ||
82 | ("MlmeAddBAReqSanity fail - broadcast address not support BA\n")); | ||
83 | return FALSE; | ||
84 | } | ||
85 | |||
86 | return TRUE; | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | ========================================================================== | ||
91 | Description: | ||
92 | MLME message sanity check | ||
93 | Return: | ||
94 | TRUE if all parameters are OK, FALSE otherwise | ||
95 | |||
96 | IRQL = DISPATCH_LEVEL | ||
97 | |||
98 | ========================================================================== | ||
99 | */ | ||
100 | BOOLEAN MlmeDelBAReqSanity(struct rt_rtmp_adapter *pAd, void * Msg, unsigned long MsgLen) | ||
101 | { | ||
102 | struct rt_mlme_delba_req *pInfo; | ||
103 | pInfo = (struct rt_mlme_delba_req *)Msg; | ||
104 | |||
105 | if ((MsgLen != sizeof(struct rt_mlme_delba_req))) { | ||
106 | DBGPRINT(RT_DEBUG_ERROR, | ||
107 | ("MlmeDelBAReqSanity fail - message length not correct.\n")); | ||
108 | return FALSE; | ||
109 | } | ||
110 | |||
111 | if ((pInfo->Wcid >= MAX_LEN_OF_MAC_TABLE)) { | ||
112 | DBGPRINT(RT_DEBUG_ERROR, | ||
113 | ("MlmeDelBAReqSanity fail - The peer Mac is not associated yet.\n")); | ||
114 | return FALSE; | ||
115 | } | ||
116 | |||
117 | if ((pInfo->TID & 0xf0)) { | ||
118 | DBGPRINT(RT_DEBUG_ERROR, | ||
119 | ("MlmeDelBAReqSanity fail - The peer TID is incorrect.\n")); | ||
120 | return FALSE; | ||
121 | } | ||
122 | |||
123 | if (NdisEqualMemory | ||
124 | (pAd->MacTab.Content[pInfo->Wcid].Addr, pInfo->Addr, | ||
125 | MAC_ADDR_LEN) == 0) { | ||
126 | DBGPRINT(RT_DEBUG_ERROR, | ||
127 | ("MlmeDelBAReqSanity fail - the peer addr dosen't exist.\n")); | ||
128 | return FALSE; | ||
129 | } | ||
130 | |||
131 | return TRUE; | ||
132 | } | ||
133 | |||
134 | BOOLEAN PeerAddBAReqActionSanity(struct rt_rtmp_adapter *pAd, | ||
135 | void * pMsg, | ||
136 | unsigned long MsgLen, u8 *pAddr2) | ||
137 | { | ||
138 | struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *) pMsg; | ||
139 | struct rt_frame_addba_req * pAddFrame; | ||
140 | pAddFrame = (struct rt_frame_addba_req *) (pMsg); | ||
141 | if (MsgLen < (sizeof(struct rt_frame_addba_req))) { | ||
142 | DBGPRINT(RT_DEBUG_ERROR, | ||
143 | ("PeerAddBAReqActionSanity: ADDBA Request frame length size = %ld incorrect\n", | ||
144 | MsgLen)); | ||
145 | return FALSE; | ||
146 | } | ||
147 | /* we support immediate BA. */ | ||
148 | *(u16 *) (&pAddFrame->BaParm) = | ||
149 | cpu2le16(*(u16 *) (&pAddFrame->BaParm)); | ||
150 | pAddFrame->TimeOutValue = cpu2le16(pAddFrame->TimeOutValue); | ||
151 | pAddFrame->BaStartSeq.word = cpu2le16(pAddFrame->BaStartSeq.word); | ||
152 | |||
153 | if (pAddFrame->BaParm.BAPolicy != IMMED_BA) { | ||
154 | DBGPRINT(RT_DEBUG_ERROR, | ||
155 | ("PeerAddBAReqActionSanity: ADDBA Request Ba Policy[%d] not support\n", | ||
156 | pAddFrame->BaParm.BAPolicy)); | ||
157 | DBGPRINT(RT_DEBUG_ERROR, | ||
158 | ("ADDBA Request. tid=%x, Bufsize=%x, AMSDUSupported=%x \n", | ||
159 | pAddFrame->BaParm.TID, pAddFrame->BaParm.BufSize, | ||
160 | pAddFrame->BaParm.AMSDUSupported)); | ||
161 | return FALSE; | ||
162 | } | ||
163 | /* we support immediate BA. */ | ||
164 | if (pAddFrame->BaParm.TID & 0xfff0) { | ||
165 | DBGPRINT(RT_DEBUG_ERROR, | ||
166 | ("PeerAddBAReqActionSanity: ADDBA Request incorrect TID = %d\n", | ||
167 | pAddFrame->BaParm.TID)); | ||
168 | return FALSE; | ||
169 | } | ||
170 | COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); | ||
171 | return TRUE; | ||
172 | } | ||
173 | |||
174 | BOOLEAN PeerAddBARspActionSanity(struct rt_rtmp_adapter *pAd, | ||
175 | void * pMsg, unsigned long MsgLen) | ||
176 | { | ||
177 | struct rt_frame_addba_rsp * pAddFrame; | ||
178 | |||
179 | pAddFrame = (struct rt_frame_addba_rsp *) (pMsg); | ||
180 | if (MsgLen < (sizeof(struct rt_frame_addba_rsp))) { | ||
181 | DBGPRINT(RT_DEBUG_ERROR, | ||
182 | ("PeerAddBARspActionSanity: ADDBA Response frame length size = %ld incorrect\n", | ||
183 | MsgLen)); | ||
184 | return FALSE; | ||
185 | } | ||
186 | /* we support immediate BA. */ | ||
187 | *(u16 *) (&pAddFrame->BaParm) = | ||
188 | cpu2le16(*(u16 *) (&pAddFrame->BaParm)); | ||
189 | pAddFrame->StatusCode = cpu2le16(pAddFrame->StatusCode); | ||
190 | pAddFrame->TimeOutValue = cpu2le16(pAddFrame->TimeOutValue); | ||
191 | |||
192 | if (pAddFrame->BaParm.BAPolicy != IMMED_BA) { | ||
193 | DBGPRINT(RT_DEBUG_ERROR, | ||
194 | ("PeerAddBAReqActionSanity: ADDBA Response Ba Policy[%d] not support\n", | ||
195 | pAddFrame->BaParm.BAPolicy)); | ||
196 | return FALSE; | ||
197 | } | ||
198 | /* we support immediate BA. */ | ||
199 | if (pAddFrame->BaParm.TID & 0xfff0) { | ||
200 | DBGPRINT(RT_DEBUG_ERROR, | ||
201 | ("PeerAddBARspActionSanity: ADDBA Response incorrect TID = %d\n", | ||
202 | pAddFrame->BaParm.TID)); | ||
203 | return FALSE; | ||
204 | } | ||
205 | return TRUE; | ||
206 | |||
207 | } | ||
208 | |||
209 | BOOLEAN PeerDelBAActionSanity(struct rt_rtmp_adapter *pAd, | ||
210 | u8 Wcid, void * pMsg, unsigned long MsgLen) | ||
211 | { | ||
212 | /*struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *)pMsg; */ | ||
213 | struct rt_frame_delba_req * pDelFrame; | ||
214 | if (MsgLen != (sizeof(struct rt_frame_delba_req))) | ||
215 | return FALSE; | ||
216 | |||
217 | if (Wcid >= MAX_LEN_OF_MAC_TABLE) | ||
218 | return FALSE; | ||
219 | |||
220 | pDelFrame = (struct rt_frame_delba_req *) (pMsg); | ||
221 | |||
222 | *(u16 *) (&pDelFrame->DelbaParm) = | ||
223 | cpu2le16(*(u16 *) (&pDelFrame->DelbaParm)); | ||
224 | pDelFrame->ReasonCode = cpu2le16(pDelFrame->ReasonCode); | ||
225 | |||
226 | if (pDelFrame->DelbaParm.TID & 0xfff0) | ||
227 | return FALSE; | ||
228 | |||
229 | return TRUE; | ||
230 | } | ||
231 | |||
232 | /* | ||
233 | ========================================================================== | ||
234 | Description: | ||
235 | MLME message sanity check | ||
236 | Return: | ||
237 | TRUE if all parameters are OK, FALSE otherwise | ||
238 | |||
239 | IRQL = DISPATCH_LEVEL | ||
240 | |||
241 | ========================================================================== | ||
242 | */ | ||
243 | BOOLEAN PeerBeaconAndProbeRspSanity(struct rt_rtmp_adapter *pAd, void * Msg, unsigned long MsgLen, u8 MsgChannel, u8 *pAddr2, u8 *pBssid, char Ssid[], u8 * pSsidLen, u8 * pBssType, u16 * pBeaconPeriod, u8 * pChannel, u8 * pNewChannel, OUT LARGE_INTEGER * pTimestamp, struct rt_cf_parm * pCfParm, u16 * pAtimWin, u16 * pCapabilityInfo, u8 * pErp, u8 * pDtimCount, u8 * pDtimPeriod, u8 * pBcastFlag, u8 * pMessageToMe, u8 SupRate[], u8 * pSupRateLen, u8 ExtRate[], u8 * pExtRateLen, u8 * pCkipFlag, u8 * pAironetCellPowerLimit, struct rt_edca_parm *pEdcaParm, struct rt_qbss_load_parm *pQbssLoad, struct rt_qos_capability_parm *pQosCapability, unsigned long * pRalinkIe, u8 * pHtCapabilityLen, u8 * pPreNHtCapabilityLen, struct rt_ht_capability_ie * pHtCapability, u8 * AddHtInfoLen, struct rt_add_ht_info_ie * AddHtInfo, u8 * NewExtChannelOffset, /* Ht extension channel offset(above or below) */ | ||
244 | u16 * LengthVIE, | ||
245 | struct rt_ndis_802_11_variable_ies *pVIE) | ||
246 | { | ||
247 | u8 *Ptr; | ||
248 | u8 TimLen; | ||
249 | struct rt_frame_802_11 * pFrame; | ||
250 | struct rt_eid * pEid; | ||
251 | u8 SubType; | ||
252 | u8 Sanity; | ||
253 | /*u8 ECWMin, ECWMax; */ | ||
254 | /*MAC_CSR9_STRUC Csr9; */ | ||
255 | unsigned long Length = 0; | ||
256 | |||
257 | /* For some 11a AP which didn't have DS_IE, we use two conditions to decide the channel */ | ||
258 | /* 1. If the AP is 11n enabled, then check the control channel. */ | ||
259 | /* 2. If the AP didn't have any info about channel, use the channel we received this frame as the channel. (May inaccuracy!) */ | ||
260 | u8 CtrlChannel = 0; | ||
261 | |||
262 | /* Add for 3 necessary EID field check */ | ||
263 | Sanity = 0; | ||
264 | |||
265 | *pAtimWin = 0; | ||
266 | *pErp = 0; | ||
267 | *pDtimCount = 0; | ||
268 | *pDtimPeriod = 0; | ||
269 | *pBcastFlag = 0; | ||
270 | *pMessageToMe = 0; | ||
271 | *pExtRateLen = 0; | ||
272 | *pCkipFlag = 0; /* Default of CkipFlag is 0 */ | ||
273 | *pAironetCellPowerLimit = 0xFF; /* Default of AironetCellPowerLimit is 0xFF */ | ||
274 | *LengthVIE = 0; /* Set the length of VIE to init value 0 */ | ||
275 | *pHtCapabilityLen = 0; /* Set the length of VIE to init value 0 */ | ||
276 | if (pAd->OpMode == OPMODE_STA) | ||
277 | *pPreNHtCapabilityLen = 0; /* Set the length of VIE to init value 0 */ | ||
278 | *AddHtInfoLen = 0; /* Set the length of VIE to init value 0 */ | ||
279 | *pRalinkIe = 0; | ||
280 | *pNewChannel = 0; | ||
281 | *NewExtChannelOffset = 0xff; /*Default 0xff means no such IE */ | ||
282 | pCfParm->bValid = FALSE; /* default: no IE_CF found */ | ||
283 | pQbssLoad->bValid = FALSE; /* default: no IE_QBSS_LOAD found */ | ||
284 | pEdcaParm->bValid = FALSE; /* default: no IE_EDCA_PARAMETER found */ | ||
285 | pQosCapability->bValid = FALSE; /* default: no IE_QOS_CAPABILITY found */ | ||
286 | |||
287 | pFrame = (struct rt_frame_802_11 *) Msg; | ||
288 | |||
289 | /* get subtype from header */ | ||
290 | SubType = (u8)pFrame->Hdr.FC.SubType; | ||
291 | |||
292 | /* get Addr2 and BSSID from header */ | ||
293 | COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); | ||
294 | COPY_MAC_ADDR(pBssid, pFrame->Hdr.Addr3); | ||
295 | |||
296 | Ptr = pFrame->Octet; | ||
297 | Length += LENGTH_802_11; | ||
298 | |||
299 | /* get timestamp from payload and advance the pointer */ | ||
300 | NdisMoveMemory(pTimestamp, Ptr, TIMESTAMP_LEN); | ||
301 | |||
302 | pTimestamp->u.LowPart = cpu2le32(pTimestamp->u.LowPart); | ||
303 | pTimestamp->u.HighPart = cpu2le32(pTimestamp->u.HighPart); | ||
304 | |||
305 | Ptr += TIMESTAMP_LEN; | ||
306 | Length += TIMESTAMP_LEN; | ||
307 | |||
308 | /* get beacon interval from payload and advance the pointer */ | ||
309 | NdisMoveMemory(pBeaconPeriod, Ptr, 2); | ||
310 | Ptr += 2; | ||
311 | Length += 2; | ||
312 | |||
313 | /* get capability info from payload and advance the pointer */ | ||
314 | NdisMoveMemory(pCapabilityInfo, Ptr, 2); | ||
315 | Ptr += 2; | ||
316 | Length += 2; | ||
317 | |||
318 | if (CAP_IS_ESS_ON(*pCapabilityInfo)) | ||
319 | *pBssType = BSS_INFRA; | ||
320 | else | ||
321 | *pBssType = BSS_ADHOC; | ||
322 | |||
323 | pEid = (struct rt_eid *) Ptr; | ||
324 | |||
325 | /* get variable fields from payload and advance the pointer */ | ||
326 | while ((Length + 2 + pEid->Len) <= MsgLen) { | ||
327 | /* */ | ||
328 | /* Secure copy VIE to VarIE[MAX_VIE_LEN] didn't overflow. */ | ||
329 | /* */ | ||
330 | if ((*LengthVIE + pEid->Len + 2) >= MAX_VIE_LEN) { | ||
331 | DBGPRINT(RT_DEBUG_WARN, | ||
332 | ("PeerBeaconAndProbeRspSanity - Variable IEs out of resource [len(=%d) > MAX_VIE_LEN(=%d)]\n", | ||
333 | (*LengthVIE + pEid->Len + 2), MAX_VIE_LEN)); | ||
334 | break; | ||
335 | } | ||
336 | |||
337 | switch (pEid->Eid) { | ||
338 | case IE_SSID: | ||
339 | /* Already has one SSID EID in this beacon, ignore the second one */ | ||
340 | if (Sanity & 0x1) | ||
341 | break; | ||
342 | if (pEid->Len <= MAX_LEN_OF_SSID) { | ||
343 | NdisMoveMemory(Ssid, pEid->Octet, pEid->Len); | ||
344 | *pSsidLen = pEid->Len; | ||
345 | Sanity |= 0x1; | ||
346 | } else { | ||
347 | DBGPRINT(RT_DEBUG_TRACE, | ||
348 | ("PeerBeaconAndProbeRspSanity - wrong IE_SSID (len=%d)\n", | ||
349 | pEid->Len)); | ||
350 | return FALSE; | ||
351 | } | ||
352 | break; | ||
353 | |||
354 | case IE_SUPP_RATES: | ||
355 | if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) { | ||
356 | Sanity |= 0x2; | ||
357 | NdisMoveMemory(SupRate, pEid->Octet, pEid->Len); | ||
358 | *pSupRateLen = pEid->Len; | ||
359 | |||
360 | /* TODO: 2004-09-14 not a good design here, cause it exclude extra rates */ | ||
361 | /* from ScanTab. We should report as is. And filter out unsupported */ | ||
362 | /* rates in MlmeAux. */ | ||
363 | /* Check against the supported rates */ | ||
364 | /* RTMPCheckRates(pAd, SupRate, pSupRateLen); */ | ||
365 | } else { | ||
366 | DBGPRINT(RT_DEBUG_TRACE, | ||
367 | ("PeerBeaconAndProbeRspSanity - wrong IE_SUPP_RATES (len=%d)\n", | ||
368 | pEid->Len)); | ||
369 | return FALSE; | ||
370 | } | ||
371 | break; | ||
372 | |||
373 | case IE_HT_CAP: | ||
374 | if (pEid->Len >= SIZE_HT_CAP_IE) /*Note: allow extension! */ | ||
375 | { | ||
376 | NdisMoveMemory(pHtCapability, pEid->Octet, | ||
377 | sizeof(struct rt_ht_capability_ie)); | ||
378 | *pHtCapabilityLen = SIZE_HT_CAP_IE; /* Nnow we only support 26 bytes. */ | ||
379 | |||
380 | *(u16 *) (&pHtCapability->HtCapInfo) = | ||
381 | cpu2le16(*(u16 *) | ||
382 | (&pHtCapability->HtCapInfo)); | ||
383 | *(u16 *) (&pHtCapability->ExtHtCapInfo) = | ||
384 | cpu2le16(*(u16 *) | ||
385 | (&pHtCapability->ExtHtCapInfo)); | ||
386 | |||
387 | { | ||
388 | *pPreNHtCapabilityLen = 0; /* Nnow we only support 26 bytes. */ | ||
389 | |||
390 | Ptr = (u8 *)pVIE; | ||
391 | NdisMoveMemory(Ptr + *LengthVIE, | ||
392 | &pEid->Eid, | ||
393 | pEid->Len + 2); | ||
394 | *LengthVIE += (pEid->Len + 2); | ||
395 | } | ||
396 | } else { | ||
397 | DBGPRINT(RT_DEBUG_WARN, | ||
398 | ("PeerBeaconAndProbeRspSanity - wrong IE_HT_CAP. pEid->Len = %d\n", | ||
399 | pEid->Len)); | ||
400 | } | ||
401 | |||
402 | break; | ||
403 | case IE_ADD_HT: | ||
404 | if (pEid->Len >= sizeof(struct rt_add_ht_info_ie)) { | ||
405 | /* This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only */ | ||
406 | /* copy first sizeof(struct rt_add_ht_info_ie) */ | ||
407 | NdisMoveMemory(AddHtInfo, pEid->Octet, | ||
408 | sizeof(struct rt_add_ht_info_ie)); | ||
409 | *AddHtInfoLen = SIZE_ADD_HT_INFO_IE; | ||
410 | |||
411 | CtrlChannel = AddHtInfo->ControlChan; | ||
412 | |||
413 | *(u16 *) (&AddHtInfo->AddHtInfo2) = | ||
414 | cpu2le16(*(u16 *) | ||
415 | (&AddHtInfo->AddHtInfo2)); | ||
416 | *(u16 *) (&AddHtInfo->AddHtInfo3) = | ||
417 | cpu2le16(*(u16 *) | ||
418 | (&AddHtInfo->AddHtInfo3)); | ||
419 | |||
420 | { | ||
421 | Ptr = (u8 *)pVIE; | ||
422 | NdisMoveMemory(Ptr + *LengthVIE, | ||
423 | &pEid->Eid, | ||
424 | pEid->Len + 2); | ||
425 | *LengthVIE += (pEid->Len + 2); | ||
426 | } | ||
427 | } else { | ||
428 | DBGPRINT(RT_DEBUG_WARN, | ||
429 | ("PeerBeaconAndProbeRspSanity - wrong IE_ADD_HT. \n")); | ||
430 | } | ||
431 | |||
432 | break; | ||
433 | case IE_SECONDARY_CH_OFFSET: | ||
434 | if (pEid->Len == 1) { | ||
435 | *NewExtChannelOffset = pEid->Octet[0]; | ||
436 | } else { | ||
437 | DBGPRINT(RT_DEBUG_WARN, | ||
438 | ("PeerBeaconAndProbeRspSanity - wrong IE_SECONDARY_CH_OFFSET. \n")); | ||
439 | } | ||
440 | |||
441 | break; | ||
442 | case IE_FH_PARM: | ||
443 | DBGPRINT(RT_DEBUG_TRACE, | ||
444 | ("PeerBeaconAndProbeRspSanity(IE_FH_PARM) \n")); | ||
445 | break; | ||
446 | |||
447 | case IE_DS_PARM: | ||
448 | if (pEid->Len == 1) { | ||
449 | *pChannel = *pEid->Octet; | ||
450 | |||
451 | { | ||
452 | if (ChannelSanity(pAd, *pChannel) == 0) { | ||
453 | |||
454 | return FALSE; | ||
455 | } | ||
456 | } | ||
457 | |||
458 | Sanity |= 0x4; | ||
459 | } else { | ||
460 | DBGPRINT(RT_DEBUG_TRACE, | ||
461 | ("PeerBeaconAndProbeRspSanity - wrong IE_DS_PARM (len=%d)\n", | ||
462 | pEid->Len)); | ||
463 | return FALSE; | ||
464 | } | ||
465 | break; | ||
466 | |||
467 | case IE_CF_PARM: | ||
468 | if (pEid->Len == 6) { | ||
469 | pCfParm->bValid = TRUE; | ||
470 | pCfParm->CfpCount = pEid->Octet[0]; | ||
471 | pCfParm->CfpPeriod = pEid->Octet[1]; | ||
472 | pCfParm->CfpMaxDuration = | ||
473 | pEid->Octet[2] + 256 * pEid->Octet[3]; | ||
474 | pCfParm->CfpDurRemaining = | ||
475 | pEid->Octet[4] + 256 * pEid->Octet[5]; | ||
476 | } else { | ||
477 | DBGPRINT(RT_DEBUG_TRACE, | ||
478 | ("PeerBeaconAndProbeRspSanity - wrong IE_CF_PARM\n")); | ||
479 | return FALSE; | ||
480 | } | ||
481 | break; | ||
482 | |||
483 | case IE_IBSS_PARM: | ||
484 | if (pEid->Len == 2) { | ||
485 | NdisMoveMemory(pAtimWin, pEid->Octet, | ||
486 | pEid->Len); | ||
487 | } else { | ||
488 | DBGPRINT(RT_DEBUG_TRACE, | ||
489 | ("PeerBeaconAndProbeRspSanity - wrong IE_IBSS_PARM\n")); | ||
490 | return FALSE; | ||
491 | } | ||
492 | break; | ||
493 | |||
494 | case IE_TIM: | ||
495 | if (INFRA_ON(pAd) && SubType == SUBTYPE_BEACON) { | ||
496 | GetTimBit((char *)pEid, pAd->StaActive.Aid, | ||
497 | &TimLen, pBcastFlag, pDtimCount, | ||
498 | pDtimPeriod, pMessageToMe); | ||
499 | } | ||
500 | break; | ||
501 | case IE_CHANNEL_SWITCH_ANNOUNCEMENT: | ||
502 | if (pEid->Len == 3) { | ||
503 | *pNewChannel = pEid->Octet[1]; /*extract new channel number */ | ||
504 | } | ||
505 | break; | ||
506 | |||
507 | /* New for WPA */ | ||
508 | /* CCX v2 has the same IE, we need to parse that too */ | ||
509 | /* Wifi WMM use the same IE vale, need to parse that too */ | ||
510 | /* case IE_WPA: */ | ||
511 | case IE_VENDOR_SPECIFIC: | ||
512 | /* Check Broadcom/Atheros 802.11n OUI version, for HT Capability IE. */ | ||
513 | /* This HT IE is before IEEE draft set HT IE value.2006-09-28 by Jan. */ | ||
514 | /*if (NdisEqualMemory(pEid->Octet, BROADCOM_OUI, 3) && (pEid->Len >= 4)) | ||
515 | { | ||
516 | if ((pEid->Octet[3] == OUI_BROADCOM_HT) && (pEid->Len >= 30)) | ||
517 | { | ||
518 | { | ||
519 | NdisMoveMemory(pHtCapability, &pEid->Octet[4], sizeof(struct rt_ht_capability_ie)); | ||
520 | *pHtCapabilityLen = SIZE_HT_CAP_IE; // Nnow we only support 26 bytes. | ||
521 | } | ||
522 | } | ||
523 | if ((pEid->Octet[3] == OUI_BROADCOM_HT) && (pEid->Len >= 26)) | ||
524 | { | ||
525 | { | ||
526 | NdisMoveMemory(AddHtInfo, &pEid->Octet[4], sizeof(struct rt_add_ht_info_ie)); | ||
527 | *AddHtInfoLen = SIZE_ADD_HT_INFO_IE; // Nnow we only support 26 bytes. | ||
528 | } | ||
529 | } | ||
530 | } | ||
531 | */ | ||
532 | /* Check the OUI version, filter out non-standard usage */ | ||
533 | if (NdisEqualMemory(pEid->Octet, RALINK_OUI, 3) | ||
534 | && (pEid->Len == 7)) { | ||
535 | /**pRalinkIe = pEid->Octet[3]; */ | ||
536 | if (pEid->Octet[3] != 0) | ||
537 | *pRalinkIe = pEid->Octet[3]; | ||
538 | else | ||
539 | *pRalinkIe = 0xf0000000; /* Set to non-zero value (can't set bit0-2) to represent this is Ralink Chip. So at linkup, we will set ralinkchip flag. */ | ||
540 | } | ||
541 | /* This HT IE is before IEEE draft set HT IE value.2006-09-28 by Jan. */ | ||
542 | |||
543 | /* Other vendors had production before IE_HT_CAP value is assigned. To backward support those old-firmware AP, */ | ||
544 | /* Check broadcom-defiend pre-802.11nD1.0 OUI for HT related IE, including HT Capatilities IE and HT Information IE */ | ||
545 | else if ((*pHtCapabilityLen == 0) | ||
546 | && NdisEqualMemory(pEid->Octet, PRE_N_HT_OUI, | ||
547 | 3) && (pEid->Len >= 4) | ||
548 | && (pAd->OpMode == OPMODE_STA)) { | ||
549 | if ((pEid->Octet[3] == OUI_PREN_HT_CAP) | ||
550 | && (pEid->Len >= 30) | ||
551 | && (*pHtCapabilityLen == 0)) { | ||
552 | NdisMoveMemory(pHtCapability, | ||
553 | &pEid->Octet[4], | ||
554 | sizeof | ||
555 | (struct rt_ht_capability_ie)); | ||
556 | *pPreNHtCapabilityLen = SIZE_HT_CAP_IE; | ||
557 | } | ||
558 | |||
559 | if ((pEid->Octet[3] == OUI_PREN_ADD_HT) | ||
560 | && (pEid->Len >= 26)) { | ||
561 | NdisMoveMemory(AddHtInfo, | ||
562 | &pEid->Octet[4], | ||
563 | sizeof(struct rt_add_ht_info_ie)); | ||
564 | *AddHtInfoLen = SIZE_ADD_HT_INFO_IE; | ||
565 | } | ||
566 | } else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) { | ||
567 | /* Copy to pVIE which will report to microsoft bssid list. */ | ||
568 | Ptr = (u8 *)pVIE; | ||
569 | NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, | ||
570 | pEid->Len + 2); | ||
571 | *LengthVIE += (pEid->Len + 2); | ||
572 | } else | ||
573 | if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) | ||
574 | && (pEid->Len == 24)) { | ||
575 | u8 *ptr; | ||
576 | int i; | ||
577 | |||
578 | /* parsing EDCA parameters */ | ||
579 | pEdcaParm->bValid = TRUE; | ||
580 | pEdcaParm->bQAck = FALSE; /* pEid->Octet[0] & 0x10; */ | ||
581 | pEdcaParm->bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20; */ | ||
582 | pEdcaParm->bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40; */ | ||
583 | pEdcaParm->EdcaUpdateCount = | ||
584 | pEid->Octet[6] & 0x0f; | ||
585 | pEdcaParm->bAPSDCapable = | ||
586 | (pEid->Octet[6] & 0x80) ? 1 : 0; | ||
587 | ptr = &pEid->Octet[8]; | ||
588 | for (i = 0; i < 4; i++) { | ||
589 | u8 aci = (*ptr & 0x60) >> 5; /* b5~6 is AC INDEX */ | ||
590 | pEdcaParm->bACM[aci] = (((*ptr) & 0x10) == 0x10); /* b5 is ACM */ | ||
591 | pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f; /* b0~3 is AIFSN */ | ||
592 | pEdcaParm->Cwmin[aci] = *(ptr + 1) & 0x0f; /* b0~4 is Cwmin */ | ||
593 | pEdcaParm->Cwmax[aci] = *(ptr + 1) >> 4; /* b5~8 is Cwmax */ | ||
594 | pEdcaParm->Txop[aci] = *(ptr + 2) + 256 * (*(ptr + 3)); /* in unit of 32-us */ | ||
595 | ptr += 4; /* point to next AC */ | ||
596 | } | ||
597 | } else | ||
598 | if (NdisEqualMemory(pEid->Octet, WME_INFO_ELEM, 6) | ||
599 | && (pEid->Len == 7)) { | ||
600 | /* parsing EDCA parameters */ | ||
601 | pEdcaParm->bValid = TRUE; | ||
602 | pEdcaParm->bQAck = FALSE; /* pEid->Octet[0] & 0x10; */ | ||
603 | pEdcaParm->bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20; */ | ||
604 | pEdcaParm->bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40; */ | ||
605 | pEdcaParm->EdcaUpdateCount = | ||
606 | pEid->Octet[6] & 0x0f; | ||
607 | pEdcaParm->bAPSDCapable = | ||
608 | (pEid->Octet[6] & 0x80) ? 1 : 0; | ||
609 | |||
610 | /* use default EDCA parameter */ | ||
611 | pEdcaParm->bACM[QID_AC_BE] = 0; | ||
612 | pEdcaParm->Aifsn[QID_AC_BE] = 3; | ||
613 | pEdcaParm->Cwmin[QID_AC_BE] = CW_MIN_IN_BITS; | ||
614 | pEdcaParm->Cwmax[QID_AC_BE] = CW_MAX_IN_BITS; | ||
615 | pEdcaParm->Txop[QID_AC_BE] = 0; | ||
616 | |||
617 | pEdcaParm->bACM[QID_AC_BK] = 0; | ||
618 | pEdcaParm->Aifsn[QID_AC_BK] = 7; | ||
619 | pEdcaParm->Cwmin[QID_AC_BK] = CW_MIN_IN_BITS; | ||
620 | pEdcaParm->Cwmax[QID_AC_BK] = CW_MAX_IN_BITS; | ||
621 | pEdcaParm->Txop[QID_AC_BK] = 0; | ||
622 | |||
623 | pEdcaParm->bACM[QID_AC_VI] = 0; | ||
624 | pEdcaParm->Aifsn[QID_AC_VI] = 2; | ||
625 | pEdcaParm->Cwmin[QID_AC_VI] = | ||
626 | CW_MIN_IN_BITS - 1; | ||
627 | pEdcaParm->Cwmax[QID_AC_VI] = CW_MAX_IN_BITS; | ||
628 | pEdcaParm->Txop[QID_AC_VI] = 96; /* AC_VI: 96*32us ~= 3ms */ | ||
629 | |||
630 | pEdcaParm->bACM[QID_AC_VO] = 0; | ||
631 | pEdcaParm->Aifsn[QID_AC_VO] = 2; | ||
632 | pEdcaParm->Cwmin[QID_AC_VO] = | ||
633 | CW_MIN_IN_BITS - 2; | ||
634 | pEdcaParm->Cwmax[QID_AC_VO] = | ||
635 | CW_MAX_IN_BITS - 1; | ||
636 | pEdcaParm->Txop[QID_AC_VO] = 48; /* AC_VO: 48*32us ~= 1.5ms */ | ||
637 | } | ||
638 | |||
639 | break; | ||
640 | |||
641 | case IE_EXT_SUPP_RATES: | ||
642 | if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) { | ||
643 | NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len); | ||
644 | *pExtRateLen = pEid->Len; | ||
645 | |||
646 | /* TODO: 2004-09-14 not a good design here, cause it exclude extra rates */ | ||
647 | /* from ScanTab. We should report as is. And filter out unsupported */ | ||
648 | /* rates in MlmeAux. */ | ||
649 | /* Check against the supported rates */ | ||
650 | /* RTMPCheckRates(pAd, ExtRate, pExtRateLen); */ | ||
651 | } | ||
652 | break; | ||
653 | |||
654 | case IE_ERP: | ||
655 | if (pEid->Len == 1) { | ||
656 | *pErp = (u8)pEid->Octet[0]; | ||
657 | } | ||
658 | break; | ||
659 | |||
660 | case IE_AIRONET_CKIP: | ||
661 | /* 0. Check Aironet IE length, it must be larger or equal to 28 */ | ||
662 | /* Cisco AP350 used length as 28 */ | ||
663 | /* Cisco AP12XX used length as 30 */ | ||
664 | if (pEid->Len < (CKIP_NEGOTIATION_LENGTH - 2)) | ||
665 | break; | ||
666 | |||
667 | /* 1. Copy CKIP flag byte to buffer for process */ | ||
668 | *pCkipFlag = *(pEid->Octet + 8); | ||
669 | break; | ||
670 | |||
671 | case IE_AP_TX_POWER: | ||
672 | /* AP Control of Client Transmit Power */ | ||
673 | /*0. Check Aironet IE length, it must be 6 */ | ||
674 | if (pEid->Len != 0x06) | ||
675 | break; | ||
676 | |||
677 | /* Get cell power limit in dBm */ | ||
678 | if (NdisEqualMemory(pEid->Octet, CISCO_OUI, 3) == 1) | ||
679 | *pAironetCellPowerLimit = *(pEid->Octet + 4); | ||
680 | break; | ||
681 | |||
682 | /* WPA2 & 802.11i RSN */ | ||
683 | case IE_RSN: | ||
684 | /* There is no OUI for version anymore, check the group cipher OUI before copying */ | ||
685 | if (RTMPEqualMemory(pEid->Octet + 2, RSN_OUI, 3)) { | ||
686 | /* Copy to pVIE which will report to microsoft bssid list. */ | ||
687 | Ptr = (u8 *)pVIE; | ||
688 | NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, | ||
689 | pEid->Len + 2); | ||
690 | *LengthVIE += (pEid->Len + 2); | ||
691 | } | ||
692 | break; | ||
693 | |||
694 | default: | ||
695 | break; | ||
696 | } | ||
697 | |||
698 | Length = Length + 2 + pEid->Len; /* Eid[1] + Len[1]+ content[Len] */ | ||
699 | pEid = (struct rt_eid *) ((u8 *) pEid + 2 + pEid->Len); | ||
700 | } | ||
701 | |||
702 | /* For some 11a AP. it did not have the channel EID, patch here */ | ||
703 | { | ||
704 | u8 LatchRfChannel = MsgChannel; | ||
705 | if ((pAd->LatchRfRegs.Channel > 14) && ((Sanity & 0x4) == 0)) { | ||
706 | if (CtrlChannel != 0) | ||
707 | *pChannel = CtrlChannel; | ||
708 | else | ||
709 | *pChannel = LatchRfChannel; | ||
710 | Sanity |= 0x4; | ||
711 | } | ||
712 | } | ||
713 | |||
714 | if (Sanity != 0x7) { | ||
715 | DBGPRINT(RT_DEBUG_LOUD, | ||
716 | ("PeerBeaconAndProbeRspSanity - missing field, Sanity=0x%02x\n", | ||
717 | Sanity)); | ||
718 | return FALSE; | ||
719 | } else { | ||
720 | return TRUE; | ||
721 | } | ||
722 | |||
723 | } | ||
724 | |||
725 | /* | ||
726 | ========================================================================== | ||
727 | Description: | ||
728 | MLME message sanity check | ||
729 | Return: | ||
730 | TRUE if all parameters are OK, FALSE otherwise | ||
731 | ========================================================================== | ||
732 | */ | ||
733 | BOOLEAN MlmeScanReqSanity(struct rt_rtmp_adapter *pAd, | ||
734 | void * Msg, | ||
735 | unsigned long MsgLen, | ||
736 | u8 * pBssType, | ||
737 | char Ssid[], | ||
738 | u8 * pSsidLen, u8 * pScanType) | ||
739 | { | ||
740 | struct rt_mlme_scan_req *Info; | ||
741 | |||
742 | Info = (struct rt_mlme_scan_req *)(Msg); | ||
743 | *pBssType = Info->BssType; | ||
744 | *pSsidLen = Info->SsidLen; | ||
745 | NdisMoveMemory(Ssid, Info->Ssid, *pSsidLen); | ||
746 | *pScanType = Info->ScanType; | ||
747 | |||
748 | if ((*pBssType == BSS_INFRA || *pBssType == BSS_ADHOC | ||
749 | || *pBssType == BSS_ANY) | ||
750 | && (*pScanType == SCAN_ACTIVE || *pScanType == SCAN_PASSIVE)) { | ||
751 | return TRUE; | ||
752 | } else { | ||
753 | DBGPRINT(RT_DEBUG_TRACE, | ||
754 | ("MlmeScanReqSanity fail - wrong BssType or ScanType\n")); | ||
755 | return FALSE; | ||
756 | } | ||
757 | } | ||
758 | |||
759 | /* IRQL = DISPATCH_LEVEL */ | ||
760 | u8 ChannelSanity(struct rt_rtmp_adapter *pAd, u8 channel) | ||
761 | { | ||
762 | int i; | ||
763 | |||
764 | for (i = 0; i < pAd->ChannelListNum; i++) { | ||
765 | if (channel == pAd->ChannelList[i].Channel) | ||
766 | return 1; | ||
767 | } | ||
768 | return 0; | ||
769 | } | ||
770 | |||
771 | /* | ||
772 | ========================================================================== | ||
773 | Description: | ||
774 | MLME message sanity check | ||
775 | Return: | ||
776 | TRUE if all parameters are OK, FALSE otherwise | ||
777 | |||
778 | IRQL = DISPATCH_LEVEL | ||
779 | |||
780 | ========================================================================== | ||
781 | */ | ||
782 | BOOLEAN PeerDeauthSanity(struct rt_rtmp_adapter *pAd, | ||
783 | void * Msg, | ||
784 | unsigned long MsgLen, | ||
785 | u8 *pAddr2, u16 * pReason) | ||
786 | { | ||
787 | struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *) Msg; | ||
788 | |||
789 | COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); | ||
790 | NdisMoveMemory(pReason, &pFrame->Octet[0], 2); | ||
791 | |||
792 | return TRUE; | ||
793 | } | ||
794 | |||
795 | /* | ||
796 | ========================================================================== | ||
797 | Description: | ||
798 | MLME message sanity check | ||
799 | Return: | ||
800 | TRUE if all parameters are OK, FALSE otherwise | ||
801 | |||
802 | IRQL = DISPATCH_LEVEL | ||
803 | |||
804 | ========================================================================== | ||
805 | */ | ||
806 | BOOLEAN PeerAuthSanity(struct rt_rtmp_adapter *pAd, | ||
807 | void * Msg, | ||
808 | unsigned long MsgLen, | ||
809 | u8 *pAddr, | ||
810 | u16 * pAlg, | ||
811 | u16 * pSeq, | ||
812 | u16 * pStatus, char * pChlgText) | ||
813 | { | ||
814 | struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *) Msg; | ||
815 | |||
816 | COPY_MAC_ADDR(pAddr, pFrame->Hdr.Addr2); | ||
817 | NdisMoveMemory(pAlg, &pFrame->Octet[0], 2); | ||
818 | NdisMoveMemory(pSeq, &pFrame->Octet[2], 2); | ||
819 | NdisMoveMemory(pStatus, &pFrame->Octet[4], 2); | ||
820 | |||
821 | if (*pAlg == AUTH_MODE_OPEN) { | ||
822 | if (*pSeq == 1 || *pSeq == 2) { | ||
823 | return TRUE; | ||
824 | } else { | ||
825 | DBGPRINT(RT_DEBUG_TRACE, | ||
826 | ("PeerAuthSanity fail - wrong Seg#\n")); | ||
827 | return FALSE; | ||
828 | } | ||
829 | } else if (*pAlg == AUTH_MODE_KEY) { | ||
830 | if (*pSeq == 1 || *pSeq == 4) { | ||
831 | return TRUE; | ||
832 | } else if (*pSeq == 2 || *pSeq == 3) { | ||
833 | NdisMoveMemory(pChlgText, &pFrame->Octet[8], | ||
834 | CIPHER_TEXT_LEN); | ||
835 | return TRUE; | ||
836 | } else { | ||
837 | DBGPRINT(RT_DEBUG_TRACE, | ||
838 | ("PeerAuthSanity fail - wrong Seg#\n")); | ||
839 | return FALSE; | ||
840 | } | ||
841 | } else { | ||
842 | DBGPRINT(RT_DEBUG_TRACE, | ||
843 | ("PeerAuthSanity fail - wrong algorithm\n")); | ||
844 | return FALSE; | ||
845 | } | ||
846 | } | ||
847 | |||
848 | /* | ||
849 | ========================================================================== | ||
850 | Description: | ||
851 | MLME message sanity check | ||
852 | Return: | ||
853 | TRUE if all parameters are OK, FALSE otherwise | ||
854 | ========================================================================== | ||
855 | */ | ||
856 | BOOLEAN MlmeAuthReqSanity(struct rt_rtmp_adapter *pAd, | ||
857 | void * Msg, | ||
858 | unsigned long MsgLen, | ||
859 | u8 *pAddr, | ||
860 | unsigned long * pTimeout, u16 * pAlg) | ||
861 | { | ||
862 | struct rt_mlme_auth_req *pInfo; | ||
863 | |||
864 | pInfo = (struct rt_mlme_auth_req *)Msg; | ||
865 | COPY_MAC_ADDR(pAddr, pInfo->Addr); | ||
866 | *pTimeout = pInfo->Timeout; | ||
867 | *pAlg = pInfo->Alg; | ||
868 | |||
869 | if (((*pAlg == AUTH_MODE_KEY) || (*pAlg == AUTH_MODE_OPEN) | ||
870 | ) && ((*pAddr & 0x01) == 0)) { | ||
871 | return TRUE; | ||
872 | } else { | ||
873 | DBGPRINT(RT_DEBUG_TRACE, | ||
874 | ("MlmeAuthReqSanity fail - wrong algorithm\n")); | ||
875 | return FALSE; | ||
876 | } | ||
877 | } | ||
878 | |||
879 | /* | ||
880 | ========================================================================== | ||
881 | Description: | ||
882 | MLME message sanity check | ||
883 | Return: | ||
884 | TRUE if all parameters are OK, FALSE otherwise | ||
885 | |||
886 | IRQL = DISPATCH_LEVEL | ||
887 | |||
888 | ========================================================================== | ||
889 | */ | ||
890 | BOOLEAN MlmeAssocReqSanity(struct rt_rtmp_adapter *pAd, | ||
891 | void * Msg, | ||
892 | unsigned long MsgLen, | ||
893 | u8 *pApAddr, | ||
894 | u16 * pCapabilityInfo, | ||
895 | unsigned long * pTimeout, u16 * pListenIntv) | ||
896 | { | ||
897 | struct rt_mlme_assoc_req *pInfo; | ||
898 | |||
899 | pInfo = (struct rt_mlme_assoc_req *)Msg; | ||
900 | *pTimeout = pInfo->Timeout; /* timeout */ | ||
901 | COPY_MAC_ADDR(pApAddr, pInfo->Addr); /* AP address */ | ||
902 | *pCapabilityInfo = pInfo->CapabilityInfo; /* capability info */ | ||
903 | *pListenIntv = pInfo->ListenIntv; | ||
904 | |||
905 | return TRUE; | ||
906 | } | ||
907 | |||
908 | /* | ||
909 | ========================================================================== | ||
910 | Description: | ||
911 | MLME message sanity check | ||
912 | Return: | ||
913 | TRUE if all parameters are OK, FALSE otherwise | ||
914 | |||
915 | IRQL = DISPATCH_LEVEL | ||
916 | |||
917 | ========================================================================== | ||
918 | */ | ||
919 | BOOLEAN PeerDisassocSanity(struct rt_rtmp_adapter *pAd, | ||
920 | void * Msg, | ||
921 | unsigned long MsgLen, | ||
922 | u8 *pAddr2, u16 * pReason) | ||
923 | { | ||
924 | struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *) Msg; | ||
925 | |||
926 | COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); | ||
927 | NdisMoveMemory(pReason, &pFrame->Octet[0], 2); | ||
928 | |||
929 | return TRUE; | ||
930 | } | ||
931 | |||
932 | /* | ||
933 | ======================================================================== | ||
934 | Routine Description: | ||
935 | Sanity check NetworkType (11b, 11g or 11a) | ||
936 | |||
937 | Arguments: | ||
938 | pBss - Pointer to BSS table. | ||
939 | |||
940 | Return Value: | ||
941 | Ndis802_11DS .......(11b) | ||
942 | Ndis802_11OFDM24....(11g) | ||
943 | Ndis802_11OFDM5.....(11a) | ||
944 | |||
945 | IRQL = DISPATCH_LEVEL | ||
946 | |||
947 | ======================================================================== | ||
948 | */ | ||
949 | NDIS_802_11_NETWORK_TYPE NetworkTypeInUseSanity(struct rt_bss_entry *pBss) | ||
950 | { | ||
951 | NDIS_802_11_NETWORK_TYPE NetWorkType; | ||
952 | u8 rate, i; | ||
953 | |||
954 | NetWorkType = Ndis802_11DS; | ||
955 | |||
956 | if (pBss->Channel <= 14) { | ||
957 | /* */ | ||
958 | /* First check support Rate. */ | ||
959 | /* */ | ||
960 | for (i = 0; i < pBss->SupRateLen; i++) { | ||
961 | rate = pBss->SupRate[i] & 0x7f; /* Mask out basic rate set bit */ | ||
962 | if ((rate == 2) || (rate == 4) || (rate == 11) | ||
963 | || (rate == 22)) { | ||
964 | continue; | ||
965 | } else { | ||
966 | /* */ | ||
967 | /* Otherwise (even rate > 108) means Ndis802_11OFDM24 */ | ||
968 | /* */ | ||
969 | NetWorkType = Ndis802_11OFDM24; | ||
970 | break; | ||
971 | } | ||
972 | } | ||
973 | |||
974 | /* */ | ||
975 | /* Second check Extend Rate. */ | ||
976 | /* */ | ||
977 | if (NetWorkType != Ndis802_11OFDM24) { | ||
978 | for (i = 0; i < pBss->ExtRateLen; i++) { | ||
979 | rate = pBss->SupRate[i] & 0x7f; /* Mask out basic rate set bit */ | ||
980 | if ((rate == 2) || (rate == 4) || (rate == 11) | ||
981 | || (rate == 22)) { | ||
982 | continue; | ||
983 | } else { | ||
984 | /* */ | ||
985 | /* Otherwise (even rate > 108) means Ndis802_11OFDM24 */ | ||
986 | /* */ | ||
987 | NetWorkType = Ndis802_11OFDM24; | ||
988 | break; | ||
989 | } | ||
990 | } | ||
991 | } | ||
992 | } else { | ||
993 | NetWorkType = Ndis802_11OFDM5; | ||
994 | } | ||
995 | |||
996 | if (pBss->HtCapabilityLen != 0) { | ||
997 | if (NetWorkType == Ndis802_11OFDM5) | ||
998 | NetWorkType = Ndis802_11OFDM5_N; | ||
999 | else | ||
1000 | NetWorkType = Ndis802_11OFDM24_N; | ||
1001 | } | ||
1002 | |||
1003 | return NetWorkType; | ||
1004 | } | ||
1005 | |||
1006 | /* | ||
1007 | ========================================================================== | ||
1008 | Description: | ||
1009 | Check the validity of the received EAPoL frame | ||
1010 | Return: | ||
1011 | TRUE if all parameters are OK, | ||
1012 | FALSE otherwise | ||
1013 | ========================================================================== | ||
1014 | */ | ||
1015 | BOOLEAN PeerWpaMessageSanity(struct rt_rtmp_adapter *pAd, | ||
1016 | struct rt_eapol_packet * pMsg, | ||
1017 | unsigned long MsgLen, | ||
1018 | u8 MsgType, struct rt_mac_table_entry *pEntry) | ||
1019 | { | ||
1020 | u8 mic[LEN_KEY_DESC_MIC], digest[80], KEYDATA[MAX_LEN_OF_RSNIE]; | ||
1021 | BOOLEAN bReplayDiff = FALSE; | ||
1022 | BOOLEAN bWPA2 = FALSE; | ||
1023 | struct rt_key_info EapolKeyInfo; | ||
1024 | u8 GroupKeyIndex = 0; | ||
1025 | |||
1026 | NdisZeroMemory(mic, sizeof(mic)); | ||
1027 | NdisZeroMemory(digest, sizeof(digest)); | ||
1028 | NdisZeroMemory(KEYDATA, sizeof(KEYDATA)); | ||
1029 | NdisZeroMemory((u8 *)& EapolKeyInfo, sizeof(EapolKeyInfo)); | ||
1030 | |||
1031 | NdisMoveMemory((u8 *)& EapolKeyInfo, | ||
1032 | (u8 *)& pMsg->KeyDesc.KeyInfo, sizeof(struct rt_key_info)); | ||
1033 | |||
1034 | *((u16 *) & EapolKeyInfo) = cpu2le16(*((u16 *) & EapolKeyInfo)); | ||
1035 | |||
1036 | /* Choose WPA2 or not */ | ||
1037 | if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) | ||
1038 | || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) | ||
1039 | bWPA2 = TRUE; | ||
1040 | |||
1041 | /* 0. Check MsgType */ | ||
1042 | if ((MsgType > EAPOL_GROUP_MSG_2) || (MsgType < EAPOL_PAIR_MSG_1)) { | ||
1043 | DBGPRINT(RT_DEBUG_ERROR, | ||
1044 | ("The message type is invalid(%d)! \n", MsgType)); | ||
1045 | return FALSE; | ||
1046 | } | ||
1047 | /* 1. Replay counter check */ | ||
1048 | if (MsgType == EAPOL_PAIR_MSG_1 || MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1) /* For supplicant */ | ||
1049 | { | ||
1050 | /* First validate replay counter, only accept message with larger replay counter. */ | ||
1051 | /* Let equal pass, some AP start with all zero replay counter */ | ||
1052 | u8 ZeroReplay[LEN_KEY_DESC_REPLAY]; | ||
1053 | |||
1054 | NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY); | ||
1055 | if ((RTMPCompareMemory | ||
1056 | (pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, | ||
1057 | LEN_KEY_DESC_REPLAY) != 1) | ||
1058 | && | ||
1059 | (RTMPCompareMemory | ||
1060 | (pMsg->KeyDesc.ReplayCounter, ZeroReplay, | ||
1061 | LEN_KEY_DESC_REPLAY) != 0)) { | ||
1062 | bReplayDiff = TRUE; | ||
1063 | } | ||
1064 | } else if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2) /* For authenticator */ | ||
1065 | { | ||
1066 | /* check Replay Counter coresponds to MSG from authenticator, otherwise discard */ | ||
1067 | if (!NdisEqualMemory | ||
1068 | (pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, | ||
1069 | LEN_KEY_DESC_REPLAY)) { | ||
1070 | bReplayDiff = TRUE; | ||
1071 | } | ||
1072 | } | ||
1073 | /* Replay Counter different condition */ | ||
1074 | if (bReplayDiff) { | ||
1075 | /* send wireless event - for replay counter different */ | ||
1076 | if (pAd->CommonCfg.bWirelessEvent) | ||
1077 | RTMPSendWirelessEvent(pAd, | ||
1078 | IW_REPLAY_COUNTER_DIFF_EVENT_FLAG, | ||
1079 | pEntry->Addr, pEntry->apidx, 0); | ||
1080 | |||
1081 | if (MsgType < EAPOL_GROUP_MSG_1) { | ||
1082 | DBGPRINT(RT_DEBUG_ERROR, | ||
1083 | ("Replay Counter Different in pairwise msg %d of 4-way handshake!\n", | ||
1084 | MsgType)); | ||
1085 | } else { | ||
1086 | DBGPRINT(RT_DEBUG_ERROR, | ||
1087 | ("Replay Counter Different in group msg %d of 2-way handshake!\n", | ||
1088 | (MsgType - EAPOL_PAIR_MSG_4))); | ||
1089 | } | ||
1090 | |||
1091 | hex_dump("Receive replay counter ", pMsg->KeyDesc.ReplayCounter, | ||
1092 | LEN_KEY_DESC_REPLAY); | ||
1093 | hex_dump("Current replay counter ", pEntry->R_Counter, | ||
1094 | LEN_KEY_DESC_REPLAY); | ||
1095 | return FALSE; | ||
1096 | } | ||
1097 | /* 2. Verify MIC except Pairwise Msg1 */ | ||
1098 | if (MsgType != EAPOL_PAIR_MSG_1) { | ||
1099 | u8 rcvd_mic[LEN_KEY_DESC_MIC]; | ||
1100 | |||
1101 | /* Record the received MIC for check later */ | ||
1102 | NdisMoveMemory(rcvd_mic, pMsg->KeyDesc.KeyMic, | ||
1103 | LEN_KEY_DESC_MIC); | ||
1104 | NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); | ||
1105 | |||
1106 | if (EapolKeyInfo.KeyDescVer == DESC_TYPE_TKIP) /* TKIP */ | ||
1107 | { | ||
1108 | HMAC_MD5(pEntry->PTK, LEN_EAP_MICK, (u8 *)pMsg, | ||
1109 | MsgLen, mic, MD5_DIGEST_SIZE); | ||
1110 | } else if (EapolKeyInfo.KeyDescVer == DESC_TYPE_AES) /* AES */ | ||
1111 | { | ||
1112 | HMAC_SHA1(pEntry->PTK, LEN_EAP_MICK, (u8 *)pMsg, | ||
1113 | MsgLen, digest, SHA1_DIGEST_SIZE); | ||
1114 | NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC); | ||
1115 | } | ||
1116 | |||
1117 | if (!NdisEqualMemory(rcvd_mic, mic, LEN_KEY_DESC_MIC)) { | ||
1118 | /* send wireless event - for MIC different */ | ||
1119 | if (pAd->CommonCfg.bWirelessEvent) | ||
1120 | RTMPSendWirelessEvent(pAd, | ||
1121 | IW_MIC_DIFF_EVENT_FLAG, | ||
1122 | pEntry->Addr, | ||
1123 | pEntry->apidx, 0); | ||
1124 | |||
1125 | if (MsgType < EAPOL_GROUP_MSG_1) { | ||
1126 | DBGPRINT(RT_DEBUG_ERROR, | ||
1127 | ("MIC Different in pairwise msg %d of 4-way handshake!\n", | ||
1128 | MsgType)); | ||
1129 | } else { | ||
1130 | DBGPRINT(RT_DEBUG_ERROR, | ||
1131 | ("MIC Different in group msg %d of 2-way handshake!\n", | ||
1132 | (MsgType - EAPOL_PAIR_MSG_4))); | ||
1133 | } | ||
1134 | |||
1135 | hex_dump("Received MIC", rcvd_mic, LEN_KEY_DESC_MIC); | ||
1136 | hex_dump("Desired MIC", mic, LEN_KEY_DESC_MIC); | ||
1137 | |||
1138 | return FALSE; | ||
1139 | } | ||
1140 | } | ||
1141 | /* 1. Decrypt the Key Data field if GTK is included. */ | ||
1142 | /* 2. Extract the context of the Key Data field if it exist. */ | ||
1143 | /* The field in pairwise_msg_2_WPA1(WPA2) & pairwise_msg_3_WPA1 is clear. */ | ||
1144 | /* The field in group_msg_1_WPA1(WPA2) & pairwise_msg_3_WPA2 is encrypted. */ | ||
1145 | if (CONV_ARRARY_TO_u16(pMsg->KeyDesc.KeyDataLen) > 0) { | ||
1146 | /* Decrypt this field */ | ||
1147 | if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) | ||
1148 | || (MsgType == EAPOL_GROUP_MSG_1)) { | ||
1149 | if ((EapolKeyInfo.KeyDescVer == DESC_TYPE_AES)) { | ||
1150 | /* AES */ | ||
1151 | AES_GTK_KEY_UNWRAP(&pEntry->PTK[16], KEYDATA, | ||
1152 | CONV_ARRARY_TO_u16(pMsg-> | ||
1153 | KeyDesc. | ||
1154 | KeyDataLen), | ||
1155 | pMsg->KeyDesc.KeyData); | ||
1156 | } else { | ||
1157 | int i; | ||
1158 | u8 Key[32]; | ||
1159 | /* Decrypt TKIP GTK */ | ||
1160 | /* Construct 32 bytes RC4 Key */ | ||
1161 | NdisMoveMemory(Key, pMsg->KeyDesc.KeyIv, 16); | ||
1162 | NdisMoveMemory(&Key[16], &pEntry->PTK[16], 16); | ||
1163 | ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, Key, | ||
1164 | 32); | ||
1165 | /*discard first 256 bytes */ | ||
1166 | for (i = 0; i < 256; i++) | ||
1167 | ARCFOUR_BYTE(&pAd->PrivateInfo. | ||
1168 | WEPCONTEXT); | ||
1169 | /* Decrypt GTK. Becareful, there is no ICV to check the result is correct or not */ | ||
1170 | ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, | ||
1171 | KEYDATA, pMsg->KeyDesc.KeyData, | ||
1172 | CONV_ARRARY_TO_u16(pMsg-> | ||
1173 | KeyDesc. | ||
1174 | KeyDataLen)); | ||
1175 | } | ||
1176 | |||
1177 | if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)) | ||
1178 | GroupKeyIndex = EapolKeyInfo.KeyIndex; | ||
1179 | |||
1180 | } else if ((MsgType == EAPOL_PAIR_MSG_2) | ||
1181 | || (MsgType == EAPOL_PAIR_MSG_3 && !bWPA2)) { | ||
1182 | NdisMoveMemory(KEYDATA, pMsg->KeyDesc.KeyData, | ||
1183 | CONV_ARRARY_TO_u16(pMsg->KeyDesc. | ||
1184 | KeyDataLen)); | ||
1185 | } else { | ||
1186 | |||
1187 | return TRUE; | ||
1188 | } | ||
1189 | |||
1190 | /* Parse Key Data field to */ | ||
1191 | /* 1. verify RSN IE for pairwise_msg_2_WPA1(WPA2) ,pairwise_msg_3_WPA1(WPA2) */ | ||
1192 | /* 2. verify KDE format for pairwise_msg_3_WPA2, group_msg_1_WPA2 */ | ||
1193 | /* 3. update shared key for pairwise_msg_3_WPA2, group_msg_1_WPA1(WPA2) */ | ||
1194 | if (!RTMPParseEapolKeyData(pAd, KEYDATA, | ||
1195 | CONV_ARRARY_TO_u16(pMsg->KeyDesc. | ||
1196 | KeyDataLen), | ||
1197 | GroupKeyIndex, MsgType, bWPA2, | ||
1198 | pEntry)) { | ||
1199 | return FALSE; | ||
1200 | } | ||
1201 | } | ||
1202 | |||
1203 | return TRUE; | ||
1204 | |||
1205 | } | ||
diff --git a/drivers/staging/rt2860/common/cmm_sync.c b/drivers/staging/rt2860/common/cmm_sync.c deleted file mode 100644 index aefe1b77465..00000000000 --- a/drivers/staging/rt2860/common/cmm_sync.c +++ /dev/null | |||
@@ -1,718 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | |||
27 | Module Name: | ||
28 | cmm_sync.c | ||
29 | |||
30 | Abstract: | ||
31 | |||
32 | Revision History: | ||
33 | Who When What | ||
34 | -------- ---------- ---------------------------------------------- | ||
35 | John Chang 2004-09-01 modified for rt2561/2661 | ||
36 | */ | ||
37 | #include "../rt_config.h" | ||
38 | |||
39 | /* 2.4 Ghz channel plan index in the TxPower arrays. */ | ||
40 | #define BG_BAND_REGION_0_START 0 /* 1,2,3,4,5,6,7,8,9,10,11 */ | ||
41 | #define BG_BAND_REGION_0_SIZE 11 | ||
42 | #define BG_BAND_REGION_1_START 0 /* 1,2,3,4,5,6,7,8,9,10,11,12,13 */ | ||
43 | #define BG_BAND_REGION_1_SIZE 13 | ||
44 | #define BG_BAND_REGION_2_START 9 /* 10,11 */ | ||
45 | #define BG_BAND_REGION_2_SIZE 2 | ||
46 | #define BG_BAND_REGION_3_START 9 /* 10,11,12,13 */ | ||
47 | #define BG_BAND_REGION_3_SIZE 4 | ||
48 | #define BG_BAND_REGION_4_START 13 /* 14 */ | ||
49 | #define BG_BAND_REGION_4_SIZE 1 | ||
50 | #define BG_BAND_REGION_5_START 0 /* 1,2,3,4,5,6,7,8,9,10,11,12,13,14 */ | ||
51 | #define BG_BAND_REGION_5_SIZE 14 | ||
52 | #define BG_BAND_REGION_6_START 2 /* 3,4,5,6,7,8,9 */ | ||
53 | #define BG_BAND_REGION_6_SIZE 7 | ||
54 | #define BG_BAND_REGION_7_START 4 /* 5,6,7,8,9,10,11,12,13 */ | ||
55 | #define BG_BAND_REGION_7_SIZE 9 | ||
56 | #define BG_BAND_REGION_31_START 0 /* 1,2,3,4,5,6,7,8,9,10,11,12,13,14 */ | ||
57 | #define BG_BAND_REGION_31_SIZE 14 | ||
58 | |||
59 | /* 5 Ghz channel plan index in the TxPower arrays. */ | ||
60 | u8 A_BAND_REGION_0_CHANNEL_LIST[] = | ||
61 | { 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165 }; | ||
62 | u8 A_BAND_REGION_1_CHANNEL_LIST[] = | ||
63 | { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, | ||
64 | 132, 136, 140 }; | ||
65 | u8 A_BAND_REGION_2_CHANNEL_LIST[] = { 36, 40, 44, 48, 52, 56, 60, 64 }; | ||
66 | u8 A_BAND_REGION_3_CHANNEL_LIST[] = { 52, 56, 60, 64, 149, 153, 157, 161 }; | ||
67 | u8 A_BAND_REGION_4_CHANNEL_LIST[] = { 149, 153, 157, 161, 165 }; | ||
68 | u8 A_BAND_REGION_5_CHANNEL_LIST[] = { 149, 153, 157, 161 }; | ||
69 | u8 A_BAND_REGION_6_CHANNEL_LIST[] = { 36, 40, 44, 48 }; | ||
70 | u8 A_BAND_REGION_7_CHANNEL_LIST[] = | ||
71 | { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, | ||
72 | 132, 136, 140, 149, 153, 157, 161, 165, 169, 173 }; | ||
73 | u8 A_BAND_REGION_8_CHANNEL_LIST[] = { 52, 56, 60, 64 }; | ||
74 | u8 A_BAND_REGION_9_CHANNEL_LIST[] = | ||
75 | { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, | ||
76 | 149, 153, 157, 161, 165 }; | ||
77 | u8 A_BAND_REGION_10_CHANNEL_LIST[] = | ||
78 | { 36, 40, 44, 48, 149, 153, 157, 161, 165 }; | ||
79 | u8 A_BAND_REGION_11_CHANNEL_LIST[] = | ||
80 | { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 149, 153, | ||
81 | 157, 161 }; | ||
82 | u8 A_BAND_REGION_12_CHANNEL_LIST[] = | ||
83 | { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, | ||
84 | 132, 136, 140 }; | ||
85 | u8 A_BAND_REGION_13_CHANNEL_LIST[] = | ||
86 | { 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, | ||
87 | 149, 153, 157, 161 }; | ||
88 | u8 A_BAND_REGION_14_CHANNEL_LIST[] = | ||
89 | { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, | ||
90 | 153, 157, 161, 165 }; | ||
91 | u8 A_BAND_REGION_15_CHANNEL_LIST[] = { 149, 153, 157, 161, 165, 169, 173 }; | ||
92 | |||
93 | /*BaSizeArray follows the 802.11n definition as MaxRxFactor. 2^(13+factor) bytes. When factor =0, it's about Ba buffer size =8. */ | ||
94 | u8 BaSizeArray[4] = { 8, 16, 32, 64 }; | ||
95 | |||
96 | /* | ||
97 | ========================================================================== | ||
98 | Description: | ||
99 | Update StaCfg->ChannelList[] according to 1) Country Region 2) RF IC type, | ||
100 | and 3) PHY-mode user selected. | ||
101 | The outcome is used by driver when doing site survey. | ||
102 | |||
103 | IRQL = PASSIVE_LEVEL | ||
104 | IRQL = DISPATCH_LEVEL | ||
105 | |||
106 | ========================================================================== | ||
107 | */ | ||
108 | void BuildChannelList(struct rt_rtmp_adapter *pAd) | ||
109 | { | ||
110 | u8 i, j, index = 0, num = 0; | ||
111 | u8 *pChannelList = NULL; | ||
112 | |||
113 | NdisZeroMemory(pAd->ChannelList, | ||
114 | MAX_NUM_OF_CHANNELS * sizeof(struct rt_channel_tx_power)); | ||
115 | |||
116 | /* if not 11a-only mode, channel list starts from 2.4Ghz band */ | ||
117 | if ((pAd->CommonCfg.PhyMode != PHY_11A) | ||
118 | && (pAd->CommonCfg.PhyMode != PHY_11AN_MIXED) | ||
119 | && (pAd->CommonCfg.PhyMode != PHY_11N_5G) | ||
120 | ) { | ||
121 | switch (pAd->CommonCfg.CountryRegion & 0x7f) { | ||
122 | case REGION_0_BG_BAND: /* 1 -11 */ | ||
123 | NdisMoveMemory(&pAd->ChannelList[index], | ||
124 | &pAd->TxPower[BG_BAND_REGION_0_START], | ||
125 | sizeof(struct rt_channel_tx_power) * | ||
126 | BG_BAND_REGION_0_SIZE); | ||
127 | index += BG_BAND_REGION_0_SIZE; | ||
128 | break; | ||
129 | case REGION_1_BG_BAND: /* 1 - 13 */ | ||
130 | NdisMoveMemory(&pAd->ChannelList[index], | ||
131 | &pAd->TxPower[BG_BAND_REGION_1_START], | ||
132 | sizeof(struct rt_channel_tx_power) * | ||
133 | BG_BAND_REGION_1_SIZE); | ||
134 | index += BG_BAND_REGION_1_SIZE; | ||
135 | break; | ||
136 | case REGION_2_BG_BAND: /* 10 - 11 */ | ||
137 | NdisMoveMemory(&pAd->ChannelList[index], | ||
138 | &pAd->TxPower[BG_BAND_REGION_2_START], | ||
139 | sizeof(struct rt_channel_tx_power) * | ||
140 | BG_BAND_REGION_2_SIZE); | ||
141 | index += BG_BAND_REGION_2_SIZE; | ||
142 | break; | ||
143 | case REGION_3_BG_BAND: /* 10 - 13 */ | ||
144 | NdisMoveMemory(&pAd->ChannelList[index], | ||
145 | &pAd->TxPower[BG_BAND_REGION_3_START], | ||
146 | sizeof(struct rt_channel_tx_power) * | ||
147 | BG_BAND_REGION_3_SIZE); | ||
148 | index += BG_BAND_REGION_3_SIZE; | ||
149 | break; | ||
150 | case REGION_4_BG_BAND: /* 14 */ | ||
151 | NdisMoveMemory(&pAd->ChannelList[index], | ||
152 | &pAd->TxPower[BG_BAND_REGION_4_START], | ||
153 | sizeof(struct rt_channel_tx_power) * | ||
154 | BG_BAND_REGION_4_SIZE); | ||
155 | index += BG_BAND_REGION_4_SIZE; | ||
156 | break; | ||
157 | case REGION_5_BG_BAND: /* 1 - 14 */ | ||
158 | NdisMoveMemory(&pAd->ChannelList[index], | ||
159 | &pAd->TxPower[BG_BAND_REGION_5_START], | ||
160 | sizeof(struct rt_channel_tx_power) * | ||
161 | BG_BAND_REGION_5_SIZE); | ||
162 | index += BG_BAND_REGION_5_SIZE; | ||
163 | break; | ||
164 | case REGION_6_BG_BAND: /* 3 - 9 */ | ||
165 | NdisMoveMemory(&pAd->ChannelList[index], | ||
166 | &pAd->TxPower[BG_BAND_REGION_6_START], | ||
167 | sizeof(struct rt_channel_tx_power) * | ||
168 | BG_BAND_REGION_6_SIZE); | ||
169 | index += BG_BAND_REGION_6_SIZE; | ||
170 | break; | ||
171 | case REGION_7_BG_BAND: /* 5 - 13 */ | ||
172 | NdisMoveMemory(&pAd->ChannelList[index], | ||
173 | &pAd->TxPower[BG_BAND_REGION_7_START], | ||
174 | sizeof(struct rt_channel_tx_power) * | ||
175 | BG_BAND_REGION_7_SIZE); | ||
176 | index += BG_BAND_REGION_7_SIZE; | ||
177 | break; | ||
178 | case REGION_31_BG_BAND: /* 1 - 14 */ | ||
179 | NdisMoveMemory(&pAd->ChannelList[index], | ||
180 | &pAd->TxPower[BG_BAND_REGION_31_START], | ||
181 | sizeof(struct rt_channel_tx_power) * | ||
182 | BG_BAND_REGION_31_SIZE); | ||
183 | index += BG_BAND_REGION_31_SIZE; | ||
184 | break; | ||
185 | default: /* Error. should never happen */ | ||
186 | break; | ||
187 | } | ||
188 | for (i = 0; i < index; i++) | ||
189 | pAd->ChannelList[i].MaxTxPwr = 20; | ||
190 | } | ||
191 | |||
192 | if ((pAd->CommonCfg.PhyMode == PHY_11A) | ||
193 | || (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) | ||
194 | || (pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) | ||
195 | || (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED) | ||
196 | || (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) | ||
197 | || (pAd->CommonCfg.PhyMode == PHY_11N_5G) | ||
198 | ) { | ||
199 | switch (pAd->CommonCfg.CountryRegionForABand & 0x7f) { | ||
200 | case REGION_0_A_BAND: | ||
201 | num = | ||
202 | sizeof(A_BAND_REGION_0_CHANNEL_LIST) / | ||
203 | sizeof(u8); | ||
204 | pChannelList = A_BAND_REGION_0_CHANNEL_LIST; | ||
205 | break; | ||
206 | case REGION_1_A_BAND: | ||
207 | num = | ||
208 | sizeof(A_BAND_REGION_1_CHANNEL_LIST) / | ||
209 | sizeof(u8); | ||
210 | pChannelList = A_BAND_REGION_1_CHANNEL_LIST; | ||
211 | break; | ||
212 | case REGION_2_A_BAND: | ||
213 | num = | ||
214 | sizeof(A_BAND_REGION_2_CHANNEL_LIST) / | ||
215 | sizeof(u8); | ||
216 | pChannelList = A_BAND_REGION_2_CHANNEL_LIST; | ||
217 | break; | ||
218 | case REGION_3_A_BAND: | ||
219 | num = | ||
220 | sizeof(A_BAND_REGION_3_CHANNEL_LIST) / | ||
221 | sizeof(u8); | ||
222 | pChannelList = A_BAND_REGION_3_CHANNEL_LIST; | ||
223 | break; | ||
224 | case REGION_4_A_BAND: | ||
225 | num = | ||
226 | sizeof(A_BAND_REGION_4_CHANNEL_LIST) / | ||
227 | sizeof(u8); | ||
228 | pChannelList = A_BAND_REGION_4_CHANNEL_LIST; | ||
229 | break; | ||
230 | case REGION_5_A_BAND: | ||
231 | num = | ||
232 | sizeof(A_BAND_REGION_5_CHANNEL_LIST) / | ||
233 | sizeof(u8); | ||
234 | pChannelList = A_BAND_REGION_5_CHANNEL_LIST; | ||
235 | break; | ||
236 | case REGION_6_A_BAND: | ||
237 | num = | ||
238 | sizeof(A_BAND_REGION_6_CHANNEL_LIST) / | ||
239 | sizeof(u8); | ||
240 | pChannelList = A_BAND_REGION_6_CHANNEL_LIST; | ||
241 | break; | ||
242 | case REGION_7_A_BAND: | ||
243 | num = | ||
244 | sizeof(A_BAND_REGION_7_CHANNEL_LIST) / | ||
245 | sizeof(u8); | ||
246 | pChannelList = A_BAND_REGION_7_CHANNEL_LIST; | ||
247 | break; | ||
248 | case REGION_8_A_BAND: | ||
249 | num = | ||
250 | sizeof(A_BAND_REGION_8_CHANNEL_LIST) / | ||
251 | sizeof(u8); | ||
252 | pChannelList = A_BAND_REGION_8_CHANNEL_LIST; | ||
253 | break; | ||
254 | case REGION_9_A_BAND: | ||
255 | num = | ||
256 | sizeof(A_BAND_REGION_9_CHANNEL_LIST) / | ||
257 | sizeof(u8); | ||
258 | pChannelList = A_BAND_REGION_9_CHANNEL_LIST; | ||
259 | break; | ||
260 | |||
261 | case REGION_10_A_BAND: | ||
262 | num = | ||
263 | sizeof(A_BAND_REGION_10_CHANNEL_LIST) / | ||
264 | sizeof(u8); | ||
265 | pChannelList = A_BAND_REGION_10_CHANNEL_LIST; | ||
266 | break; | ||
267 | |||
268 | case REGION_11_A_BAND: | ||
269 | num = | ||
270 | sizeof(A_BAND_REGION_11_CHANNEL_LIST) / | ||
271 | sizeof(u8); | ||
272 | pChannelList = A_BAND_REGION_11_CHANNEL_LIST; | ||
273 | break; | ||
274 | case REGION_12_A_BAND: | ||
275 | num = | ||
276 | sizeof(A_BAND_REGION_12_CHANNEL_LIST) / | ||
277 | sizeof(u8); | ||
278 | pChannelList = A_BAND_REGION_12_CHANNEL_LIST; | ||
279 | break; | ||
280 | case REGION_13_A_BAND: | ||
281 | num = | ||
282 | sizeof(A_BAND_REGION_13_CHANNEL_LIST) / | ||
283 | sizeof(u8); | ||
284 | pChannelList = A_BAND_REGION_13_CHANNEL_LIST; | ||
285 | break; | ||
286 | case REGION_14_A_BAND: | ||
287 | num = | ||
288 | sizeof(A_BAND_REGION_14_CHANNEL_LIST) / | ||
289 | sizeof(u8); | ||
290 | pChannelList = A_BAND_REGION_14_CHANNEL_LIST; | ||
291 | break; | ||
292 | case REGION_15_A_BAND: | ||
293 | num = | ||
294 | sizeof(A_BAND_REGION_15_CHANNEL_LIST) / | ||
295 | sizeof(u8); | ||
296 | pChannelList = A_BAND_REGION_15_CHANNEL_LIST; | ||
297 | break; | ||
298 | default: /* Error. should never happen */ | ||
299 | DBGPRINT(RT_DEBUG_WARN, | ||
300 | ("countryregion=%d not support", | ||
301 | pAd->CommonCfg.CountryRegionForABand)); | ||
302 | break; | ||
303 | } | ||
304 | |||
305 | if (num != 0) { | ||
306 | u8 RadarCh[15] = | ||
307 | { 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, | ||
308 | 128, 132, 136, 140 }; | ||
309 | for (i = 0; i < num; i++) { | ||
310 | for (j = 0; j < MAX_NUM_OF_CHANNELS; j++) { | ||
311 | if (pChannelList[i] == | ||
312 | pAd->TxPower[j].Channel) | ||
313 | NdisMoveMemory(&pAd-> | ||
314 | ChannelList[index | ||
315 | + i], | ||
316 | &pAd->TxPower[j], | ||
317 | sizeof | ||
318 | (struct rt_channel_tx_power)); | ||
319 | } | ||
320 | for (j = 0; j < 15; j++) { | ||
321 | if (pChannelList[i] == RadarCh[j]) | ||
322 | pAd->ChannelList[index + | ||
323 | i].DfsReq = | ||
324 | TRUE; | ||
325 | } | ||
326 | pAd->ChannelList[index + i].MaxTxPwr = 20; | ||
327 | } | ||
328 | index += num; | ||
329 | } | ||
330 | } | ||
331 | |||
332 | pAd->ChannelListNum = index; | ||
333 | DBGPRINT(RT_DEBUG_TRACE, | ||
334 | ("country code=%d/%d, RFIC=%d, PHY mode=%d, support %d channels\n", | ||
335 | pAd->CommonCfg.CountryRegion, | ||
336 | pAd->CommonCfg.CountryRegionForABand, pAd->RfIcType, | ||
337 | pAd->CommonCfg.PhyMode, pAd->ChannelListNum)); | ||
338 | #ifdef DBG | ||
339 | for (i = 0; i < pAd->ChannelListNum; i++) { | ||
340 | DBGPRINT_RAW(RT_DEBUG_TRACE, | ||
341 | ("BuildChannel # %d :: Pwr0 = %d, Pwr1 =%d, \n ", | ||
342 | pAd->ChannelList[i].Channel, | ||
343 | pAd->ChannelList[i].Power, | ||
344 | pAd->ChannelList[i].Power2)); | ||
345 | } | ||
346 | #endif | ||
347 | } | ||
348 | |||
349 | /* | ||
350 | ========================================================================== | ||
351 | Description: | ||
352 | This routine return the first channel number according to the country | ||
353 | code selection and RF IC selection (signal band or dual band). It is called | ||
354 | whenever driver need to start a site survey of all supported channels. | ||
355 | Return: | ||
356 | ch - the first channel number of current country code setting | ||
357 | |||
358 | IRQL = PASSIVE_LEVEL | ||
359 | |||
360 | ========================================================================== | ||
361 | */ | ||
362 | u8 FirstChannel(struct rt_rtmp_adapter *pAd) | ||
363 | { | ||
364 | return pAd->ChannelList[0].Channel; | ||
365 | } | ||
366 | |||
367 | /* | ||
368 | ========================================================================== | ||
369 | Description: | ||
370 | This routine returns the next channel number. This routine is called | ||
371 | during driver need to start a site survey of all supported channels. | ||
372 | Return: | ||
373 | next_channel - the next channel number valid in current country code setting. | ||
374 | Note: | ||
375 | return 0 if no more next channel | ||
376 | ========================================================================== | ||
377 | */ | ||
378 | u8 NextChannel(struct rt_rtmp_adapter *pAd, u8 channel) | ||
379 | { | ||
380 | int i; | ||
381 | u8 next_channel = 0; | ||
382 | |||
383 | for (i = 0; i < (pAd->ChannelListNum - 1); i++) | ||
384 | if (channel == pAd->ChannelList[i].Channel) { | ||
385 | next_channel = pAd->ChannelList[i + 1].Channel; | ||
386 | break; | ||
387 | } | ||
388 | return next_channel; | ||
389 | } | ||
390 | |||
391 | /* | ||
392 | ========================================================================== | ||
393 | Description: | ||
394 | This routine is for Cisco Compatible Extensions 2.X | ||
395 | Spec31. AP Control of Client Transmit Power | ||
396 | Return: | ||
397 | None | ||
398 | Note: | ||
399 | Required by Aironet dBm(mW) | ||
400 | 0dBm(1mW), 1dBm(5mW), 13dBm(20mW), 15dBm(30mW), | ||
401 | 17dBm(50mw), 20dBm(100mW) | ||
402 | |||
403 | We supported | ||
404 | 3dBm(Lowest), 6dBm(10%), 9dBm(25%), 12dBm(50%), | ||
405 | 14dBm(75%), 15dBm(100%) | ||
406 | |||
407 | The client station's actual transmit power shall be within +/- 5dB of | ||
408 | the minimum value or next lower value. | ||
409 | ========================================================================== | ||
410 | */ | ||
411 | void ChangeToCellPowerLimit(struct rt_rtmp_adapter *pAd, | ||
412 | u8 AironetCellPowerLimit) | ||
413 | { | ||
414 | /*valud 0xFF means that hasn't found power limit information */ | ||
415 | /*from the AP's Beacon/Probe response. */ | ||
416 | if (AironetCellPowerLimit == 0xFF) | ||
417 | return; | ||
418 | |||
419 | if (AironetCellPowerLimit < 6) /*Used Lowest Power Percentage. */ | ||
420 | pAd->CommonCfg.TxPowerPercentage = 6; | ||
421 | else if (AironetCellPowerLimit < 9) | ||
422 | pAd->CommonCfg.TxPowerPercentage = 10; | ||
423 | else if (AironetCellPowerLimit < 12) | ||
424 | pAd->CommonCfg.TxPowerPercentage = 25; | ||
425 | else if (AironetCellPowerLimit < 14) | ||
426 | pAd->CommonCfg.TxPowerPercentage = 50; | ||
427 | else if (AironetCellPowerLimit < 15) | ||
428 | pAd->CommonCfg.TxPowerPercentage = 75; | ||
429 | else | ||
430 | pAd->CommonCfg.TxPowerPercentage = 100; /*else used maximum */ | ||
431 | |||
432 | if (pAd->CommonCfg.TxPowerPercentage > pAd->CommonCfg.TxPowerDefault) | ||
433 | pAd->CommonCfg.TxPowerPercentage = | ||
434 | pAd->CommonCfg.TxPowerDefault; | ||
435 | |||
436 | } | ||
437 | |||
438 | char ConvertToRssi(struct rt_rtmp_adapter *pAd, char Rssi, u8 RssiNumber) | ||
439 | { | ||
440 | u8 RssiOffset, LNAGain; | ||
441 | |||
442 | /* Rssi equals to zero should be an invalid value */ | ||
443 | if (Rssi == 0) | ||
444 | return -99; | ||
445 | |||
446 | LNAGain = GET_LNA_GAIN(pAd); | ||
447 | if (pAd->LatchRfRegs.Channel > 14) { | ||
448 | if (RssiNumber == 0) | ||
449 | RssiOffset = pAd->ARssiOffset0; | ||
450 | else if (RssiNumber == 1) | ||
451 | RssiOffset = pAd->ARssiOffset1; | ||
452 | else | ||
453 | RssiOffset = pAd->ARssiOffset2; | ||
454 | } else { | ||
455 | if (RssiNumber == 0) | ||
456 | RssiOffset = pAd->BGRssiOffset0; | ||
457 | else if (RssiNumber == 1) | ||
458 | RssiOffset = pAd->BGRssiOffset1; | ||
459 | else | ||
460 | RssiOffset = pAd->BGRssiOffset2; | ||
461 | } | ||
462 | |||
463 | return (-12 - RssiOffset - LNAGain - Rssi); | ||
464 | } | ||
465 | |||
466 | /* | ||
467 | ========================================================================== | ||
468 | Description: | ||
469 | Scan next channel | ||
470 | ========================================================================== | ||
471 | */ | ||
472 | void ScanNextChannel(struct rt_rtmp_adapter *pAd) | ||
473 | { | ||
474 | struct rt_header_802_11 Hdr80211; | ||
475 | u8 *pOutBuffer = NULL; | ||
476 | int NStatus; | ||
477 | unsigned long FrameLen = 0; | ||
478 | u8 SsidLen = 0, ScanType = pAd->MlmeAux.ScanType, BBPValue = 0; | ||
479 | u16 Status; | ||
480 | struct rt_header_802_11 * pHdr80211; | ||
481 | u32 ScanTimeIn5gChannel = SHORT_CHANNEL_TIME; | ||
482 | |||
483 | { | ||
484 | if (MONITOR_ON(pAd)) | ||
485 | return; | ||
486 | } | ||
487 | |||
488 | if (pAd->MlmeAux.Channel == 0) { | ||
489 | if ((pAd->CommonCfg.BBPCurrentBW == BW_40) | ||
490 | && (INFRA_ON(pAd) | ||
491 | || (pAd->OpMode == OPMODE_AP)) | ||
492 | ) { | ||
493 | AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, | ||
494 | FALSE); | ||
495 | AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); | ||
496 | RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); | ||
497 | BBPValue &= (~0x18); | ||
498 | BBPValue |= 0x10; | ||
499 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); | ||
500 | DBGPRINT(RT_DEBUG_TRACE, | ||
501 | ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n", | ||
502 | pAd->CommonCfg.CentralChannel, | ||
503 | pAd->ScanTab.BssNr)); | ||
504 | } else { | ||
505 | AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); | ||
506 | AsicLockChannel(pAd, pAd->CommonCfg.Channel); | ||
507 | DBGPRINT(RT_DEBUG_TRACE, | ||
508 | ("SYNC - End of SCAN, restore to channel %d, Total BSS[%02d]\n", | ||
509 | pAd->CommonCfg.Channel, pAd->ScanTab.BssNr)); | ||
510 | } | ||
511 | |||
512 | { | ||
513 | /* */ | ||
514 | /* To prevent data lost. */ | ||
515 | /* Send an NULL data with turned PSM bit on to current associated AP before SCAN progress. */ | ||
516 | /* Now, we need to send an NULL data with turned PSM bit off to AP, when scan progress done */ | ||
517 | /* */ | ||
518 | if (OPSTATUS_TEST_FLAG | ||
519 | (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) | ||
520 | && (INFRA_ON(pAd))) { | ||
521 | NStatus = | ||
522 | MlmeAllocateMemory(pAd, | ||
523 | (void *)& pOutBuffer); | ||
524 | if (NStatus == NDIS_STATUS_SUCCESS) { | ||
525 | pHdr80211 = (struct rt_header_802_11 *) pOutBuffer; | ||
526 | MgtMacHeaderInit(pAd, pHdr80211, | ||
527 | SUBTYPE_NULL_FUNC, 1, | ||
528 | pAd->CommonCfg.Bssid, | ||
529 | pAd->CommonCfg.Bssid); | ||
530 | pHdr80211->Duration = 0; | ||
531 | pHdr80211->FC.Type = BTYPE_DATA; | ||
532 | pHdr80211->FC.PwrMgmt = | ||
533 | (pAd->StaCfg.Psm == PWR_SAVE); | ||
534 | |||
535 | /* Send using priority queue */ | ||
536 | MiniportMMRequest(pAd, 0, pOutBuffer, | ||
537 | sizeof | ||
538 | (struct rt_header_802_11)); | ||
539 | DBGPRINT(RT_DEBUG_TRACE, | ||
540 | ("MlmeScanReqAction -- Send PSM Data frame\n")); | ||
541 | MlmeFreeMemory(pAd, pOutBuffer); | ||
542 | RTMPusecDelay(5000); | ||
543 | } | ||
544 | } | ||
545 | |||
546 | pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; | ||
547 | Status = MLME_SUCCESS; | ||
548 | MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, | ||
549 | 2, &Status); | ||
550 | } | ||
551 | |||
552 | RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); | ||
553 | } | ||
554 | #ifdef RTMP_MAC_USB | ||
555 | else if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) | ||
556 | && (pAd->OpMode == OPMODE_STA)) { | ||
557 | pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; | ||
558 | MlmeCntlConfirm(pAd, MT2_SCAN_CONF, MLME_FAIL_NO_RESOURCE); | ||
559 | } | ||
560 | #endif /* RTMP_MAC_USB // */ | ||
561 | else { | ||
562 | { | ||
563 | /* BBP and RF are not accessible in PS mode, we has to wake them up first */ | ||
564 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) | ||
565 | AsicForceWakeup(pAd, TRUE); | ||
566 | |||
567 | /* leave PSM during scanning. otherwise we may lost ProbeRsp & BEACON */ | ||
568 | if (pAd->StaCfg.Psm == PWR_SAVE) | ||
569 | RTMP_SET_PSM_BIT(pAd, PWR_ACTIVE); | ||
570 | } | ||
571 | |||
572 | AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, TRUE); | ||
573 | AsicLockChannel(pAd, pAd->MlmeAux.Channel); | ||
574 | |||
575 | { | ||
576 | if (pAd->MlmeAux.Channel > 14) { | ||
577 | if ((pAd->CommonCfg.bIEEE80211H == 1) | ||
578 | && RadarChannelCheck(pAd, | ||
579 | pAd->MlmeAux. | ||
580 | Channel)) { | ||
581 | ScanType = SCAN_PASSIVE; | ||
582 | ScanTimeIn5gChannel = MIN_CHANNEL_TIME; | ||
583 | } | ||
584 | } | ||
585 | } | ||
586 | |||
587 | /*Global country domain(ch1-11:active scan, ch12-14 passive scan) */ | ||
588 | if ((pAd->MlmeAux.Channel <= 14) && (pAd->MlmeAux.Channel >= 12) | ||
589 | && ((pAd->CommonCfg.CountryRegion & 0x7f) == | ||
590 | REGION_31_BG_BAND)) { | ||
591 | ScanType = SCAN_PASSIVE; | ||
592 | } | ||
593 | /* We need to shorten active scan time in order for WZC connect issue */ | ||
594 | /* Chnage the channel scan time for CISCO stuff based on its IAPP announcement */ | ||
595 | if (ScanType == FAST_SCAN_ACTIVE) | ||
596 | RTMPSetTimer(&pAd->MlmeAux.ScanTimer, | ||
597 | FAST_ACTIVE_SCAN_TIME); | ||
598 | else /* must be SCAN_PASSIVE or SCAN_ACTIVE */ | ||
599 | { | ||
600 | if ((pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) | ||
601 | || (pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) | ||
602 | || (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) | ||
603 | ) { | ||
604 | if (pAd->MlmeAux.Channel > 14) | ||
605 | RTMPSetTimer(&pAd->MlmeAux.ScanTimer, | ||
606 | ScanTimeIn5gChannel); | ||
607 | else | ||
608 | RTMPSetTimer(&pAd->MlmeAux.ScanTimer, | ||
609 | MIN_CHANNEL_TIME); | ||
610 | } else | ||
611 | RTMPSetTimer(&pAd->MlmeAux.ScanTimer, | ||
612 | MAX_CHANNEL_TIME); | ||
613 | } | ||
614 | |||
615 | if ((ScanType == SCAN_ACTIVE) | ||
616 | || (ScanType == FAST_SCAN_ACTIVE) | ||
617 | ) { | ||
618 | NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ | ||
619 | if (NStatus != NDIS_STATUS_SUCCESS) { | ||
620 | DBGPRINT(RT_DEBUG_TRACE, | ||
621 | ("SYNC - ScanNextChannel() allocate memory fail\n")); | ||
622 | |||
623 | { | ||
624 | pAd->Mlme.SyncMachine.CurrState = | ||
625 | SYNC_IDLE; | ||
626 | Status = MLME_FAIL_NO_RESOURCE; | ||
627 | MlmeEnqueue(pAd, | ||
628 | MLME_CNTL_STATE_MACHINE, | ||
629 | MT2_SCAN_CONF, 2, &Status); | ||
630 | } | ||
631 | |||
632 | return; | ||
633 | } | ||
634 | /* There is no need to send broadcast probe request if active scan is in effect. */ | ||
635 | if ((ScanType == SCAN_ACTIVE) | ||
636 | || (ScanType == FAST_SCAN_ACTIVE) | ||
637 | ) | ||
638 | SsidLen = pAd->MlmeAux.SsidLen; | ||
639 | else | ||
640 | SsidLen = 0; | ||
641 | |||
642 | MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, | ||
643 | BROADCAST_ADDR, BROADCAST_ADDR); | ||
644 | MakeOutgoingFrame(pOutBuffer, &FrameLen, | ||
645 | sizeof(struct rt_header_802_11), &Hdr80211, 1, | ||
646 | &SsidIe, 1, &SsidLen, SsidLen, | ||
647 | pAd->MlmeAux.Ssid, 1, &SupRateIe, 1, | ||
648 | &pAd->CommonCfg.SupRateLen, | ||
649 | pAd->CommonCfg.SupRateLen, | ||
650 | pAd->CommonCfg.SupRate, END_OF_ARGS); | ||
651 | |||
652 | if (pAd->CommonCfg.ExtRateLen) { | ||
653 | unsigned long Tmp; | ||
654 | MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, | ||
655 | 1, &ExtRateIe, | ||
656 | 1, &pAd->CommonCfg.ExtRateLen, | ||
657 | pAd->CommonCfg.ExtRateLen, | ||
658 | pAd->CommonCfg.ExtRate, | ||
659 | END_OF_ARGS); | ||
660 | FrameLen += Tmp; | ||
661 | } | ||
662 | |||
663 | if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) { | ||
664 | unsigned long Tmp; | ||
665 | u8 HtLen; | ||
666 | u8 BROADCOM[4] = { 0x0, 0x90, 0x4c, 0x33 }; | ||
667 | |||
668 | if (pAd->bBroadComHT == TRUE) { | ||
669 | HtLen = | ||
670 | pAd->MlmeAux.HtCapabilityLen + 4; | ||
671 | |||
672 | MakeOutgoingFrame(pOutBuffer + FrameLen, | ||
673 | &Tmp, 1, &WpaIe, 1, | ||
674 | &HtLen, 4, | ||
675 | &BROADCOM[0], | ||
676 | pAd->MlmeAux. | ||
677 | HtCapabilityLen, | ||
678 | &pAd->MlmeAux. | ||
679 | HtCapability, | ||
680 | END_OF_ARGS); | ||
681 | } else { | ||
682 | HtLen = pAd->MlmeAux.HtCapabilityLen; | ||
683 | |||
684 | MakeOutgoingFrame(pOutBuffer + FrameLen, | ||
685 | &Tmp, 1, &HtCapIe, 1, | ||
686 | &HtLen, HtLen, | ||
687 | &pAd->CommonCfg. | ||
688 | HtCapability, | ||
689 | END_OF_ARGS); | ||
690 | } | ||
691 | FrameLen += Tmp; | ||
692 | } | ||
693 | |||
694 | MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); | ||
695 | MlmeFreeMemory(pAd, pOutBuffer); | ||
696 | } | ||
697 | /* For SCAN_CISCO_PASSIVE, do nothing and silently wait for beacon or other probe response */ | ||
698 | |||
699 | pAd->Mlme.SyncMachine.CurrState = SCAN_LISTEN; | ||
700 | } | ||
701 | } | ||
702 | |||
703 | void MgtProbReqMacHeaderInit(struct rt_rtmp_adapter *pAd, | ||
704 | struct rt_header_802_11 * pHdr80211, | ||
705 | u8 SubType, | ||
706 | u8 ToDs, u8 *pDA, u8 *pBssid) | ||
707 | { | ||
708 | NdisZeroMemory(pHdr80211, sizeof(struct rt_header_802_11)); | ||
709 | |||
710 | pHdr80211->FC.Type = BTYPE_MGMT; | ||
711 | pHdr80211->FC.SubType = SubType; | ||
712 | if (SubType == SUBTYPE_ACK) | ||
713 | pHdr80211->FC.Type = BTYPE_CNTL; | ||
714 | pHdr80211->FC.ToDs = ToDs; | ||
715 | COPY_MAC_ADDR(pHdr80211->Addr1, pDA); | ||
716 | COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress); | ||
717 | COPY_MAC_ADDR(pHdr80211->Addr3, pBssid); | ||
718 | } | ||
diff --git a/drivers/staging/rt2860/common/cmm_tkip.c b/drivers/staging/rt2860/common/cmm_tkip.c deleted file mode 100644 index 4881ef9ba02..00000000000 --- a/drivers/staging/rt2860/common/cmm_tkip.c +++ /dev/null | |||
@@ -1,833 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | |||
27 | Module Name: | ||
28 | cmm_tkip.c | ||
29 | |||
30 | Abstract: | ||
31 | |||
32 | Revision History: | ||
33 | Who When What | ||
34 | -------- ---------- ---------------------------------------------- | ||
35 | Paul Wu 02-25-02 Initial | ||
36 | */ | ||
37 | |||
38 | #include "../rt_config.h" | ||
39 | |||
40 | /* Rotation functions on 32 bit values */ | ||
41 | #define ROL32( A, n ) \ | ||
42 | ( ((A) << (n)) | ( ((A)>>(32-(n))) & ( (1UL << (n)) - 1 ) ) ) | ||
43 | #define ROR32( A, n ) ROL32( (A), 32-(n) ) | ||
44 | |||
45 | u32 Tkip_Sbox_Lower[256] = { | ||
46 | 0xA5, 0x84, 0x99, 0x8D, 0x0D, 0xBD, 0xB1, 0x54, | ||
47 | 0x50, 0x03, 0xA9, 0x7D, 0x19, 0x62, 0xE6, 0x9A, | ||
48 | 0x45, 0x9D, 0x40, 0x87, 0x15, 0xEB, 0xC9, 0x0B, | ||
49 | 0xEC, 0x67, 0xFD, 0xEA, 0xBF, 0xF7, 0x96, 0x5B, | ||
50 | 0xC2, 0x1C, 0xAE, 0x6A, 0x5A, 0x41, 0x02, 0x4F, | ||
51 | 0x5C, 0xF4, 0x34, 0x08, 0x93, 0x73, 0x53, 0x3F, | ||
52 | 0x0C, 0x52, 0x65, 0x5E, 0x28, 0xA1, 0x0F, 0xB5, | ||
53 | 0x09, 0x36, 0x9B, 0x3D, 0x26, 0x69, 0xCD, 0x9F, | ||
54 | 0x1B, 0x9E, 0x74, 0x2E, 0x2D, 0xB2, 0xEE, 0xFB, | ||
55 | 0xF6, 0x4D, 0x61, 0xCE, 0x7B, 0x3E, 0x71, 0x97, | ||
56 | 0xF5, 0x68, 0x00, 0x2C, 0x60, 0x1F, 0xC8, 0xED, | ||
57 | 0xBE, 0x46, 0xD9, 0x4B, 0xDE, 0xD4, 0xE8, 0x4A, | ||
58 | 0x6B, 0x2A, 0xE5, 0x16, 0xC5, 0xD7, 0x55, 0x94, | ||
59 | 0xCF, 0x10, 0x06, 0x81, 0xF0, 0x44, 0xBA, 0xE3, | ||
60 | 0xF3, 0xFE, 0xC0, 0x8A, 0xAD, 0xBC, 0x48, 0x04, | ||
61 | 0xDF, 0xC1, 0x75, 0x63, 0x30, 0x1A, 0x0E, 0x6D, | ||
62 | 0x4C, 0x14, 0x35, 0x2F, 0xE1, 0xA2, 0xCC, 0x39, | ||
63 | 0x57, 0xF2, 0x82, 0x47, 0xAC, 0xE7, 0x2B, 0x95, | ||
64 | 0xA0, 0x98, 0xD1, 0x7F, 0x66, 0x7E, 0xAB, 0x83, | ||
65 | 0xCA, 0x29, 0xD3, 0x3C, 0x79, 0xE2, 0x1D, 0x76, | ||
66 | 0x3B, 0x56, 0x4E, 0x1E, 0xDB, 0x0A, 0x6C, 0xE4, | ||
67 | 0x5D, 0x6E, 0xEF, 0xA6, 0xA8, 0xA4, 0x37, 0x8B, | ||
68 | 0x32, 0x43, 0x59, 0xB7, 0x8C, 0x64, 0xD2, 0xE0, | ||
69 | 0xB4, 0xFA, 0x07, 0x25, 0xAF, 0x8E, 0xE9, 0x18, | ||
70 | 0xD5, 0x88, 0x6F, 0x72, 0x24, 0xF1, 0xC7, 0x51, | ||
71 | 0x23, 0x7C, 0x9C, 0x21, 0xDD, 0xDC, 0x86, 0x85, | ||
72 | 0x90, 0x42, 0xC4, 0xAA, 0xD8, 0x05, 0x01, 0x12, | ||
73 | 0xA3, 0x5F, 0xF9, 0xD0, 0x91, 0x58, 0x27, 0xB9, | ||
74 | 0x38, 0x13, 0xB3, 0x33, 0xBB, 0x70, 0x89, 0xA7, | ||
75 | 0xB6, 0x22, 0x92, 0x20, 0x49, 0xFF, 0x78, 0x7A, | ||
76 | 0x8F, 0xF8, 0x80, 0x17, 0xDA, 0x31, 0xC6, 0xB8, | ||
77 | 0xC3, 0xB0, 0x77, 0x11, 0xCB, 0xFC, 0xD6, 0x3A | ||
78 | }; | ||
79 | |||
80 | u32 Tkip_Sbox_Upper[256] = { | ||
81 | 0xC6, 0xF8, 0xEE, 0xF6, 0xFF, 0xD6, 0xDE, 0x91, | ||
82 | 0x60, 0x02, 0xCE, 0x56, 0xE7, 0xB5, 0x4D, 0xEC, | ||
83 | 0x8F, 0x1F, 0x89, 0xFA, 0xEF, 0xB2, 0x8E, 0xFB, | ||
84 | 0x41, 0xB3, 0x5F, 0x45, 0x23, 0x53, 0xE4, 0x9B, | ||
85 | 0x75, 0xE1, 0x3D, 0x4C, 0x6C, 0x7E, 0xF5, 0x83, | ||
86 | 0x68, 0x51, 0xD1, 0xF9, 0xE2, 0xAB, 0x62, 0x2A, | ||
87 | 0x08, 0x95, 0x46, 0x9D, 0x30, 0x37, 0x0A, 0x2F, | ||
88 | 0x0E, 0x24, 0x1B, 0xDF, 0xCD, 0x4E, 0x7F, 0xEA, | ||
89 | 0x12, 0x1D, 0x58, 0x34, 0x36, 0xDC, 0xB4, 0x5B, | ||
90 | 0xA4, 0x76, 0xB7, 0x7D, 0x52, 0xDD, 0x5E, 0x13, | ||
91 | 0xA6, 0xB9, 0x00, 0xC1, 0x40, 0xE3, 0x79, 0xB6, | ||
92 | 0xD4, 0x8D, 0x67, 0x72, 0x94, 0x98, 0xB0, 0x85, | ||
93 | 0xBB, 0xC5, 0x4F, 0xED, 0x86, 0x9A, 0x66, 0x11, | ||
94 | 0x8A, 0xE9, 0x04, 0xFE, 0xA0, 0x78, 0x25, 0x4B, | ||
95 | 0xA2, 0x5D, 0x80, 0x05, 0x3F, 0x21, 0x70, 0xF1, | ||
96 | 0x63, 0x77, 0xAF, 0x42, 0x20, 0xE5, 0xFD, 0xBF, | ||
97 | 0x81, 0x18, 0x26, 0xC3, 0xBE, 0x35, 0x88, 0x2E, | ||
98 | 0x93, 0x55, 0xFC, 0x7A, 0xC8, 0xBA, 0x32, 0xE6, | ||
99 | 0xC0, 0x19, 0x9E, 0xA3, 0x44, 0x54, 0x3B, 0x0B, | ||
100 | 0x8C, 0xC7, 0x6B, 0x28, 0xA7, 0xBC, 0x16, 0xAD, | ||
101 | 0xDB, 0x64, 0x74, 0x14, 0x92, 0x0C, 0x48, 0xB8, | ||
102 | 0x9F, 0xBD, 0x43, 0xC4, 0x39, 0x31, 0xD3, 0xF2, | ||
103 | 0xD5, 0x8B, 0x6E, 0xDA, 0x01, 0xB1, 0x9C, 0x49, | ||
104 | 0xD8, 0xAC, 0xF3, 0xCF, 0xCA, 0xF4, 0x47, 0x10, | ||
105 | 0x6F, 0xF0, 0x4A, 0x5C, 0x38, 0x57, 0x73, 0x97, | ||
106 | 0xCB, 0xA1, 0xE8, 0x3E, 0x96, 0x61, 0x0D, 0x0F, | ||
107 | 0xE0, 0x7C, 0x71, 0xCC, 0x90, 0x06, 0xF7, 0x1C, | ||
108 | 0xC2, 0x6A, 0xAE, 0x69, 0x17, 0x99, 0x3A, 0x27, | ||
109 | 0xD9, 0xEB, 0x2B, 0x22, 0xD2, 0xA9, 0x07, 0x33, | ||
110 | 0x2D, 0x3C, 0x15, 0xC9, 0x87, 0xAA, 0x50, 0xA5, | ||
111 | 0x03, 0x59, 0x09, 0x1A, 0x65, 0xD7, 0x84, 0xD0, | ||
112 | 0x82, 0x29, 0x5A, 0x1E, 0x7B, 0xA8, 0x6D, 0x2C | ||
113 | }; | ||
114 | |||
115 | /* */ | ||
116 | /* Expanded IV for TKIP function. */ | ||
117 | /* */ | ||
118 | struct PACKED rt_tkip_iv { | ||
119 | union PACKED { | ||
120 | struct PACKED { | ||
121 | u8 rc0; | ||
122 | u8 rc1; | ||
123 | u8 rc2; | ||
124 | |||
125 | union PACKED { | ||
126 | struct PACKED { | ||
127 | u8 Rsvd:5; | ||
128 | u8 ExtIV:1; | ||
129 | u8 KeyID:2; | ||
130 | } field; | ||
131 | u8 Byte; | ||
132 | } CONTROL; | ||
133 | } field; | ||
134 | |||
135 | unsigned long word; | ||
136 | } IV16; | ||
137 | |||
138 | unsigned long IV32; | ||
139 | }; | ||
140 | |||
141 | /* | ||
142 | ======================================================================== | ||
143 | |||
144 | Routine Description: | ||
145 | Convert from u8[] to unsigned long in a portable way | ||
146 | |||
147 | Arguments: | ||
148 | pMICKey pointer to MIC Key | ||
149 | |||
150 | Return Value: | ||
151 | None | ||
152 | |||
153 | Note: | ||
154 | |||
155 | ======================================================================== | ||
156 | */ | ||
157 | unsigned long RTMPTkipGetUInt32(u8 *pMICKey) | ||
158 | { | ||
159 | unsigned long res = 0; | ||
160 | int i; | ||
161 | |||
162 | for (i = 0; i < 4; i++) { | ||
163 | res |= (*pMICKey++) << (8 * i); | ||
164 | } | ||
165 | |||
166 | return res; | ||
167 | } | ||
168 | |||
169 | /* | ||
170 | ======================================================================== | ||
171 | |||
172 | Routine Description: | ||
173 | Convert from unsigned long to u8[] in a portable way | ||
174 | |||
175 | Arguments: | ||
176 | pDst pointer to destination for convert unsigned long to u8[] | ||
177 | val the value for convert | ||
178 | |||
179 | Return Value: | ||
180 | None | ||
181 | |||
182 | IRQL = DISPATCH_LEVEL | ||
183 | |||
184 | Note: | ||
185 | |||
186 | ======================================================================== | ||
187 | */ | ||
188 | void RTMPTkipPutUInt32(IN u8 *pDst, unsigned long val) | ||
189 | { | ||
190 | int i; | ||
191 | |||
192 | for (i = 0; i < 4; i++) { | ||
193 | *pDst++ = (u8)(val & 0xff); | ||
194 | val >>= 8; | ||
195 | } | ||
196 | } | ||
197 | |||
198 | /* | ||
199 | ======================================================================== | ||
200 | |||
201 | Routine Description: | ||
202 | Set the MIC Key. | ||
203 | |||
204 | Arguments: | ||
205 | pAd Pointer to our adapter | ||
206 | pMICKey pointer to MIC Key | ||
207 | |||
208 | Return Value: | ||
209 | None | ||
210 | |||
211 | IRQL = DISPATCH_LEVEL | ||
212 | |||
213 | Note: | ||
214 | |||
215 | ======================================================================== | ||
216 | */ | ||
217 | void RTMPTkipSetMICKey(struct rt_tkip_key_info *pTkip, u8 *pMICKey) | ||
218 | { | ||
219 | /* Set the key */ | ||
220 | pTkip->K0 = RTMPTkipGetUInt32(pMICKey); | ||
221 | pTkip->K1 = RTMPTkipGetUInt32(pMICKey + 4); | ||
222 | /* and reset the message */ | ||
223 | pTkip->L = pTkip->K0; | ||
224 | pTkip->R = pTkip->K1; | ||
225 | pTkip->nBytesInM = 0; | ||
226 | pTkip->M = 0; | ||
227 | } | ||
228 | |||
229 | /* | ||
230 | ======================================================================== | ||
231 | |||
232 | Routine Description: | ||
233 | Calculate the MIC Value. | ||
234 | |||
235 | Arguments: | ||
236 | pAd Pointer to our adapter | ||
237 | uChar Append this uChar | ||
238 | |||
239 | Return Value: | ||
240 | None | ||
241 | |||
242 | IRQL = DISPATCH_LEVEL | ||
243 | |||
244 | Note: | ||
245 | |||
246 | ======================================================================== | ||
247 | */ | ||
248 | void RTMPTkipAppendByte(struct rt_tkip_key_info *pTkip, u8 uChar) | ||
249 | { | ||
250 | /* Append the byte to our word-sized buffer */ | ||
251 | pTkip->M |= (uChar << (8 * pTkip->nBytesInM)); | ||
252 | pTkip->nBytesInM++; | ||
253 | /* Process the word if it is full. */ | ||
254 | if (pTkip->nBytesInM >= 4) { | ||
255 | pTkip->L ^= pTkip->M; | ||
256 | pTkip->R ^= ROL32(pTkip->L, 17); | ||
257 | pTkip->L += pTkip->R; | ||
258 | pTkip->R ^= | ||
259 | ((pTkip->L & 0xff00ff00) >> 8) | ((pTkip-> | ||
260 | L & 0x00ff00ff) << 8); | ||
261 | pTkip->L += pTkip->R; | ||
262 | pTkip->R ^= ROL32(pTkip->L, 3); | ||
263 | pTkip->L += pTkip->R; | ||
264 | pTkip->R ^= ROR32(pTkip->L, 2); | ||
265 | pTkip->L += pTkip->R; | ||
266 | /* Clear the buffer */ | ||
267 | pTkip->M = 0; | ||
268 | pTkip->nBytesInM = 0; | ||
269 | } | ||
270 | } | ||
271 | |||
272 | /* | ||
273 | ======================================================================== | ||
274 | |||
275 | Routine Description: | ||
276 | Calculate the MIC Value. | ||
277 | |||
278 | Arguments: | ||
279 | pAd Pointer to our adapter | ||
280 | pSrc Pointer to source data for Calculate MIC Value | ||
281 | Len Indicate the length of the source data | ||
282 | |||
283 | Return Value: | ||
284 | None | ||
285 | |||
286 | IRQL = DISPATCH_LEVEL | ||
287 | |||
288 | Note: | ||
289 | |||
290 | ======================================================================== | ||
291 | */ | ||
292 | void RTMPTkipAppend(struct rt_tkip_key_info *pTkip, u8 *pSrc, u32 nBytes) | ||
293 | { | ||
294 | /* This is simple */ | ||
295 | while (nBytes > 0) { | ||
296 | RTMPTkipAppendByte(pTkip, *pSrc++); | ||
297 | nBytes--; | ||
298 | } | ||
299 | } | ||
300 | |||
301 | /* | ||
302 | ======================================================================== | ||
303 | |||
304 | Routine Description: | ||
305 | Get the MIC Value. | ||
306 | |||
307 | Arguments: | ||
308 | pAd Pointer to our adapter | ||
309 | |||
310 | Return Value: | ||
311 | None | ||
312 | |||
313 | IRQL = DISPATCH_LEVEL | ||
314 | |||
315 | Note: | ||
316 | the MIC Value is store in pAd->PrivateInfo.MIC | ||
317 | ======================================================================== | ||
318 | */ | ||
319 | void RTMPTkipGetMIC(struct rt_tkip_key_info *pTkip) | ||
320 | { | ||
321 | /* Append the minimum padding */ | ||
322 | RTMPTkipAppendByte(pTkip, 0x5a); | ||
323 | RTMPTkipAppendByte(pTkip, 0); | ||
324 | RTMPTkipAppendByte(pTkip, 0); | ||
325 | RTMPTkipAppendByte(pTkip, 0); | ||
326 | RTMPTkipAppendByte(pTkip, 0); | ||
327 | /* and then zeroes until the length is a multiple of 4 */ | ||
328 | while (pTkip->nBytesInM != 0) { | ||
329 | RTMPTkipAppendByte(pTkip, 0); | ||
330 | } | ||
331 | /* The appendByte function has already computed the result. */ | ||
332 | RTMPTkipPutUInt32(pTkip->MIC, pTkip->L); | ||
333 | RTMPTkipPutUInt32(pTkip->MIC + 4, pTkip->R); | ||
334 | } | ||
335 | |||
336 | /* | ||
337 | ======================================================================== | ||
338 | |||
339 | Routine Description: | ||
340 | Init Tkip function. | ||
341 | |||
342 | Arguments: | ||
343 | pAd Pointer to our adapter | ||
344 | pTKey Pointer to the Temporal Key (TK), TK shall be 128bits. | ||
345 | KeyId TK Key ID | ||
346 | pTA Pointer to transmitter address | ||
347 | pMICKey pointer to MIC Key | ||
348 | |||
349 | Return Value: | ||
350 | None | ||
351 | |||
352 | IRQL = DISPATCH_LEVEL | ||
353 | |||
354 | Note: | ||
355 | |||
356 | ======================================================================== | ||
357 | */ | ||
358 | void RTMPInitTkipEngine(struct rt_rtmp_adapter *pAd, | ||
359 | u8 *pKey, | ||
360 | u8 KeyId, | ||
361 | u8 *pTA, | ||
362 | u8 *pMICKey, | ||
363 | u8 *pTSC, unsigned long *pIV16, unsigned long *pIV32) | ||
364 | { | ||
365 | struct rt_tkip_iv tkipIv; | ||
366 | |||
367 | /* Prepare 8 bytes TKIP encapsulation for MPDU */ | ||
368 | NdisZeroMemory(&tkipIv, sizeof(struct rt_tkip_iv)); | ||
369 | tkipIv.IV16.field.rc0 = *(pTSC + 1); | ||
370 | tkipIv.IV16.field.rc1 = (tkipIv.IV16.field.rc0 | 0x20) & 0x7f; | ||
371 | tkipIv.IV16.field.rc2 = *pTSC; | ||
372 | tkipIv.IV16.field.CONTROL.field.ExtIV = 1; /* 0: non-extended IV, 1: an extended IV */ | ||
373 | tkipIv.IV16.field.CONTROL.field.KeyID = KeyId; | ||
374 | /* tkipIv.IV32 = *(unsigned long *)(pTSC + 2); */ | ||
375 | NdisMoveMemory(&tkipIv.IV32, (pTSC + 2), 4); /* Copy IV */ | ||
376 | |||
377 | *pIV16 = tkipIv.IV16.word; | ||
378 | *pIV32 = tkipIv.IV32; | ||
379 | } | ||
380 | |||
381 | /* | ||
382 | ======================================================================== | ||
383 | |||
384 | Routine Description: | ||
385 | Init MIC Value calculation function which include set MIC key & | ||
386 | calculate first 16 bytes (DA + SA + priority + 0) | ||
387 | |||
388 | Arguments: | ||
389 | pAd Pointer to our adapter | ||
390 | pTKey Pointer to the Temporal Key (TK), TK shall be 128bits. | ||
391 | pDA Pointer to DA address | ||
392 | pSA Pointer to SA address | ||
393 | pMICKey pointer to MIC Key | ||
394 | |||
395 | Return Value: | ||
396 | None | ||
397 | |||
398 | Note: | ||
399 | |||
400 | ======================================================================== | ||
401 | */ | ||
402 | void RTMPInitMICEngine(struct rt_rtmp_adapter *pAd, | ||
403 | u8 *pKey, | ||
404 | u8 *pDA, | ||
405 | u8 *pSA, u8 UserPriority, u8 *pMICKey) | ||
406 | { | ||
407 | unsigned long Priority = UserPriority; | ||
408 | |||
409 | /* Init MIC value calculation */ | ||
410 | RTMPTkipSetMICKey(&pAd->PrivateInfo.Tx, pMICKey); | ||
411 | /* DA */ | ||
412 | RTMPTkipAppend(&pAd->PrivateInfo.Tx, pDA, MAC_ADDR_LEN); | ||
413 | /* SA */ | ||
414 | RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSA, MAC_ADDR_LEN); | ||
415 | /* Priority + 3 bytes of 0 */ | ||
416 | RTMPTkipAppend(&pAd->PrivateInfo.Tx, (u8 *)& Priority, 4); | ||
417 | } | ||
418 | |||
419 | /* | ||
420 | ======================================================================== | ||
421 | |||
422 | Routine Description: | ||
423 | Compare MIC value of received MSDU | ||
424 | |||
425 | Arguments: | ||
426 | pAd Pointer to our adapter | ||
427 | pSrc Pointer to the received Plain text data | ||
428 | pDA Pointer to DA address | ||
429 | pSA Pointer to SA address | ||
430 | pMICKey pointer to MIC Key | ||
431 | Len the length of the received plain text data exclude MIC value | ||
432 | |||
433 | Return Value: | ||
434 | TRUE MIC value matched | ||
435 | FALSE MIC value mismatched | ||
436 | |||
437 | IRQL = DISPATCH_LEVEL | ||
438 | |||
439 | Note: | ||
440 | |||
441 | ======================================================================== | ||
442 | */ | ||
443 | BOOLEAN RTMPTkipCompareMICValue(struct rt_rtmp_adapter *pAd, | ||
444 | u8 *pSrc, | ||
445 | u8 *pDA, | ||
446 | u8 *pSA, | ||
447 | u8 *pMICKey, | ||
448 | u8 UserPriority, u32 Len) | ||
449 | { | ||
450 | u8 OldMic[8]; | ||
451 | unsigned long Priority = UserPriority; | ||
452 | |||
453 | /* Init MIC value calculation */ | ||
454 | RTMPTkipSetMICKey(&pAd->PrivateInfo.Rx, pMICKey); | ||
455 | /* DA */ | ||
456 | RTMPTkipAppend(&pAd->PrivateInfo.Rx, pDA, MAC_ADDR_LEN); | ||
457 | /* SA */ | ||
458 | RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSA, MAC_ADDR_LEN); | ||
459 | /* Priority + 3 bytes of 0 */ | ||
460 | RTMPTkipAppend(&pAd->PrivateInfo.Rx, (u8 *)& Priority, 4); | ||
461 | |||
462 | /* Calculate MIC value from plain text data */ | ||
463 | RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSrc, Len); | ||
464 | |||
465 | /* Get MIC valude from received frame */ | ||
466 | NdisMoveMemory(OldMic, pSrc + Len, 8); | ||
467 | |||
468 | /* Get MIC value from decrypted plain data */ | ||
469 | RTMPTkipGetMIC(&pAd->PrivateInfo.Rx); | ||
470 | |||
471 | /* Move MIC value from MSDU, this steps should move to data path. */ | ||
472 | /* Since the MIC value might cross MPDUs. */ | ||
473 | if (!NdisEqualMemory(pAd->PrivateInfo.Rx.MIC, OldMic, 8)) { | ||
474 | DBGPRINT_RAW(RT_DEBUG_ERROR, ("RTMPTkipCompareMICValue(): TKIP MIC Error !\n")); /*MIC error. */ | ||
475 | |||
476 | return (FALSE); | ||
477 | } | ||
478 | return (TRUE); | ||
479 | } | ||
480 | |||
481 | /* | ||
482 | ======================================================================== | ||
483 | |||
484 | Routine Description: | ||
485 | Copy frame from waiting queue into relative ring buffer and set | ||
486 | appropriate ASIC register to kick hardware transmit function | ||
487 | |||
488 | Arguments: | ||
489 | pAd Pointer to our adapter | ||
490 | void * Pointer to Ndis Packet for MIC calculation | ||
491 | pEncap Pointer to LLC encap data | ||
492 | LenEncap Total encap length, might be 0 which indicates no encap | ||
493 | |||
494 | Return Value: | ||
495 | None | ||
496 | |||
497 | IRQL = DISPATCH_LEVEL | ||
498 | |||
499 | Note: | ||
500 | |||
501 | ======================================================================== | ||
502 | */ | ||
503 | void RTMPCalculateMICValue(struct rt_rtmp_adapter *pAd, | ||
504 | void *pPacket, | ||
505 | u8 *pEncap, | ||
506 | struct rt_cipher_key *pKey, u8 apidx) | ||
507 | { | ||
508 | struct rt_packet_info PacketInfo; | ||
509 | u8 *pSrcBufVA; | ||
510 | u32 SrcBufLen; | ||
511 | u8 *pSrc; | ||
512 | u8 UserPriority; | ||
513 | u8 vlan_offset = 0; | ||
514 | |||
515 | RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); | ||
516 | |||
517 | UserPriority = RTMP_GET_PACKET_UP(pPacket); | ||
518 | pSrc = pSrcBufVA; | ||
519 | |||
520 | /* determine if this is a vlan packet */ | ||
521 | if (((*(pSrc + 12) << 8) + *(pSrc + 13)) == 0x8100) | ||
522 | vlan_offset = 4; | ||
523 | |||
524 | { | ||
525 | RTMPInitMICEngine(pAd, | ||
526 | pKey->Key, | ||
527 | pSrc, pSrc + 6, UserPriority, pKey->TxMic); | ||
528 | } | ||
529 | |||
530 | if (pEncap != NULL) { | ||
531 | /* LLC encapsulation */ | ||
532 | RTMPTkipAppend(&pAd->PrivateInfo.Tx, pEncap, 6); | ||
533 | /* Protocol Type */ | ||
534 | RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSrc + 12 + vlan_offset, | ||
535 | 2); | ||
536 | } | ||
537 | SrcBufLen -= (14 + vlan_offset); | ||
538 | pSrc += (14 + vlan_offset); | ||
539 | do { | ||
540 | if (SrcBufLen > 0) { | ||
541 | RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSrc, SrcBufLen); | ||
542 | } | ||
543 | |||
544 | break; /* No need handle next packet */ | ||
545 | |||
546 | } while (TRUE); /* End of copying payload */ | ||
547 | |||
548 | /* Compute the final MIC Value */ | ||
549 | RTMPTkipGetMIC(&pAd->PrivateInfo.Tx); | ||
550 | } | ||
551 | |||
552 | /************************************************************/ | ||
553 | /* tkip_sbox() */ | ||
554 | /* Returns a 16 bit value from a 64K entry table. The Table */ | ||
555 | /* is synthesized from two 256 entry byte wide tables. */ | ||
556 | /************************************************************/ | ||
557 | |||
558 | u32 tkip_sbox(u32 index) | ||
559 | { | ||
560 | u32 index_low; | ||
561 | u32 index_high; | ||
562 | u32 left, right; | ||
563 | |||
564 | index_low = (index % 256); | ||
565 | index_high = ((index >> 8) % 256); | ||
566 | |||
567 | left = Tkip_Sbox_Lower[index_low] + (Tkip_Sbox_Upper[index_low] * 256); | ||
568 | right = | ||
569 | Tkip_Sbox_Upper[index_high] + (Tkip_Sbox_Lower[index_high] * 256); | ||
570 | |||
571 | return (left ^ right); | ||
572 | } | ||
573 | |||
574 | u32 rotr1(u32 a) | ||
575 | { | ||
576 | unsigned int b; | ||
577 | |||
578 | if ((a & 0x01) == 0x01) { | ||
579 | b = (a >> 1) | 0x8000; | ||
580 | } else { | ||
581 | b = (a >> 1) & 0x7fff; | ||
582 | } | ||
583 | b = b % 65536; | ||
584 | return b; | ||
585 | } | ||
586 | |||
587 | void RTMPTkipMixKey(u8 * key, u8 * ta, unsigned long pnl, /* Least significant 16 bits of PN */ | ||
588 | unsigned long pnh, /* Most significant 32 bits of PN */ | ||
589 | u8 * rc4key, u32 * p1k) | ||
590 | { | ||
591 | |||
592 | u32 tsc0; | ||
593 | u32 tsc1; | ||
594 | u32 tsc2; | ||
595 | |||
596 | u32 ppk0; | ||
597 | u32 ppk1; | ||
598 | u32 ppk2; | ||
599 | u32 ppk3; | ||
600 | u32 ppk4; | ||
601 | u32 ppk5; | ||
602 | |||
603 | int i; | ||
604 | int j; | ||
605 | |||
606 | tsc0 = (unsigned int)((pnh >> 16) % 65536); /* msb */ | ||
607 | tsc1 = (unsigned int)(pnh % 65536); | ||
608 | tsc2 = (unsigned int)(pnl % 65536); /* lsb */ | ||
609 | |||
610 | /* Phase 1, step 1 */ | ||
611 | p1k[0] = tsc1; | ||
612 | p1k[1] = tsc0; | ||
613 | p1k[2] = (u32)(ta[0] + (ta[1] * 256)); | ||
614 | p1k[3] = (u32)(ta[2] + (ta[3] * 256)); | ||
615 | p1k[4] = (u32)(ta[4] + (ta[5] * 256)); | ||
616 | |||
617 | /* Phase 1, step 2 */ | ||
618 | for (i = 0; i < 8; i++) { | ||
619 | j = 2 * (i & 1); | ||
620 | p1k[0] = | ||
621 | (p1k[0] + | ||
622 | tkip_sbox((p1k[4] ^ ((256 * key[1 + j]) + key[j])) % | ||
623 | 65536)) % 65536; | ||
624 | p1k[1] = | ||
625 | (p1k[1] + | ||
626 | tkip_sbox((p1k[0] ^ ((256 * key[5 + j]) + key[4 + j])) % | ||
627 | 65536)) % 65536; | ||
628 | p1k[2] = | ||
629 | (p1k[2] + | ||
630 | tkip_sbox((p1k[1] ^ ((256 * key[9 + j]) + key[8 + j])) % | ||
631 | 65536)) % 65536; | ||
632 | p1k[3] = | ||
633 | (p1k[3] + | ||
634 | tkip_sbox((p1k[2] ^ ((256 * key[13 + j]) + key[12 + j])) % | ||
635 | 65536)) % 65536; | ||
636 | p1k[4] = | ||
637 | (p1k[4] + | ||
638 | tkip_sbox((p1k[3] ^ (((256 * key[1 + j]) + key[j]))) % | ||
639 | 65536)) % 65536; | ||
640 | p1k[4] = (p1k[4] + i) % 65536; | ||
641 | } | ||
642 | |||
643 | /* Phase 2, Step 1 */ | ||
644 | ppk0 = p1k[0]; | ||
645 | ppk1 = p1k[1]; | ||
646 | ppk2 = p1k[2]; | ||
647 | ppk3 = p1k[3]; | ||
648 | ppk4 = p1k[4]; | ||
649 | ppk5 = (p1k[4] + tsc2) % 65536; | ||
650 | |||
651 | /* Phase2, Step 2 */ | ||
652 | ppk0 = ppk0 + tkip_sbox((ppk5 ^ ((256 * key[1]) + key[0])) % 65536); | ||
653 | ppk1 = ppk1 + tkip_sbox((ppk0 ^ ((256 * key[3]) + key[2])) % 65536); | ||
654 | ppk2 = ppk2 + tkip_sbox((ppk1 ^ ((256 * key[5]) + key[4])) % 65536); | ||
655 | ppk3 = ppk3 + tkip_sbox((ppk2 ^ ((256 * key[7]) + key[6])) % 65536); | ||
656 | ppk4 = ppk4 + tkip_sbox((ppk3 ^ ((256 * key[9]) + key[8])) % 65536); | ||
657 | ppk5 = ppk5 + tkip_sbox((ppk4 ^ ((256 * key[11]) + key[10])) % 65536); | ||
658 | |||
659 | ppk0 = ppk0 + rotr1(ppk5 ^ ((256 * key[13]) + key[12])); | ||
660 | ppk1 = ppk1 + rotr1(ppk0 ^ ((256 * key[15]) + key[14])); | ||
661 | ppk2 = ppk2 + rotr1(ppk1); | ||
662 | ppk3 = ppk3 + rotr1(ppk2); | ||
663 | ppk4 = ppk4 + rotr1(ppk3); | ||
664 | ppk5 = ppk5 + rotr1(ppk4); | ||
665 | |||
666 | /* Phase 2, Step 3 */ | ||
667 | /* Phase 2, Step 3 */ | ||
668 | |||
669 | tsc0 = (unsigned int)((pnh >> 16) % 65536); /* msb */ | ||
670 | tsc1 = (unsigned int)(pnh % 65536); | ||
671 | tsc2 = (unsigned int)(pnl % 65536); /* lsb */ | ||
672 | |||
673 | rc4key[0] = (tsc2 >> 8) % 256; | ||
674 | rc4key[1] = (((tsc2 >> 8) % 256) | 0x20) & 0x7f; | ||
675 | rc4key[2] = tsc2 % 256; | ||
676 | rc4key[3] = ((ppk5 ^ ((256 * key[1]) + key[0])) >> 1) % 256; | ||
677 | |||
678 | rc4key[4] = ppk0 % 256; | ||
679 | rc4key[5] = (ppk0 >> 8) % 256; | ||
680 | |||
681 | rc4key[6] = ppk1 % 256; | ||
682 | rc4key[7] = (ppk1 >> 8) % 256; | ||
683 | |||
684 | rc4key[8] = ppk2 % 256; | ||
685 | rc4key[9] = (ppk2 >> 8) % 256; | ||
686 | |||
687 | rc4key[10] = ppk3 % 256; | ||
688 | rc4key[11] = (ppk3 >> 8) % 256; | ||
689 | |||
690 | rc4key[12] = ppk4 % 256; | ||
691 | rc4key[13] = (ppk4 >> 8) % 256; | ||
692 | |||
693 | rc4key[14] = ppk5 % 256; | ||
694 | rc4key[15] = (ppk5 >> 8) % 256; | ||
695 | } | ||
696 | |||
697 | /* */ | ||
698 | /* TRUE: Success! */ | ||
699 | /* FALSE: Decrypt Error! */ | ||
700 | /* */ | ||
701 | BOOLEAN RTMPSoftDecryptTKIP(struct rt_rtmp_adapter *pAd, | ||
702 | u8 *pData, | ||
703 | unsigned long DataByteCnt, | ||
704 | u8 UserPriority, struct rt_cipher_key *pWpaKey) | ||
705 | { | ||
706 | u8 KeyID; | ||
707 | u32 HeaderLen; | ||
708 | u8 fc0; | ||
709 | u8 fc1; | ||
710 | u16 fc; | ||
711 | u32 frame_type; | ||
712 | u32 frame_subtype; | ||
713 | u32 from_ds; | ||
714 | u32 to_ds; | ||
715 | int a4_exists; | ||
716 | int qc_exists; | ||
717 | u16 duration; | ||
718 | u16 seq_control; | ||
719 | u16 qos_control; | ||
720 | u8 TA[MAC_ADDR_LEN]; | ||
721 | u8 DA[MAC_ADDR_LEN]; | ||
722 | u8 SA[MAC_ADDR_LEN]; | ||
723 | u8 RC4Key[16]; | ||
724 | u32 p1k[5]; /*for mix_key; */ | ||
725 | unsigned long pnl; /* Least significant 16 bits of PN */ | ||
726 | unsigned long pnh; /* Most significant 32 bits of PN */ | ||
727 | u32 num_blocks; | ||
728 | u32 payload_remainder; | ||
729 | struct rt_arcfourcontext ArcFourContext; | ||
730 | u32 crc32 = 0; | ||
731 | u32 trailfcs = 0; | ||
732 | u8 MIC[8]; | ||
733 | u8 TrailMIC[8]; | ||
734 | |||
735 | fc0 = *pData; | ||
736 | fc1 = *(pData + 1); | ||
737 | |||
738 | fc = *((u16 *)pData); | ||
739 | |||
740 | frame_type = ((fc0 >> 2) & 0x03); | ||
741 | frame_subtype = ((fc0 >> 4) & 0x0f); | ||
742 | |||
743 | from_ds = (fc1 & 0x2) >> 1; | ||
744 | to_ds = (fc1 & 0x1); | ||
745 | |||
746 | a4_exists = (from_ds & to_ds); | ||
747 | qc_exists = ((frame_subtype == 0x08) || /* Assumed QoS subtypes */ | ||
748 | (frame_subtype == 0x09) || /* Likely to change. */ | ||
749 | (frame_subtype == 0x0a) || (frame_subtype == 0x0b) | ||
750 | ); | ||
751 | |||
752 | HeaderLen = 24; | ||
753 | if (a4_exists) | ||
754 | HeaderLen += 6; | ||
755 | |||
756 | KeyID = *((u8 *)(pData + HeaderLen + 3)); | ||
757 | KeyID = KeyID >> 6; | ||
758 | |||
759 | if (pWpaKey[KeyID].KeyLen == 0) { | ||
760 | DBGPRINT(RT_DEBUG_TRACE, | ||
761 | ("RTMPSoftDecryptTKIP failed!(KeyID[%d] Length can not be 0)\n", | ||
762 | KeyID)); | ||
763 | return FALSE; | ||
764 | } | ||
765 | |||
766 | duration = *((u16 *)(pData + 2)); | ||
767 | |||
768 | seq_control = *((u16 *)(pData + 22)); | ||
769 | |||
770 | if (qc_exists) { | ||
771 | if (a4_exists) { | ||
772 | qos_control = *((u16 *)(pData + 30)); | ||
773 | } else { | ||
774 | qos_control = *((u16 *)(pData + 24)); | ||
775 | } | ||
776 | } | ||
777 | |||
778 | if (to_ds == 0 && from_ds == 1) { | ||
779 | NdisMoveMemory(DA, pData + 4, MAC_ADDR_LEN); | ||
780 | NdisMoveMemory(SA, pData + 16, MAC_ADDR_LEN); | ||
781 | NdisMoveMemory(TA, pData + 10, MAC_ADDR_LEN); /*BSSID */ | ||
782 | } else if (to_ds == 0 && from_ds == 0) { | ||
783 | NdisMoveMemory(TA, pData + 10, MAC_ADDR_LEN); | ||
784 | NdisMoveMemory(DA, pData + 4, MAC_ADDR_LEN); | ||
785 | NdisMoveMemory(SA, pData + 10, MAC_ADDR_LEN); | ||
786 | } else if (to_ds == 1 && from_ds == 0) { | ||
787 | NdisMoveMemory(SA, pData + 10, MAC_ADDR_LEN); | ||
788 | NdisMoveMemory(TA, pData + 10, MAC_ADDR_LEN); | ||
789 | NdisMoveMemory(DA, pData + 16, MAC_ADDR_LEN); | ||
790 | } else if (to_ds == 1 && from_ds == 1) { | ||
791 | NdisMoveMemory(TA, pData + 10, MAC_ADDR_LEN); | ||
792 | NdisMoveMemory(DA, pData + 16, MAC_ADDR_LEN); | ||
793 | NdisMoveMemory(SA, pData + 22, MAC_ADDR_LEN); | ||
794 | } | ||
795 | |||
796 | num_blocks = (DataByteCnt - 16) / 16; | ||
797 | payload_remainder = (DataByteCnt - 16) % 16; | ||
798 | |||
799 | pnl = (*(pData + HeaderLen)) * 256 + *(pData + HeaderLen + 2); | ||
800 | pnh = *((unsigned long *)(pData + HeaderLen + 4)); | ||
801 | pnh = cpu2le32(pnh); | ||
802 | RTMPTkipMixKey(pWpaKey[KeyID].Key, TA, pnl, pnh, RC4Key, p1k); | ||
803 | |||
804 | ARCFOUR_INIT(&ArcFourContext, RC4Key, 16); | ||
805 | |||
806 | ARCFOUR_DECRYPT(&ArcFourContext, pData + HeaderLen, | ||
807 | pData + HeaderLen + 8, DataByteCnt - HeaderLen - 8); | ||
808 | NdisMoveMemory(&trailfcs, pData + DataByteCnt - 8 - 4, 4); | ||
809 | crc32 = RTMP_CALC_FCS32(PPPINITFCS32, pData + HeaderLen, DataByteCnt - HeaderLen - 8 - 4); /*Skip IV+EIV 8 bytes & Skip last 4 bytes(FCS). */ | ||
810 | crc32 ^= 0xffffffff; /* complement */ | ||
811 | |||
812 | if (crc32 != cpu2le32(trailfcs)) { | ||
813 | DBGPRINT(RT_DEBUG_TRACE, ("RTMPSoftDecryptTKIP, WEP Data ICV Error !\n")); /*ICV error. */ | ||
814 | |||
815 | return (FALSE); | ||
816 | } | ||
817 | |||
818 | NdisMoveMemory(TrailMIC, pData + DataByteCnt - 8 - 8 - 4, 8); | ||
819 | RTMPInitMICEngine(pAd, pWpaKey[KeyID].Key, DA, SA, UserPriority, | ||
820 | pWpaKey[KeyID].RxMic); | ||
821 | RTMPTkipAppend(&pAd->PrivateInfo.Tx, pData + HeaderLen, | ||
822 | DataByteCnt - HeaderLen - 8 - 12); | ||
823 | RTMPTkipGetMIC(&pAd->PrivateInfo.Tx); | ||
824 | NdisMoveMemory(MIC, pAd->PrivateInfo.Tx.MIC, 8); | ||
825 | |||
826 | if (!NdisEqualMemory(MIC, TrailMIC, 8)) { | ||
827 | DBGPRINT(RT_DEBUG_ERROR, ("RTMPSoftDecryptTKIP, WEP Data MIC Error !\n")); /*MIC error. */ | ||
828 | /*RTMPReportMicError(pAd, &pWpaKey[KeyID]); // marked by AlbertY @ 20060630 */ | ||
829 | return (FALSE); | ||
830 | } | ||
831 | /*DBGPRINT(RT_DEBUG_TRACE, "RTMPSoftDecryptTKIP Decript done!\n"); */ | ||
832 | return TRUE; | ||
833 | } | ||
diff --git a/drivers/staging/rt2860/common/cmm_wep.c b/drivers/staging/rt2860/common/cmm_wep.c deleted file mode 100644 index 76f880cb39b..00000000000 --- a/drivers/staging/rt2860/common/cmm_wep.c +++ /dev/null | |||
@@ -1,473 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | |||
27 | Module Name: | ||
28 | rtmp_wep.c | ||
29 | |||
30 | Abstract: | ||
31 | |||
32 | Revision History: | ||
33 | Who When What | ||
34 | -------- ---------- ---------------------------------------------- | ||
35 | Paul Wu 10-28-02 Initial | ||
36 | */ | ||
37 | |||
38 | #include "../rt_config.h" | ||
39 | |||
40 | u32 FCSTAB_32[256] = { | ||
41 | 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, | ||
42 | 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, | ||
43 | 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, | ||
44 | 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, | ||
45 | 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, | ||
46 | 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, | ||
47 | 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, | ||
48 | 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, | ||
49 | 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, | ||
50 | 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, | ||
51 | 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, | ||
52 | 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, | ||
53 | 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, | ||
54 | 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, | ||
55 | 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, | ||
56 | 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, | ||
57 | 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, | ||
58 | 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, | ||
59 | 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, | ||
60 | 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, | ||
61 | 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, | ||
62 | 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, | ||
63 | 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, | ||
64 | 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, | ||
65 | 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, | ||
66 | 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, | ||
67 | 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, | ||
68 | 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, | ||
69 | 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, | ||
70 | 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, | ||
71 | 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, | ||
72 | 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, | ||
73 | 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, | ||
74 | 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, | ||
75 | 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, | ||
76 | 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, | ||
77 | 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, | ||
78 | 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, | ||
79 | 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, | ||
80 | 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, | ||
81 | 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, | ||
82 | 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, | ||
83 | 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, | ||
84 | 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, | ||
85 | 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, | ||
86 | 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, | ||
87 | 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, | ||
88 | 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, | ||
89 | 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, | ||
90 | 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, | ||
91 | 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, | ||
92 | 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, | ||
93 | 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, | ||
94 | 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, | ||
95 | 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, | ||
96 | 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, | ||
97 | 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, | ||
98 | 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, | ||
99 | 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, | ||
100 | 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, | ||
101 | 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, | ||
102 | 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, | ||
103 | 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, | ||
104 | 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d | ||
105 | }; | ||
106 | |||
107 | /* | ||
108 | u8 WEPKEY[] = { | ||
109 | //IV | ||
110 | 0x00, 0x11, 0x22, | ||
111 | //WEP KEY | ||
112 | 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC | ||
113 | }; | ||
114 | */ | ||
115 | |||
116 | /* | ||
117 | ======================================================================== | ||
118 | |||
119 | Routine Description: | ||
120 | Init WEP function. | ||
121 | |||
122 | Arguments: | ||
123 | pAd Pointer to our adapter | ||
124 | pKey Pointer to the WEP KEY | ||
125 | KeyId WEP Key ID | ||
126 | KeyLen the length of WEP KEY | ||
127 | pDest Pointer to the destination which Encryption data will store in. | ||
128 | |||
129 | Return Value: | ||
130 | None | ||
131 | |||
132 | IRQL = DISPATCH_LEVEL | ||
133 | |||
134 | Note: | ||
135 | |||
136 | ======================================================================== | ||
137 | */ | ||
138 | void RTMPInitWepEngine(struct rt_rtmp_adapter *pAd, | ||
139 | u8 *pKey, | ||
140 | u8 KeyId, u8 KeyLen, IN u8 *pDest) | ||
141 | { | ||
142 | u32 i; | ||
143 | u8 WEPKEY[] = { | ||
144 | /*IV */ | ||
145 | 0x00, 0x11, 0x22, | ||
146 | /*WEP KEY */ | ||
147 | 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, | ||
148 | 0xAA, 0xBB, 0xCC | ||
149 | }; | ||
150 | |||
151 | pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32; /*Init crc32. */ | ||
152 | |||
153 | { | ||
154 | NdisMoveMemory(WEPKEY + 3, pKey, KeyLen); | ||
155 | |||
156 | for (i = 0; i < 3; i++) | ||
157 | WEPKEY[i] = RandomByte(pAd); /*Call mlme RandomByte() function. */ | ||
158 | ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, WEPKEY, KeyLen + 3); /*INIT SBOX, KEYLEN+3(IV) */ | ||
159 | |||
160 | NdisMoveMemory(pDest, WEPKEY, 3); /*Append Init Vector */ | ||
161 | } | ||
162 | *(pDest + 3) = (KeyId << 6); /*Append KEYID */ | ||
163 | |||
164 | } | ||
165 | |||
166 | /* | ||
167 | ======================================================================== | ||
168 | |||
169 | Routine Description: | ||
170 | Encrypt transimitted data | ||
171 | |||
172 | Arguments: | ||
173 | pAd Pointer to our adapter | ||
174 | pSrc Pointer to the transimitted source data that will be encrypt | ||
175 | pDest Pointer to the destination where entryption data will be store in. | ||
176 | Len Indicate the length of the source data | ||
177 | |||
178 | Return Value: | ||
179 | None | ||
180 | |||
181 | IRQL = DISPATCH_LEVEL | ||
182 | |||
183 | Note: | ||
184 | |||
185 | ======================================================================== | ||
186 | */ | ||
187 | void RTMPEncryptData(struct rt_rtmp_adapter *pAd, | ||
188 | u8 *pSrc, u8 *pDest, u32 Len) | ||
189 | { | ||
190 | pAd->PrivateInfo.FCSCRC32 = | ||
191 | RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, pSrc, Len); | ||
192 | ARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, pDest, pSrc, Len); | ||
193 | } | ||
194 | |||
195 | /* | ||
196 | ======================================================================== | ||
197 | |||
198 | Routine Description: | ||
199 | Decrypt received WEP data | ||
200 | |||
201 | Arguments: | ||
202 | pAdapter Pointer to our adapter | ||
203 | pSrc Pointer to the received data | ||
204 | Len the length of the received data | ||
205 | |||
206 | Return Value: | ||
207 | TRUE Decrypt WEP data success | ||
208 | FALSE Decrypt WEP data failed | ||
209 | |||
210 | Note: | ||
211 | |||
212 | ======================================================================== | ||
213 | */ | ||
214 | BOOLEAN RTMPSoftDecryptWEP(struct rt_rtmp_adapter *pAd, | ||
215 | u8 *pData, | ||
216 | unsigned long DataByteCnt, struct rt_cipher_key *pGroupKey) | ||
217 | { | ||
218 | u32 trailfcs; | ||
219 | u32 crc32; | ||
220 | u8 KeyIdx; | ||
221 | u8 WEPKEY[] = { | ||
222 | /*IV */ | ||
223 | 0x00, 0x11, 0x22, | ||
224 | /*WEP KEY */ | ||
225 | 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, | ||
226 | 0xAA, 0xBB, 0xCC | ||
227 | }; | ||
228 | u8 *pPayload = (u8 *) pData + LENGTH_802_11; | ||
229 | unsigned long payload_len = DataByteCnt - LENGTH_802_11; | ||
230 | |||
231 | NdisMoveMemory(WEPKEY, pPayload, 3); /*Get WEP IV */ | ||
232 | |||
233 | KeyIdx = (*(pPayload + 3) & 0xc0) >> 6; | ||
234 | if (pGroupKey[KeyIdx].KeyLen == 0) | ||
235 | return (FALSE); | ||
236 | |||
237 | NdisMoveMemory(WEPKEY + 3, pGroupKey[KeyIdx].Key, | ||
238 | pGroupKey[KeyIdx].KeyLen); | ||
239 | ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, WEPKEY, | ||
240 | pGroupKey[KeyIdx].KeyLen + 3); | ||
241 | ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, pPayload, pPayload + 4, | ||
242 | payload_len - 4); | ||
243 | NdisMoveMemory(&trailfcs, pPayload + payload_len - 8, 4); | ||
244 | crc32 = RTMP_CALC_FCS32(PPPINITFCS32, pPayload, payload_len - 8); /*Skip last 4 bytes(FCS). */ | ||
245 | crc32 ^= 0xffffffff; /* complement */ | ||
246 | |||
247 | if (crc32 != cpu2le32(trailfcs)) { | ||
248 | DBGPRINT(RT_DEBUG_TRACE, ("WEP Data CRC Error!\n")); /*CRC error. */ | ||
249 | return (FALSE); | ||
250 | } | ||
251 | return (TRUE); | ||
252 | } | ||
253 | |||
254 | /* | ||
255 | ======================================================================== | ||
256 | |||
257 | Routine Description: | ||
258 | The Stream Cipher Encryption Algorithm "struct rt_arcfour" initialize | ||
259 | |||
260 | Arguments: | ||
261 | Ctx Pointer to struct rt_arcfour CONTEXT (SBOX) | ||
262 | pKey Pointer to the WEP KEY | ||
263 | KeyLen Indicate the length fo the WEP KEY | ||
264 | |||
265 | Return Value: | ||
266 | None | ||
267 | |||
268 | IRQL = DISPATCH_LEVEL | ||
269 | |||
270 | Note: | ||
271 | |||
272 | ======================================================================== | ||
273 | */ | ||
274 | void ARCFOUR_INIT(struct rt_arcfourcontext *Ctx, u8 *pKey, u32 KeyLen) | ||
275 | { | ||
276 | u8 t, u; | ||
277 | u32 keyindex; | ||
278 | u32 stateindex; | ||
279 | u8 *state; | ||
280 | u32 counter; | ||
281 | |||
282 | state = Ctx->STATE; | ||
283 | Ctx->X = 0; | ||
284 | Ctx->Y = 0; | ||
285 | for (counter = 0; counter < 256; counter++) | ||
286 | state[counter] = (u8)counter; | ||
287 | keyindex = 0; | ||
288 | stateindex = 0; | ||
289 | for (counter = 0; counter < 256; counter++) { | ||
290 | t = state[counter]; | ||
291 | stateindex = (stateindex + pKey[keyindex] + t) & 0xff; | ||
292 | u = state[stateindex]; | ||
293 | state[stateindex] = t; | ||
294 | state[counter] = u; | ||
295 | if (++keyindex >= KeyLen) | ||
296 | keyindex = 0; | ||
297 | } | ||
298 | } | ||
299 | |||
300 | /* | ||
301 | ======================================================================== | ||
302 | |||
303 | Routine Description: | ||
304 | Get bytes from struct rt_arcfour CONTEXT (S-BOX) | ||
305 | |||
306 | Arguments: | ||
307 | Ctx Pointer to struct rt_arcfour CONTEXT (SBOX) | ||
308 | |||
309 | Return Value: | ||
310 | u8 - the value of the struct rt_arcfour CONTEXT (S-BOX) | ||
311 | |||
312 | Note: | ||
313 | |||
314 | ======================================================================== | ||
315 | */ | ||
316 | u8 ARCFOUR_BYTE(struct rt_arcfourcontext *Ctx) | ||
317 | { | ||
318 | u32 x; | ||
319 | u32 y; | ||
320 | u8 sx, sy; | ||
321 | u8 *state; | ||
322 | |||
323 | state = Ctx->STATE; | ||
324 | x = (Ctx->X + 1) & 0xff; | ||
325 | sx = state[x]; | ||
326 | y = (sx + Ctx->Y) & 0xff; | ||
327 | sy = state[y]; | ||
328 | Ctx->X = x; | ||
329 | Ctx->Y = y; | ||
330 | state[y] = sx; | ||
331 | state[x] = sy; | ||
332 | |||
333 | return (state[(sx + sy) & 0xff]); | ||
334 | |||
335 | } | ||
336 | |||
337 | /* | ||
338 | ======================================================================== | ||
339 | |||
340 | Routine Description: | ||
341 | The Stream Cipher Decryption Algorithm | ||
342 | |||
343 | Arguments: | ||
344 | Ctx Pointer to struct rt_arcfour CONTEXT (SBOX) | ||
345 | pDest Pointer to the Destination | ||
346 | pSrc Pointer to the Source data | ||
347 | Len Indicate the length of the Source data | ||
348 | |||
349 | Return Value: | ||
350 | None | ||
351 | |||
352 | Note: | ||
353 | |||
354 | ======================================================================== | ||
355 | */ | ||
356 | void ARCFOUR_DECRYPT(struct rt_arcfourcontext *Ctx, | ||
357 | u8 *pDest, u8 *pSrc, u32 Len) | ||
358 | { | ||
359 | u32 i; | ||
360 | |||
361 | for (i = 0; i < Len; i++) | ||
362 | pDest[i] = pSrc[i] ^ ARCFOUR_BYTE(Ctx); | ||
363 | } | ||
364 | |||
365 | /* | ||
366 | ======================================================================== | ||
367 | |||
368 | Routine Description: | ||
369 | The Stream Cipher Encryption Algorithm | ||
370 | |||
371 | Arguments: | ||
372 | Ctx Pointer to struct rt_arcfour CONTEXT (SBOX) | ||
373 | pDest Pointer to the Destination | ||
374 | pSrc Pointer to the Source data | ||
375 | Len Indicate the length of the Source dta | ||
376 | |||
377 | Return Value: | ||
378 | None | ||
379 | |||
380 | IRQL = DISPATCH_LEVEL | ||
381 | |||
382 | Note: | ||
383 | |||
384 | ======================================================================== | ||
385 | */ | ||
386 | void ARCFOUR_ENCRYPT(struct rt_arcfourcontext *Ctx, | ||
387 | u8 *pDest, u8 *pSrc, u32 Len) | ||
388 | { | ||
389 | u32 i; | ||
390 | |||
391 | for (i = 0; i < Len; i++) | ||
392 | pDest[i] = pSrc[i] ^ ARCFOUR_BYTE(Ctx); | ||
393 | } | ||
394 | |||
395 | /* | ||
396 | ======================================================================== | ||
397 | |||
398 | Routine Description: | ||
399 | The Stream Cipher Encryption Algorithm which conform to the special requirement to encrypt GTK. | ||
400 | |||
401 | Arguments: | ||
402 | Ctx Pointer to struct rt_arcfour CONTEXT (SBOX) | ||
403 | pDest Pointer to the Destination | ||
404 | pSrc Pointer to the Source data | ||
405 | Len Indicate the length of the Source dta | ||
406 | |||
407 | ======================================================================== | ||
408 | */ | ||
409 | |||
410 | void WPAARCFOUR_ENCRYPT(struct rt_arcfourcontext *Ctx, | ||
411 | u8 *pDest, u8 *pSrc, u32 Len) | ||
412 | { | ||
413 | u32 i; | ||
414 | /*discard first 256 bytes */ | ||
415 | for (i = 0; i < 256; i++) | ||
416 | ARCFOUR_BYTE(Ctx); | ||
417 | |||
418 | for (i = 0; i < Len; i++) | ||
419 | pDest[i] = pSrc[i] ^ ARCFOUR_BYTE(Ctx); | ||
420 | } | ||
421 | |||
422 | /* | ||
423 | ======================================================================== | ||
424 | |||
425 | Routine Description: | ||
426 | Calculate a new FCS given the current FCS and the new data. | ||
427 | |||
428 | Arguments: | ||
429 | Fcs the original FCS value | ||
430 | Cp pointer to the data which will be calculate the FCS | ||
431 | Len the length of the data | ||
432 | |||
433 | Return Value: | ||
434 | u32 - FCS 32 bits | ||
435 | |||
436 | IRQL = DISPATCH_LEVEL | ||
437 | |||
438 | Note: | ||
439 | |||
440 | ======================================================================== | ||
441 | */ | ||
442 | u32 RTMP_CALC_FCS32(u32 Fcs, u8 *Cp, int Len) | ||
443 | { | ||
444 | while (Len--) | ||
445 | Fcs = (((Fcs) >> 8) ^ FCSTAB_32[((Fcs) ^ (*Cp++)) & 0xff]); | ||
446 | |||
447 | return (Fcs); | ||
448 | } | ||
449 | |||
450 | /* | ||
451 | ======================================================================== | ||
452 | |||
453 | Routine Description: | ||
454 | Get last FCS and encrypt it to the destination | ||
455 | |||
456 | Arguments: | ||
457 | pDest Pointer to the Destination | ||
458 | |||
459 | Return Value: | ||
460 | None | ||
461 | |||
462 | Note: | ||
463 | |||
464 | ======================================================================== | ||
465 | */ | ||
466 | void RTMPSetICV(struct rt_rtmp_adapter *pAd, u8 *pDest) | ||
467 | { | ||
468 | pAd->PrivateInfo.FCSCRC32 ^= 0xffffffff; /* complement */ | ||
469 | pAd->PrivateInfo.FCSCRC32 = cpu2le32(pAd->PrivateInfo.FCSCRC32); | ||
470 | |||
471 | ARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, pDest, | ||
472 | (u8 *)& pAd->PrivateInfo.FCSCRC32, 4); | ||
473 | } | ||
diff --git a/drivers/staging/rt2860/common/cmm_wpa.c b/drivers/staging/rt2860/common/cmm_wpa.c deleted file mode 100644 index 616ebec50c6..00000000000 --- a/drivers/staging/rt2860/common/cmm_wpa.c +++ /dev/null | |||
@@ -1,3010 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | |||
27 | Module Name: | ||
28 | wpa.c | ||
29 | |||
30 | Abstract: | ||
31 | |||
32 | Revision History: | ||
33 | Who When What | ||
34 | -------- ---------- ---------------------------------------------- | ||
35 | Jan Lee 03-07-22 Initial | ||
36 | Paul Lin 03-11-28 Modify for supplicant | ||
37 | */ | ||
38 | #include "../rt_config.h" | ||
39 | /* WPA OUI */ | ||
40 | u8 OUI_WPA_NONE_AKM[4] = { 0x00, 0x50, 0xF2, 0x00 }; | ||
41 | u8 OUI_WPA_VERSION[4] = { 0x00, 0x50, 0xF2, 0x01 }; | ||
42 | u8 OUI_WPA_WEP40[4] = { 0x00, 0x50, 0xF2, 0x01 }; | ||
43 | u8 OUI_WPA_TKIP[4] = { 0x00, 0x50, 0xF2, 0x02 }; | ||
44 | u8 OUI_WPA_CCMP[4] = { 0x00, 0x50, 0xF2, 0x04 }; | ||
45 | u8 OUI_WPA_WEP104[4] = { 0x00, 0x50, 0xF2, 0x05 }; | ||
46 | u8 OUI_WPA_8021X_AKM[4] = { 0x00, 0x50, 0xF2, 0x01 }; | ||
47 | u8 OUI_WPA_PSK_AKM[4] = { 0x00, 0x50, 0xF2, 0x02 }; | ||
48 | |||
49 | /* WPA2 OUI */ | ||
50 | u8 OUI_WPA2_WEP40[4] = { 0x00, 0x0F, 0xAC, 0x01 }; | ||
51 | u8 OUI_WPA2_TKIP[4] = { 0x00, 0x0F, 0xAC, 0x02 }; | ||
52 | u8 OUI_WPA2_CCMP[4] = { 0x00, 0x0F, 0xAC, 0x04 }; | ||
53 | u8 OUI_WPA2_8021X_AKM[4] = { 0x00, 0x0F, 0xAC, 0x01 }; | ||
54 | u8 OUI_WPA2_PSK_AKM[4] = { 0x00, 0x0F, 0xAC, 0x02 }; | ||
55 | u8 OUI_WPA2_WEP104[4] = { 0x00, 0x0F, 0xAC, 0x05 }; | ||
56 | |||
57 | static void ConstructEapolKeyData(struct rt_mac_table_entry *pEntry, | ||
58 | u8 GroupKeyWepStatus, | ||
59 | u8 keyDescVer, | ||
60 | u8 MsgType, | ||
61 | u8 DefaultKeyIdx, | ||
62 | u8 * GTK, | ||
63 | u8 * RSNIE, | ||
64 | u8 RSNIE_LEN, struct rt_eapol_packet * pMsg); | ||
65 | |||
66 | static void CalculateMIC(u8 KeyDescVer, | ||
67 | u8 * PTK, struct rt_eapol_packet * pMsg); | ||
68 | |||
69 | static void WpaEAPPacketAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); | ||
70 | |||
71 | static void WpaEAPOLASFAlertAction(struct rt_rtmp_adapter *pAd, | ||
72 | struct rt_mlme_queue_elem *Elem); | ||
73 | |||
74 | static void WpaEAPOLLogoffAction(struct rt_rtmp_adapter *pAd, | ||
75 | struct rt_mlme_queue_elem *Elem); | ||
76 | |||
77 | static void WpaEAPOLStartAction(struct rt_rtmp_adapter *pAd, | ||
78 | struct rt_mlme_queue_elem *Elem); | ||
79 | |||
80 | static void WpaEAPOLKeyAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem); | ||
81 | |||
82 | /* | ||
83 | ========================================================================== | ||
84 | Description: | ||
85 | association state machine init, including state transition and timer init | ||
86 | Parameters: | ||
87 | S - pointer to the association state machine | ||
88 | ========================================================================== | ||
89 | */ | ||
90 | void WpaStateMachineInit(struct rt_rtmp_adapter *pAd, | ||
91 | struct rt_state_machine *S, OUT STATE_MACHINE_FUNC Trans[]) | ||
92 | { | ||
93 | StateMachineInit(S, (STATE_MACHINE_FUNC *) Trans, MAX_WPA_PTK_STATE, | ||
94 | MAX_WPA_MSG, (STATE_MACHINE_FUNC) Drop, WPA_PTK, | ||
95 | WPA_MACHINE_BASE); | ||
96 | |||
97 | StateMachineSetAction(S, WPA_PTK, MT2_EAPPacket, | ||
98 | (STATE_MACHINE_FUNC) WpaEAPPacketAction); | ||
99 | StateMachineSetAction(S, WPA_PTK, MT2_EAPOLStart, | ||
100 | (STATE_MACHINE_FUNC) WpaEAPOLStartAction); | ||
101 | StateMachineSetAction(S, WPA_PTK, MT2_EAPOLLogoff, | ||
102 | (STATE_MACHINE_FUNC) WpaEAPOLLogoffAction); | ||
103 | StateMachineSetAction(S, WPA_PTK, MT2_EAPOLKey, | ||
104 | (STATE_MACHINE_FUNC) WpaEAPOLKeyAction); | ||
105 | StateMachineSetAction(S, WPA_PTK, MT2_EAPOLASFAlert, | ||
106 | (STATE_MACHINE_FUNC) WpaEAPOLASFAlertAction); | ||
107 | } | ||
108 | |||
109 | /* | ||
110 | ========================================================================== | ||
111 | Description: | ||
112 | this is state machine function. | ||
113 | When receiving EAP packets which is for 802.1x authentication use. | ||
114 | Not use in PSK case | ||
115 | Return: | ||
116 | ========================================================================== | ||
117 | */ | ||
118 | void WpaEAPPacketAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) | ||
119 | { | ||
120 | } | ||
121 | |||
122 | void WpaEAPOLASFAlertAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) | ||
123 | { | ||
124 | } | ||
125 | |||
126 | void WpaEAPOLLogoffAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) | ||
127 | { | ||
128 | } | ||
129 | |||
130 | /* | ||
131 | ========================================================================== | ||
132 | Description: | ||
133 | Start 4-way HS when rcv EAPOL_START which may create by our driver in assoc.c | ||
134 | Return: | ||
135 | ========================================================================== | ||
136 | */ | ||
137 | void WpaEAPOLStartAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) | ||
138 | { | ||
139 | struct rt_mac_table_entry *pEntry; | ||
140 | struct rt_header_802_11 * pHeader; | ||
141 | |||
142 | DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLStartAction ===> \n")); | ||
143 | |||
144 | pHeader = (struct rt_header_802_11 *) Elem->Msg; | ||
145 | |||
146 | /*For normaol PSK, we enqueue an EAPOL-Start command to trigger the process. */ | ||
147 | if (Elem->MsgLen == 6) | ||
148 | pEntry = MacTableLookup(pAd, Elem->Msg); | ||
149 | else { | ||
150 | pEntry = MacTableLookup(pAd, pHeader->Addr2); | ||
151 | } | ||
152 | |||
153 | if (pEntry) { | ||
154 | DBGPRINT(RT_DEBUG_TRACE, | ||
155 | (" PortSecured(%d), WpaState(%d), AuthMode(%d), PMKID_CacheIdx(%d) \n", | ||
156 | pEntry->PortSecured, pEntry->WpaState, | ||
157 | pEntry->AuthMode, pEntry->PMKID_CacheIdx)); | ||
158 | |||
159 | if ((pEntry->PortSecured == WPA_802_1X_PORT_NOT_SECURED) | ||
160 | && (pEntry->WpaState < AS_PTKSTART) | ||
161 | && ((pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) | ||
162 | || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) | ||
163 | || ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) | ||
164 | && (pEntry->PMKID_CacheIdx != ENTRY_NOT_FOUND)))) { | ||
165 | pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; | ||
166 | pEntry->WpaState = AS_INITPSK; | ||
167 | pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; | ||
168 | NdisZeroMemory(pEntry->R_Counter, | ||
169 | sizeof(pEntry->R_Counter)); | ||
170 | pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR; | ||
171 | |||
172 | WPAStart4WayHS(pAd, pEntry, PEER_MSG1_RETRY_EXEC_INTV); | ||
173 | } | ||
174 | } | ||
175 | } | ||
176 | |||
177 | /* | ||
178 | ========================================================================== | ||
179 | Description: | ||
180 | This is state machine function. | ||
181 | When receiving EAPOL packets which is for 802.1x key management. | ||
182 | Use both in WPA, and WPAPSK case. | ||
183 | In this function, further dispatch to different functions according to the received packet. 3 categories are : | ||
184 | 1. normal 4-way pairwisekey and 2-way groupkey handshake | ||
185 | 2. MIC error (Countermeasures attack) report packet from STA. | ||
186 | 3. Request for pairwise/group key update from STA | ||
187 | Return: | ||
188 | ========================================================================== | ||
189 | */ | ||
190 | void WpaEAPOLKeyAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) | ||
191 | { | ||
192 | struct rt_mac_table_entry *pEntry; | ||
193 | struct rt_header_802_11 * pHeader; | ||
194 | struct rt_eapol_packet * pEapol_packet; | ||
195 | struct rt_key_info peerKeyInfo; | ||
196 | |||
197 | DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLKeyAction ===>\n")); | ||
198 | |||
199 | pHeader = (struct rt_header_802_11 *) Elem->Msg; | ||
200 | pEapol_packet = | ||
201 | (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; | ||
202 | |||
203 | NdisZeroMemory((u8 *)& peerKeyInfo, sizeof(peerKeyInfo)); | ||
204 | NdisMoveMemory((u8 *)& peerKeyInfo, | ||
205 | (u8 *)& pEapol_packet->KeyDesc.KeyInfo, | ||
206 | sizeof(struct rt_key_info)); | ||
207 | |||
208 | hex_dump("Received Eapol frame", (unsigned char *)pEapol_packet, | ||
209 | (Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H)); | ||
210 | |||
211 | *((u16 *) & peerKeyInfo) = cpu2le16(*((u16 *) & peerKeyInfo)); | ||
212 | |||
213 | do { | ||
214 | pEntry = MacTableLookup(pAd, pHeader->Addr2); | ||
215 | |||
216 | if (!pEntry | ||
217 | || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli))) | ||
218 | break; | ||
219 | |||
220 | if (pEntry->AuthMode < Ndis802_11AuthModeWPA) | ||
221 | break; | ||
222 | |||
223 | DBGPRINT(RT_DEBUG_TRACE, | ||
224 | ("Receive EAPoL-Key frame from STA %pMF\n", | ||
225 | pEntry->Addr)); | ||
226 | |||
227 | if (((pEapol_packet->ProVer != EAPOL_VER) | ||
228 | && (pEapol_packet->ProVer != EAPOL_VER2)) | ||
229 | || ((pEapol_packet->KeyDesc.Type != WPA1_KEY_DESC) | ||
230 | && (pEapol_packet->KeyDesc.Type != WPA2_KEY_DESC))) { | ||
231 | DBGPRINT(RT_DEBUG_ERROR, | ||
232 | ("Key descripter does not match with WPA rule\n")); | ||
233 | break; | ||
234 | } | ||
235 | /* The value 1 shall be used for all EAPOL-Key frames to and from a STA when */ | ||
236 | /* neither the group nor pairwise ciphers are CCMP for Key Descriptor 1. */ | ||
237 | if ((pEntry->WepStatus == Ndis802_11Encryption2Enabled) | ||
238 | && (peerKeyInfo.KeyDescVer != DESC_TYPE_TKIP)) { | ||
239 | DBGPRINT(RT_DEBUG_ERROR, | ||
240 | ("Key descripter version not match(TKIP) \n")); | ||
241 | break; | ||
242 | } | ||
243 | /* The value 2 shall be used for all EAPOL-Key frames to and from a STA when */ | ||
244 | /* either the pairwise or the group cipher is AES-CCMP for Key Descriptor 2. */ | ||
245 | else if ((pEntry->WepStatus == Ndis802_11Encryption3Enabled) | ||
246 | && (peerKeyInfo.KeyDescVer != DESC_TYPE_AES)) { | ||
247 | DBGPRINT(RT_DEBUG_ERROR, | ||
248 | ("Key descripter version not match(AES) \n")); | ||
249 | break; | ||
250 | } | ||
251 | /* Check if this STA is in class 3 state and the WPA state is started */ | ||
252 | if ((pEntry->Sst == SST_ASSOC) | ||
253 | && (pEntry->WpaState >= AS_INITPSK)) { | ||
254 | /* Check the Key Ack (bit 7) of the Key Information to determine the Authenticator */ | ||
255 | /* or not. */ | ||
256 | /* An EAPOL-Key frame that is sent by the Supplicant in response to an EAPOL- */ | ||
257 | /* Key frame from the Authenticator must not have the Ack bit set. */ | ||
258 | if (peerKeyInfo.KeyAck == 1) { | ||
259 | /* The frame is snet by Authenticator. */ | ||
260 | /* So the Supplicant side shall handle this. */ | ||
261 | |||
262 | if ((peerKeyInfo.Secure == 0) | ||
263 | && (peerKeyInfo.Request == 0) | ||
264 | && (peerKeyInfo.Error == 0) | ||
265 | && (peerKeyInfo.KeyType == PAIRWISEKEY)) { | ||
266 | /* Process 1. the message 1 of 4-way HS in WPA or WPA2 */ | ||
267 | /* EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1) */ | ||
268 | /* 2. the message 3 of 4-way HS in WPA */ | ||
269 | /* EAPOL-Key(0,1,1,1,P,0,KeyRSC,ANonce,MIC,DataKD_M3) */ | ||
270 | if (peerKeyInfo.KeyMic == 0) | ||
271 | PeerPairMsg1Action(pAd, pEntry, | ||
272 | Elem); | ||
273 | else | ||
274 | PeerPairMsg3Action(pAd, pEntry, | ||
275 | Elem); | ||
276 | } else if ((peerKeyInfo.Secure == 1) | ||
277 | && (peerKeyInfo.KeyMic == 1) | ||
278 | && (peerKeyInfo.Request == 0) | ||
279 | && (peerKeyInfo.Error == 0)) { | ||
280 | /* Process 1. the message 3 of 4-way HS in WPA2 */ | ||
281 | /* EAPOL-Key(1,1,1,1,P,0,KeyRSC,ANonce,MIC,DataKD_M3) */ | ||
282 | /* 2. the message 1 of group KS in WPA or WPA2 */ | ||
283 | /* EAPOL-Key(1,1,1,0,G,0,Key RSC,0, MIC,GTK[N]) */ | ||
284 | if (peerKeyInfo.KeyType == PAIRWISEKEY) | ||
285 | PeerPairMsg3Action(pAd, pEntry, | ||
286 | Elem); | ||
287 | else | ||
288 | PeerGroupMsg1Action(pAd, pEntry, | ||
289 | Elem); | ||
290 | } | ||
291 | } else { | ||
292 | /* The frame is snet by Supplicant. */ | ||
293 | /* So the Authenticator side shall handle this. */ | ||
294 | if ((peerKeyInfo.Request == 0) && | ||
295 | (peerKeyInfo.Error == 0) && | ||
296 | (peerKeyInfo.KeyMic == 1)) { | ||
297 | if (peerKeyInfo.Secure == 0 | ||
298 | && peerKeyInfo.KeyType == | ||
299 | PAIRWISEKEY) { | ||
300 | /* EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,Data) */ | ||
301 | /* Process 1. message 2 of 4-way HS in WPA or WPA2 */ | ||
302 | /* 2. message 4 of 4-way HS in WPA */ | ||
303 | if (CONV_ARRARY_TO_u16 | ||
304 | (pEapol_packet->KeyDesc. | ||
305 | KeyDataLen) == 0) { | ||
306 | PeerPairMsg4Action(pAd, | ||
307 | pEntry, | ||
308 | Elem); | ||
309 | } else { | ||
310 | PeerPairMsg2Action(pAd, | ||
311 | pEntry, | ||
312 | Elem); | ||
313 | } | ||
314 | } else if (peerKeyInfo.Secure == 1 | ||
315 | && peerKeyInfo.KeyType == | ||
316 | PAIRWISEKEY) { | ||
317 | /* EAPOL-Key(1,1,0,0,P,0,0,0,MIC,0) */ | ||
318 | /* Process message 4 of 4-way HS in WPA2 */ | ||
319 | PeerPairMsg4Action(pAd, pEntry, | ||
320 | Elem); | ||
321 | } else if (peerKeyInfo.Secure == 1 | ||
322 | && peerKeyInfo.KeyType == | ||
323 | GROUPKEY) { | ||
324 | /* EAPOL-Key(1,1,0,0,G,0,0,0,MIC,0) */ | ||
325 | /* Process message 2 of Group key HS in WPA or WPA2 */ | ||
326 | PeerGroupMsg2Action(pAd, pEntry, | ||
327 | &Elem-> | ||
328 | Msg | ||
329 | [LENGTH_802_11], | ||
330 | (Elem-> | ||
331 | MsgLen - | ||
332 | LENGTH_802_11)); | ||
333 | } | ||
334 | } | ||
335 | } | ||
336 | } | ||
337 | } while (FALSE); | ||
338 | } | ||
339 | |||
340 | /* | ||
341 | ======================================================================== | ||
342 | |||
343 | Routine Description: | ||
344 | Copy frame from waiting queue into relative ring buffer and set | ||
345 | appropriate ASIC register to kick hardware encryption before really | ||
346 | sent out to air. | ||
347 | |||
348 | Arguments: | ||
349 | pAd Pointer to our adapter | ||
350 | void * Pointer to outgoing Ndis frame | ||
351 | NumberOfFrag Number of fragment required | ||
352 | |||
353 | Return Value: | ||
354 | None | ||
355 | |||
356 | Note: | ||
357 | |||
358 | ======================================================================== | ||
359 | */ | ||
360 | void RTMPToWirelessSta(struct rt_rtmp_adapter *pAd, | ||
361 | struct rt_mac_table_entry *pEntry, | ||
362 | u8 *pHeader802_3, | ||
363 | u32 HdrLen, | ||
364 | u8 *pData, u32 DataLen, IN BOOLEAN bClearFrame) | ||
365 | { | ||
366 | void *pPacket; | ||
367 | int Status; | ||
368 | |||
369 | if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli))) | ||
370 | return; | ||
371 | |||
372 | do { | ||
373 | /* build a NDIS packet */ | ||
374 | Status = | ||
375 | RTMPAllocateNdisPacket(pAd, &pPacket, pHeader802_3, HdrLen, | ||
376 | pData, DataLen); | ||
377 | if (Status != NDIS_STATUS_SUCCESS) | ||
378 | break; | ||
379 | |||
380 | if (bClearFrame) | ||
381 | RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 1); | ||
382 | else | ||
383 | RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 0); | ||
384 | { | ||
385 | RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS); | ||
386 | |||
387 | RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, MAIN_MBSSID); /* set a default value */ | ||
388 | if (pEntry->apidx != 0) | ||
389 | RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, | ||
390 | pEntry-> | ||
391 | apidx); | ||
392 | |||
393 | RTMP_SET_PACKET_WCID(pPacket, (u8)pEntry->Aid); | ||
394 | RTMP_SET_PACKET_MOREDATA(pPacket, FALSE); | ||
395 | } | ||
396 | |||
397 | { | ||
398 | /* send out the packet */ | ||
399 | Status = STASendPacket(pAd, pPacket); | ||
400 | if (Status == NDIS_STATUS_SUCCESS) { | ||
401 | u8 Index; | ||
402 | |||
403 | /* Dequeue one frame from TxSwQueue0..3 queue and process it */ | ||
404 | /* There are three place calling dequeue for TX ring. */ | ||
405 | /* 1. Here, right after queueing the frame. */ | ||
406 | /* 2. At the end of TxRingTxDone service routine. */ | ||
407 | /* 3. Upon NDIS call RTMPSendPackets */ | ||
408 | if ((!RTMP_TEST_FLAG | ||
409 | (pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) | ||
410 | && | ||
411 | (!RTMP_TEST_FLAG | ||
412 | (pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS))) { | ||
413 | for (Index = 0; Index < 5; Index++) | ||
414 | if (pAd->TxSwQueue[Index]. | ||
415 | Number > 0) | ||
416 | RTMPDeQueuePacket(pAd, | ||
417 | FALSE, | ||
418 | Index, | ||
419 | MAX_TX_PROCESS); | ||
420 | } | ||
421 | } | ||
422 | } | ||
423 | |||
424 | } while (FALSE); | ||
425 | } | ||
426 | |||
427 | /* | ||
428 | ========================================================================== | ||
429 | Description: | ||
430 | This is a function to initialize 4-way handshake | ||
431 | |||
432 | Return: | ||
433 | |||
434 | ========================================================================== | ||
435 | */ | ||
436 | void WPAStart4WayHS(struct rt_rtmp_adapter *pAd, | ||
437 | struct rt_mac_table_entry *pEntry, unsigned long TimeInterval) | ||
438 | { | ||
439 | u8 Header802_3[14]; | ||
440 | struct rt_eapol_packet EAPOLPKT; | ||
441 | u8 *pBssid = NULL; | ||
442 | u8 group_cipher = Ndis802_11WEPDisabled; | ||
443 | |||
444 | DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart4WayHS\n")); | ||
445 | |||
446 | if (RTMP_TEST_FLAG | ||
447 | (pAd, | ||
448 | fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS)) | ||
449 | { | ||
450 | DBGPRINT(RT_DEBUG_ERROR, | ||
451 | ("[ERROR]WPAStart4WayHS : The interface is closed...\n")); | ||
452 | return; | ||
453 | } | ||
454 | |||
455 | if (pBssid == NULL) { | ||
456 | DBGPRINT(RT_DEBUG_ERROR, | ||
457 | ("[ERROR]WPAStart4WayHS : No corresponding Authenticator.\n")); | ||
458 | return; | ||
459 | } | ||
460 | /* Check the status */ | ||
461 | if ((pEntry->WpaState > AS_PTKSTART) || (pEntry->WpaState < AS_INITPMK)) { | ||
462 | DBGPRINT(RT_DEBUG_ERROR, | ||
463 | ("[ERROR]WPAStart4WayHS : Not expect calling\n")); | ||
464 | return; | ||
465 | } | ||
466 | |||
467 | /* Increment replay counter by 1 */ | ||
468 | ADD_ONE_To_64BIT_VAR(pEntry->R_Counter); | ||
469 | |||
470 | /* Randomly generate ANonce */ | ||
471 | GenRandom(pAd, (u8 *) pBssid, pEntry->ANonce); | ||
472 | |||
473 | /* Construct EAPoL message - Pairwise Msg 1 */ | ||
474 | /* EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1) */ | ||
475 | NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet)); | ||
476 | ConstructEapolMsg(pEntry, group_cipher, EAPOL_PAIR_MSG_1, 0, /* Default key index */ | ||
477 | pEntry->ANonce, NULL, /* TxRSC */ | ||
478 | NULL, /* GTK */ | ||
479 | NULL, /* RSNIE */ | ||
480 | 0, /* RSNIE length */ | ||
481 | &EAPOLPKT); | ||
482 | |||
483 | /* Make outgoing frame */ | ||
484 | MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL); | ||
485 | RTMPToWirelessSta(pAd, pEntry, Header802_3, | ||
486 | LENGTH_802_3, (u8 *)& EAPOLPKT, | ||
487 | CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, | ||
488 | (pEntry->PortSecured == | ||
489 | WPA_802_1X_PORT_SECURED) ? FALSE : TRUE); | ||
490 | |||
491 | /* Trigger Retry Timer */ | ||
492 | RTMPModTimer(&pEntry->RetryTimer, TimeInterval); | ||
493 | |||
494 | /* Update State */ | ||
495 | pEntry->WpaState = AS_PTKSTART; | ||
496 | |||
497 | DBGPRINT(RT_DEBUG_TRACE, | ||
498 | ("<=== WPAStart4WayHS: send Msg1 of 4-way \n")); | ||
499 | |||
500 | } | ||
501 | |||
502 | /* | ||
503 | ======================================================================== | ||
504 | |||
505 | Routine Description: | ||
506 | Process Pairwise key Msg-1 of 4-way handshaking and send Msg-2 | ||
507 | |||
508 | Arguments: | ||
509 | pAd Pointer to our adapter | ||
510 | Elem Message body | ||
511 | |||
512 | Return Value: | ||
513 | None | ||
514 | |||
515 | Note: | ||
516 | |||
517 | ======================================================================== | ||
518 | */ | ||
519 | void PeerPairMsg1Action(struct rt_rtmp_adapter *pAd, | ||
520 | struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem) | ||
521 | { | ||
522 | u8 PTK[80]; | ||
523 | u8 Header802_3[14]; | ||
524 | struct rt_eapol_packet * pMsg1; | ||
525 | u32 MsgLen; | ||
526 | struct rt_eapol_packet EAPOLPKT; | ||
527 | u8 *pCurrentAddr = NULL; | ||
528 | u8 *pmk_ptr = NULL; | ||
529 | u8 group_cipher = Ndis802_11WEPDisabled; | ||
530 | u8 *rsnie_ptr = NULL; | ||
531 | u8 rsnie_len = 0; | ||
532 | |||
533 | DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg1Action \n")); | ||
534 | |||
535 | if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli))) | ||
536 | return; | ||
537 | |||
538 | if (Elem->MsgLen < | ||
539 | (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + | ||
540 | sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2)) | ||
541 | return; | ||
542 | |||
543 | { | ||
544 | pCurrentAddr = pAd->CurrentAddress; | ||
545 | pmk_ptr = pAd->StaCfg.PMK; | ||
546 | group_cipher = pAd->StaCfg.GroupCipher; | ||
547 | rsnie_ptr = pAd->StaCfg.RSN_IE; | ||
548 | rsnie_len = pAd->StaCfg.RSNIE_Len; | ||
549 | } | ||
550 | |||
551 | /* Store the received frame */ | ||
552 | pMsg1 = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; | ||
553 | MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; | ||
554 | |||
555 | /* Sanity Check peer Pairwise message 1 - Replay Counter */ | ||
556 | if (PeerWpaMessageSanity(pAd, pMsg1, MsgLen, EAPOL_PAIR_MSG_1, pEntry) | ||
557 | == FALSE) | ||
558 | return; | ||
559 | |||
560 | /* Store Replay counter, it will use to verify message 3 and construct message 2 */ | ||
561 | NdisMoveMemory(pEntry->R_Counter, pMsg1->KeyDesc.ReplayCounter, | ||
562 | LEN_KEY_DESC_REPLAY); | ||
563 | |||
564 | /* Store ANonce */ | ||
565 | NdisMoveMemory(pEntry->ANonce, pMsg1->KeyDesc.KeyNonce, | ||
566 | LEN_KEY_DESC_NONCE); | ||
567 | |||
568 | /* Generate random SNonce */ | ||
569 | GenRandom(pAd, (u8 *) pCurrentAddr, pEntry->SNonce); | ||
570 | |||
571 | { | ||
572 | /* Calculate PTK(ANonce, SNonce) */ | ||
573 | WpaDerivePTK(pAd, | ||
574 | pmk_ptr, | ||
575 | pEntry->ANonce, | ||
576 | pEntry->Addr, | ||
577 | pEntry->SNonce, pCurrentAddr, PTK, LEN_PTK); | ||
578 | |||
579 | /* Save key to PTK entry */ | ||
580 | NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK); | ||
581 | } | ||
582 | |||
583 | /* Update WpaState */ | ||
584 | pEntry->WpaState = AS_PTKINIT_NEGOTIATING; | ||
585 | |||
586 | /* Construct EAPoL message - Pairwise Msg 2 */ | ||
587 | /* EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,DataKD_M2) */ | ||
588 | NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet)); | ||
589 | ConstructEapolMsg(pEntry, group_cipher, EAPOL_PAIR_MSG_2, 0, /* DefaultKeyIdx */ | ||
590 | pEntry->SNonce, NULL, /* TxRsc */ | ||
591 | NULL, /* GTK */ | ||
592 | (u8 *) rsnie_ptr, rsnie_len, &EAPOLPKT); | ||
593 | |||
594 | /* Make outgoing frame */ | ||
595 | MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL); | ||
596 | |||
597 | RTMPToWirelessSta(pAd, pEntry, | ||
598 | Header802_3, sizeof(Header802_3), (u8 *)& EAPOLPKT, | ||
599 | CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, TRUE); | ||
600 | |||
601 | DBGPRINT(RT_DEBUG_TRACE, | ||
602 | ("<=== PeerPairMsg1Action: send Msg2 of 4-way \n")); | ||
603 | } | ||
604 | |||
605 | /* | ||
606 | ========================================================================== | ||
607 | Description: | ||
608 | When receiving the second packet of 4-way pairwisekey handshake. | ||
609 | Return: | ||
610 | ========================================================================== | ||
611 | */ | ||
612 | void PeerPairMsg2Action(struct rt_rtmp_adapter *pAd, | ||
613 | struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem) | ||
614 | { | ||
615 | u8 PTK[80]; | ||
616 | BOOLEAN Cancelled; | ||
617 | struct rt_header_802_11 * pHeader; | ||
618 | struct rt_eapol_packet EAPOLPKT; | ||
619 | struct rt_eapol_packet * pMsg2; | ||
620 | u32 MsgLen; | ||
621 | u8 Header802_3[LENGTH_802_3]; | ||
622 | u8 TxTsc[6]; | ||
623 | u8 *pBssid = NULL; | ||
624 | u8 *pmk_ptr = NULL; | ||
625 | u8 *gtk_ptr = NULL; | ||
626 | u8 default_key = 0; | ||
627 | u8 group_cipher = Ndis802_11WEPDisabled; | ||
628 | u8 *rsnie_ptr = NULL; | ||
629 | u8 rsnie_len = 0; | ||
630 | |||
631 | DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg2Action \n")); | ||
632 | |||
633 | if ((!pEntry) || (!pEntry->ValidAsCLI)) | ||
634 | return; | ||
635 | |||
636 | if (Elem->MsgLen < | ||
637 | (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + | ||
638 | sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2)) | ||
639 | return; | ||
640 | |||
641 | /* check Entry in valid State */ | ||
642 | if (pEntry->WpaState < AS_PTKSTART) | ||
643 | return; | ||
644 | |||
645 | /* pointer to 802.11 header */ | ||
646 | pHeader = (struct rt_header_802_11 *) Elem->Msg; | ||
647 | |||
648 | /* skip 802.11_header(24-byte) and LLC_header(8) */ | ||
649 | pMsg2 = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; | ||
650 | MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; | ||
651 | |||
652 | /* Store SNonce */ | ||
653 | NdisMoveMemory(pEntry->SNonce, pMsg2->KeyDesc.KeyNonce, | ||
654 | LEN_KEY_DESC_NONCE); | ||
655 | |||
656 | { | ||
657 | /* Derive PTK */ | ||
658 | WpaDerivePTK(pAd, (u8 *) pmk_ptr, pEntry->ANonce, /* ANONCE */ | ||
659 | (u8 *) pBssid, pEntry->SNonce, /* SNONCE */ | ||
660 | pEntry->Addr, PTK, LEN_PTK); | ||
661 | |||
662 | NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK); | ||
663 | } | ||
664 | |||
665 | /* Sanity Check peer Pairwise message 2 - Replay Counter, MIC, RSNIE */ | ||
666 | if (PeerWpaMessageSanity(pAd, pMsg2, MsgLen, EAPOL_PAIR_MSG_2, pEntry) | ||
667 | == FALSE) | ||
668 | return; | ||
669 | |||
670 | do { | ||
671 | /* delete retry timer */ | ||
672 | RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); | ||
673 | |||
674 | /* Change state */ | ||
675 | pEntry->WpaState = AS_PTKINIT_NEGOTIATING; | ||
676 | |||
677 | /* Increment replay counter by 1 */ | ||
678 | ADD_ONE_To_64BIT_VAR(pEntry->R_Counter); | ||
679 | |||
680 | /* Construct EAPoL message - Pairwise Msg 3 */ | ||
681 | NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet)); | ||
682 | ConstructEapolMsg(pEntry, | ||
683 | group_cipher, | ||
684 | EAPOL_PAIR_MSG_3, | ||
685 | default_key, | ||
686 | pEntry->ANonce, | ||
687 | TxTsc, | ||
688 | (u8 *) gtk_ptr, | ||
689 | (u8 *) rsnie_ptr, rsnie_len, &EAPOLPKT); | ||
690 | |||
691 | /* Make outgoing frame */ | ||
692 | MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL); | ||
693 | RTMPToWirelessSta(pAd, pEntry, Header802_3, LENGTH_802_3, | ||
694 | (u8 *)& EAPOLPKT, | ||
695 | CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, | ||
696 | (pEntry->PortSecured == | ||
697 | WPA_802_1X_PORT_SECURED) ? FALSE : TRUE); | ||
698 | |||
699 | pEntry->ReTryCounter = PEER_MSG3_RETRY_TIMER_CTR; | ||
700 | RTMPSetTimer(&pEntry->RetryTimer, PEER_MSG3_RETRY_EXEC_INTV); | ||
701 | |||
702 | /* Update State */ | ||
703 | pEntry->WpaState = AS_PTKINIT_NEGOTIATING; | ||
704 | } while (FALSE); | ||
705 | |||
706 | DBGPRINT(RT_DEBUG_TRACE, | ||
707 | ("<=== PeerPairMsg2Action: send Msg3 of 4-way \n")); | ||
708 | } | ||
709 | |||
710 | /* | ||
711 | ======================================================================== | ||
712 | |||
713 | Routine Description: | ||
714 | Process Pairwise key Msg 3 of 4-way handshaking and send Msg 4 | ||
715 | |||
716 | Arguments: | ||
717 | pAd Pointer to our adapter | ||
718 | Elem Message body | ||
719 | |||
720 | Return Value: | ||
721 | None | ||
722 | |||
723 | Note: | ||
724 | |||
725 | ======================================================================== | ||
726 | */ | ||
727 | void PeerPairMsg3Action(struct rt_rtmp_adapter *pAd, | ||
728 | struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem) | ||
729 | { | ||
730 | struct rt_header_802_11 * pHeader; | ||
731 | u8 Header802_3[14]; | ||
732 | struct rt_eapol_packet EAPOLPKT; | ||
733 | struct rt_eapol_packet * pMsg3; | ||
734 | u32 MsgLen; | ||
735 | u8 *pCurrentAddr = NULL; | ||
736 | u8 group_cipher = Ndis802_11WEPDisabled; | ||
737 | |||
738 | DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg3Action \n")); | ||
739 | |||
740 | if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli))) | ||
741 | return; | ||
742 | |||
743 | if (Elem->MsgLen < | ||
744 | (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + | ||
745 | sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2)) | ||
746 | return; | ||
747 | |||
748 | { | ||
749 | pCurrentAddr = pAd->CurrentAddress; | ||
750 | group_cipher = pAd->StaCfg.GroupCipher; | ||
751 | |||
752 | } | ||
753 | |||
754 | /* Record 802.11 header & the received EAPOL packet Msg3 */ | ||
755 | pHeader = (struct rt_header_802_11 *) Elem->Msg; | ||
756 | pMsg3 = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; | ||
757 | MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; | ||
758 | |||
759 | /* Sanity Check peer Pairwise message 3 - Replay Counter, MIC, RSNIE */ | ||
760 | if (PeerWpaMessageSanity(pAd, pMsg3, MsgLen, EAPOL_PAIR_MSG_3, pEntry) | ||
761 | == FALSE) | ||
762 | return; | ||
763 | |||
764 | /* Save Replay counter, it will use construct message 4 */ | ||
765 | NdisMoveMemory(pEntry->R_Counter, pMsg3->KeyDesc.ReplayCounter, | ||
766 | LEN_KEY_DESC_REPLAY); | ||
767 | |||
768 | /* Double check ANonce */ | ||
769 | if (!NdisEqualMemory | ||
770 | (pEntry->ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE)) { | ||
771 | return; | ||
772 | } | ||
773 | /* Construct EAPoL message - Pairwise Msg 4 */ | ||
774 | NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet)); | ||
775 | ConstructEapolMsg(pEntry, group_cipher, EAPOL_PAIR_MSG_4, 0, /* group key index not used in message 4 */ | ||
776 | NULL, /* Nonce not used in message 4 */ | ||
777 | NULL, /* TxRSC not used in message 4 */ | ||
778 | NULL, /* GTK not used in message 4 */ | ||
779 | NULL, /* RSN IE not used in message 4 */ | ||
780 | 0, &EAPOLPKT); | ||
781 | |||
782 | /* Update WpaState */ | ||
783 | pEntry->WpaState = AS_PTKINITDONE; | ||
784 | |||
785 | /* Update pairwise key */ | ||
786 | { | ||
787 | struct rt_cipher_key *pSharedKey; | ||
788 | |||
789 | pSharedKey = &pAd->SharedKey[BSS0][0]; | ||
790 | |||
791 | NdisMoveMemory(pAd->StaCfg.PTK, pEntry->PTK, LEN_PTK); | ||
792 | |||
793 | /* Prepare pair-wise key information into shared key table */ | ||
794 | NdisZeroMemory(pSharedKey, sizeof(struct rt_cipher_key)); | ||
795 | pSharedKey->KeyLen = LEN_TKIP_EK; | ||
796 | NdisMoveMemory(pSharedKey->Key, &pAd->StaCfg.PTK[32], | ||
797 | LEN_TKIP_EK); | ||
798 | NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.PTK[48], | ||
799 | LEN_TKIP_RXMICK); | ||
800 | NdisMoveMemory(pSharedKey->TxMic, | ||
801 | &pAd->StaCfg.PTK[48 + LEN_TKIP_RXMICK], | ||
802 | LEN_TKIP_TXMICK); | ||
803 | |||
804 | /* Decide its ChiperAlg */ | ||
805 | if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) | ||
806 | pSharedKey->CipherAlg = CIPHER_TKIP; | ||
807 | else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) | ||
808 | pSharedKey->CipherAlg = CIPHER_AES; | ||
809 | else | ||
810 | pSharedKey->CipherAlg = CIPHER_NONE; | ||
811 | |||
812 | /* Update these related information to struct rt_mac_table_entry */ | ||
813 | pEntry = &pAd->MacTab.Content[BSSID_WCID]; | ||
814 | NdisMoveMemory(pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32], | ||
815 | LEN_TKIP_EK); | ||
816 | NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48], | ||
817 | LEN_TKIP_RXMICK); | ||
818 | NdisMoveMemory(pEntry->PairwiseKey.TxMic, | ||
819 | &pAd->StaCfg.PTK[48 + LEN_TKIP_RXMICK], | ||
820 | LEN_TKIP_TXMICK); | ||
821 | pEntry->PairwiseKey.CipherAlg = pSharedKey->CipherAlg; | ||
822 | |||
823 | /* Update pairwise key information to ASIC Shared Key Table */ | ||
824 | AsicAddSharedKeyEntry(pAd, | ||
825 | BSS0, | ||
826 | 0, | ||
827 | pSharedKey->CipherAlg, | ||
828 | pSharedKey->Key, | ||
829 | pSharedKey->TxMic, pSharedKey->RxMic); | ||
830 | |||
831 | /* Update ASIC WCID attribute table and IVEIV table */ | ||
832 | RTMPAddWcidAttributeEntry(pAd, | ||
833 | BSS0, | ||
834 | 0, pSharedKey->CipherAlg, pEntry); | ||
835 | |||
836 | } | ||
837 | |||
838 | /* open 802.1x port control and privacy filter */ | ||
839 | if (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK || | ||
840 | pEntry->AuthMode == Ndis802_11AuthModeWPA2) { | ||
841 | pEntry->PortSecured = WPA_802_1X_PORT_SECURED; | ||
842 | pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; | ||
843 | |||
844 | STA_PORT_SECURED(pAd); | ||
845 | /* Indicate Connected for GUI */ | ||
846 | pAd->IndicateMediaState = NdisMediaStateConnected; | ||
847 | DBGPRINT(RT_DEBUG_TRACE, | ||
848 | ("PeerPairMsg3Action: AuthMode(%s) PairwiseCipher(%s) GroupCipher(%s) \n", | ||
849 | GetAuthMode(pEntry->AuthMode), | ||
850 | GetEncryptType(pEntry->WepStatus), | ||
851 | GetEncryptType(group_cipher))); | ||
852 | } else { | ||
853 | } | ||
854 | |||
855 | /* Init 802.3 header and send out */ | ||
856 | MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL); | ||
857 | RTMPToWirelessSta(pAd, pEntry, | ||
858 | Header802_3, sizeof(Header802_3), | ||
859 | (u8 *)& EAPOLPKT, | ||
860 | CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, TRUE); | ||
861 | |||
862 | DBGPRINT(RT_DEBUG_TRACE, | ||
863 | ("<=== PeerPairMsg3Action: send Msg4 of 4-way \n")); | ||
864 | } | ||
865 | |||
866 | /* | ||
867 | ========================================================================== | ||
868 | Description: | ||
869 | When receiving the last packet of 4-way pairwisekey handshake. | ||
870 | Initialize 2-way groupkey handshake following. | ||
871 | Return: | ||
872 | ========================================================================== | ||
873 | */ | ||
874 | void PeerPairMsg4Action(struct rt_rtmp_adapter *pAd, | ||
875 | struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem) | ||
876 | { | ||
877 | struct rt_eapol_packet * pMsg4; | ||
878 | struct rt_header_802_11 * pHeader; | ||
879 | u32 MsgLen; | ||
880 | BOOLEAN Cancelled; | ||
881 | u8 group_cipher = Ndis802_11WEPDisabled; | ||
882 | |||
883 | DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg4Action\n")); | ||
884 | |||
885 | do { | ||
886 | if ((!pEntry) || (!pEntry->ValidAsCLI)) | ||
887 | break; | ||
888 | |||
889 | if (Elem->MsgLen < | ||
890 | (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + | ||
891 | sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2)) | ||
892 | break; | ||
893 | |||
894 | if (pEntry->WpaState < AS_PTKINIT_NEGOTIATING) | ||
895 | break; | ||
896 | |||
897 | /* pointer to 802.11 header */ | ||
898 | pHeader = (struct rt_header_802_11 *) Elem->Msg; | ||
899 | |||
900 | /* skip 802.11_header(24-byte) and LLC_header(8) */ | ||
901 | pMsg4 = | ||
902 | (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; | ||
903 | MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; | ||
904 | |||
905 | /* Sanity Check peer Pairwise message 4 - Replay Counter, MIC */ | ||
906 | if (PeerWpaMessageSanity | ||
907 | (pAd, pMsg4, MsgLen, EAPOL_PAIR_MSG_4, pEntry) == FALSE) | ||
908 | break; | ||
909 | |||
910 | /* 3. uses the MLME.SETKEYS.request to configure PTK into MAC */ | ||
911 | NdisZeroMemory(&pEntry->PairwiseKey, sizeof(struct rt_cipher_key)); | ||
912 | |||
913 | /* reset IVEIV in Asic */ | ||
914 | AsicUpdateWCIDIVEIV(pAd, pEntry->Aid, 1, 0); | ||
915 | |||
916 | pEntry->PairwiseKey.KeyLen = LEN_TKIP_EK; | ||
917 | NdisMoveMemory(pEntry->PairwiseKey.Key, &pEntry->PTK[32], | ||
918 | LEN_TKIP_EK); | ||
919 | NdisMoveMemory(pEntry->PairwiseKey.RxMic, | ||
920 | &pEntry->PTK[TKIP_AP_RXMICK_OFFSET], | ||
921 | LEN_TKIP_RXMICK); | ||
922 | NdisMoveMemory(pEntry->PairwiseKey.TxMic, | ||
923 | &pEntry->PTK[TKIP_AP_TXMICK_OFFSET], | ||
924 | LEN_TKIP_TXMICK); | ||
925 | |||
926 | /* Set pairwise key to Asic */ | ||
927 | { | ||
928 | pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; | ||
929 | if (pEntry->WepStatus == Ndis802_11Encryption2Enabled) | ||
930 | pEntry->PairwiseKey.CipherAlg = CIPHER_TKIP; | ||
931 | else if (pEntry->WepStatus == | ||
932 | Ndis802_11Encryption3Enabled) | ||
933 | pEntry->PairwiseKey.CipherAlg = CIPHER_AES; | ||
934 | |||
935 | /* Add Pair-wise key to Asic */ | ||
936 | AsicAddPairwiseKeyEntry(pAd, | ||
937 | pEntry->Addr, | ||
938 | (u8)pEntry->Aid, | ||
939 | &pEntry->PairwiseKey); | ||
940 | |||
941 | /* update WCID attribute table and IVEIV table for this entry */ | ||
942 | RTMPAddWcidAttributeEntry(pAd, | ||
943 | pEntry->apidx, | ||
944 | 0, | ||
945 | pEntry->PairwiseKey.CipherAlg, | ||
946 | pEntry); | ||
947 | } | ||
948 | |||
949 | /* 4. upgrade state */ | ||
950 | pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; | ||
951 | pEntry->WpaState = AS_PTKINITDONE; | ||
952 | pEntry->PortSecured = WPA_802_1X_PORT_SECURED; | ||
953 | |||
954 | if (pEntry->AuthMode == Ndis802_11AuthModeWPA2 || | ||
955 | pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) { | ||
956 | pEntry->GTKState = REKEY_ESTABLISHED; | ||
957 | RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); | ||
958 | |||
959 | /* send wireless event - for set key done WPA2 */ | ||
960 | if (pAd->CommonCfg.bWirelessEvent) | ||
961 | RTMPSendWirelessEvent(pAd, | ||
962 | IW_SET_KEY_DONE_WPA2_EVENT_FLAG, | ||
963 | pEntry->Addr, | ||
964 | pEntry->apidx, 0); | ||
965 | |||
966 | DBGPRINT(RT_DEBUG_OFF, | ||
967 | ("AP SETKEYS DONE - WPA2, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n", | ||
968 | pEntry->AuthMode, | ||
969 | GetAuthMode(pEntry->AuthMode), | ||
970 | pEntry->WepStatus, | ||
971 | GetEncryptType(pEntry->WepStatus), | ||
972 | group_cipher, GetEncryptType(group_cipher))); | ||
973 | } else { | ||
974 | /* 5. init Group 2-way handshake if necessary. */ | ||
975 | WPAStart2WayGroupHS(pAd, pEntry); | ||
976 | |||
977 | pEntry->ReTryCounter = GROUP_MSG1_RETRY_TIMER_CTR; | ||
978 | RTMPModTimer(&pEntry->RetryTimer, | ||
979 | PEER_MSG3_RETRY_EXEC_INTV); | ||
980 | } | ||
981 | } while (FALSE); | ||
982 | |||
983 | } | ||
984 | |||
985 | /* | ||
986 | ========================================================================== | ||
987 | Description: | ||
988 | This is a function to send the first packet of 2-way groupkey handshake | ||
989 | Return: | ||
990 | |||
991 | ========================================================================== | ||
992 | */ | ||
993 | void WPAStart2WayGroupHS(struct rt_rtmp_adapter *pAd, struct rt_mac_table_entry *pEntry) | ||
994 | { | ||
995 | u8 Header802_3[14]; | ||
996 | u8 TxTsc[6]; | ||
997 | struct rt_eapol_packet EAPOLPKT; | ||
998 | u8 group_cipher = Ndis802_11WEPDisabled; | ||
999 | u8 default_key = 0; | ||
1000 | u8 *gnonce_ptr = NULL; | ||
1001 | u8 *gtk_ptr = NULL; | ||
1002 | u8 *pBssid = NULL; | ||
1003 | |||
1004 | DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart2WayGroupHS\n")); | ||
1005 | |||
1006 | if ((!pEntry) || (!pEntry->ValidAsCLI)) | ||
1007 | return; | ||
1008 | |||
1009 | do { | ||
1010 | /* Increment replay counter by 1 */ | ||
1011 | ADD_ONE_To_64BIT_VAR(pEntry->R_Counter); | ||
1012 | |||
1013 | /* Construct EAPoL message - Group Msg 1 */ | ||
1014 | NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet)); | ||
1015 | ConstructEapolMsg(pEntry, | ||
1016 | group_cipher, | ||
1017 | EAPOL_GROUP_MSG_1, | ||
1018 | default_key, | ||
1019 | (u8 *) gnonce_ptr, | ||
1020 | TxTsc, (u8 *) gtk_ptr, NULL, 0, &EAPOLPKT); | ||
1021 | |||
1022 | /* Make outgoing frame */ | ||
1023 | MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL); | ||
1024 | RTMPToWirelessSta(pAd, pEntry, | ||
1025 | Header802_3, LENGTH_802_3, | ||
1026 | (u8 *)& EAPOLPKT, | ||
1027 | CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, | ||
1028 | FALSE); | ||
1029 | |||
1030 | } while (FALSE); | ||
1031 | |||
1032 | DBGPRINT(RT_DEBUG_TRACE, | ||
1033 | ("<=== WPAStart2WayGroupHS : send out Group Message 1 \n")); | ||
1034 | |||
1035 | return; | ||
1036 | } | ||
1037 | |||
1038 | /* | ||
1039 | ======================================================================== | ||
1040 | |||
1041 | Routine Description: | ||
1042 | Process Group key 2-way handshaking | ||
1043 | |||
1044 | Arguments: | ||
1045 | pAd Pointer to our adapter | ||
1046 | Elem Message body | ||
1047 | |||
1048 | Return Value: | ||
1049 | None | ||
1050 | |||
1051 | Note: | ||
1052 | |||
1053 | ======================================================================== | ||
1054 | */ | ||
1055 | void PeerGroupMsg1Action(struct rt_rtmp_adapter *pAd, | ||
1056 | struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem) | ||
1057 | { | ||
1058 | u8 Header802_3[14]; | ||
1059 | struct rt_eapol_packet EAPOLPKT; | ||
1060 | struct rt_eapol_packet * pGroup; | ||
1061 | u32 MsgLen; | ||
1062 | BOOLEAN Cancelled; | ||
1063 | u8 default_key = 0; | ||
1064 | u8 group_cipher = Ndis802_11WEPDisabled; | ||
1065 | u8 *pCurrentAddr = NULL; | ||
1066 | |||
1067 | DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg1Action \n")); | ||
1068 | |||
1069 | if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli))) | ||
1070 | return; | ||
1071 | |||
1072 | { | ||
1073 | pCurrentAddr = pAd->CurrentAddress; | ||
1074 | group_cipher = pAd->StaCfg.GroupCipher; | ||
1075 | default_key = pAd->StaCfg.DefaultKeyId; | ||
1076 | } | ||
1077 | |||
1078 | /* Process Group Message 1 frame. skip 802.11 header(24) & LLC_SNAP header(8) */ | ||
1079 | pGroup = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; | ||
1080 | MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H; | ||
1081 | |||
1082 | /* Sanity Check peer group message 1 - Replay Counter, MIC, RSNIE */ | ||
1083 | if (PeerWpaMessageSanity(pAd, pGroup, MsgLen, EAPOL_GROUP_MSG_1, pEntry) | ||
1084 | == FALSE) | ||
1085 | return; | ||
1086 | |||
1087 | /* delete retry timer */ | ||
1088 | RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); | ||
1089 | |||
1090 | /* Save Replay counter, it will use to construct message 2 */ | ||
1091 | NdisMoveMemory(pEntry->R_Counter, pGroup->KeyDesc.ReplayCounter, | ||
1092 | LEN_KEY_DESC_REPLAY); | ||
1093 | |||
1094 | /* Construct EAPoL message - Group Msg 2 */ | ||
1095 | NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet)); | ||
1096 | ConstructEapolMsg(pEntry, group_cipher, EAPOL_GROUP_MSG_2, default_key, NULL, /* Nonce not used */ | ||
1097 | NULL, /* TxRSC not used */ | ||
1098 | NULL, /* GTK not used */ | ||
1099 | NULL, /* RSN IE not used */ | ||
1100 | 0, &EAPOLPKT); | ||
1101 | |||
1102 | /* open 802.1x port control and privacy filter */ | ||
1103 | pEntry->PortSecured = WPA_802_1X_PORT_SECURED; | ||
1104 | pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; | ||
1105 | |||
1106 | STA_PORT_SECURED(pAd); | ||
1107 | /* Indicate Connected for GUI */ | ||
1108 | pAd->IndicateMediaState = NdisMediaStateConnected; | ||
1109 | |||
1110 | DBGPRINT(RT_DEBUG_TRACE, | ||
1111 | ("PeerGroupMsg1Action: AuthMode(%s) PairwiseCipher(%s) GroupCipher(%s) \n", | ||
1112 | GetAuthMode(pEntry->AuthMode), | ||
1113 | GetEncryptType(pEntry->WepStatus), | ||
1114 | GetEncryptType(group_cipher))); | ||
1115 | |||
1116 | /* init header and Fill Packet and send Msg 2 to authenticator */ | ||
1117 | MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL); | ||
1118 | RTMPToWirelessSta(pAd, pEntry, | ||
1119 | Header802_3, sizeof(Header802_3), | ||
1120 | (u8 *)& EAPOLPKT, | ||
1121 | CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, FALSE); | ||
1122 | |||
1123 | DBGPRINT(RT_DEBUG_TRACE, | ||
1124 | ("<=== PeerGroupMsg1Action: sned group message 2\n")); | ||
1125 | } | ||
1126 | |||
1127 | /* | ||
1128 | ========================================================================== | ||
1129 | Description: | ||
1130 | When receiving the last packet of 2-way groupkey handshake. | ||
1131 | Return: | ||
1132 | ========================================================================== | ||
1133 | */ | ||
1134 | void PeerGroupMsg2Action(struct rt_rtmp_adapter *pAd, | ||
1135 | struct rt_mac_table_entry *pEntry, | ||
1136 | void * Msg, u32 MsgLen) | ||
1137 | { | ||
1138 | u32 Len; | ||
1139 | u8 *pData; | ||
1140 | BOOLEAN Cancelled; | ||
1141 | struct rt_eapol_packet * pMsg2; | ||
1142 | u8 group_cipher = Ndis802_11WEPDisabled; | ||
1143 | |||
1144 | DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg2Action \n")); | ||
1145 | |||
1146 | do { | ||
1147 | if ((!pEntry) || (!pEntry->ValidAsCLI)) | ||
1148 | break; | ||
1149 | |||
1150 | if (MsgLen < | ||
1151 | (LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(struct rt_key_descripter) - | ||
1152 | MAX_LEN_OF_RSNIE - 2)) | ||
1153 | break; | ||
1154 | |||
1155 | if (pEntry->WpaState != AS_PTKINITDONE) | ||
1156 | break; | ||
1157 | |||
1158 | pData = (u8 *)Msg; | ||
1159 | pMsg2 = (struct rt_eapol_packet *) (pData + LENGTH_802_1_H); | ||
1160 | Len = MsgLen - LENGTH_802_1_H; | ||
1161 | |||
1162 | /* Sanity Check peer group message 2 - Replay Counter, MIC */ | ||
1163 | if (PeerWpaMessageSanity | ||
1164 | (pAd, pMsg2, Len, EAPOL_GROUP_MSG_2, pEntry) == FALSE) | ||
1165 | break; | ||
1166 | |||
1167 | /* 3. upgrade state */ | ||
1168 | |||
1169 | RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); | ||
1170 | pEntry->GTKState = REKEY_ESTABLISHED; | ||
1171 | |||
1172 | if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) | ||
1173 | || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) { | ||
1174 | /* send wireless event - for set key done WPA2 */ | ||
1175 | if (pAd->CommonCfg.bWirelessEvent) | ||
1176 | RTMPSendWirelessEvent(pAd, | ||
1177 | IW_SET_KEY_DONE_WPA2_EVENT_FLAG, | ||
1178 | pEntry->Addr, | ||
1179 | pEntry->apidx, 0); | ||
1180 | |||
1181 | DBGPRINT(RT_DEBUG_OFF, | ||
1182 | ("AP SETKEYS DONE - WPA2, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n", | ||
1183 | pEntry->AuthMode, | ||
1184 | GetAuthMode(pEntry->AuthMode), | ||
1185 | pEntry->WepStatus, | ||
1186 | GetEncryptType(pEntry->WepStatus), | ||
1187 | group_cipher, GetEncryptType(group_cipher))); | ||
1188 | } else { | ||
1189 | /* send wireless event - for set key done WPA */ | ||
1190 | if (pAd->CommonCfg.bWirelessEvent) | ||
1191 | RTMPSendWirelessEvent(pAd, | ||
1192 | IW_SET_KEY_DONE_WPA1_EVENT_FLAG, | ||
1193 | pEntry->Addr, | ||
1194 | pEntry->apidx, 0); | ||
1195 | |||
1196 | DBGPRINT(RT_DEBUG_OFF, | ||
1197 | ("AP SETKEYS DONE - WPA1, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n", | ||
1198 | pEntry->AuthMode, | ||
1199 | GetAuthMode(pEntry->AuthMode), | ||
1200 | pEntry->WepStatus, | ||
1201 | GetEncryptType(pEntry->WepStatus), | ||
1202 | group_cipher, GetEncryptType(group_cipher))); | ||
1203 | } | ||
1204 | } while (FALSE); | ||
1205 | } | ||
1206 | |||
1207 | /* | ||
1208 | ======================================================================== | ||
1209 | |||
1210 | Routine Description: | ||
1211 | Classify WPA EAP message type | ||
1212 | |||
1213 | Arguments: | ||
1214 | EAPType Value of EAP message type | ||
1215 | MsgType Internal Message definition for MLME state machine | ||
1216 | |||
1217 | Return Value: | ||
1218 | TRUE Found appropriate message type | ||
1219 | FALSE No appropriate message type | ||
1220 | |||
1221 | IRQL = DISPATCH_LEVEL | ||
1222 | |||
1223 | Note: | ||
1224 | All these constants are defined in wpa.h | ||
1225 | For supplicant, there is only EAPOL Key message available | ||
1226 | |||
1227 | ======================================================================== | ||
1228 | */ | ||
1229 | BOOLEAN WpaMsgTypeSubst(u8 EAPType, int * MsgType) | ||
1230 | { | ||
1231 | switch (EAPType) { | ||
1232 | case EAPPacket: | ||
1233 | *MsgType = MT2_EAPPacket; | ||
1234 | break; | ||
1235 | case EAPOLStart: | ||
1236 | *MsgType = MT2_EAPOLStart; | ||
1237 | break; | ||
1238 | case EAPOLLogoff: | ||
1239 | *MsgType = MT2_EAPOLLogoff; | ||
1240 | break; | ||
1241 | case EAPOLKey: | ||
1242 | *MsgType = MT2_EAPOLKey; | ||
1243 | break; | ||
1244 | case EAPOLASFAlert: | ||
1245 | *MsgType = MT2_EAPOLASFAlert; | ||
1246 | break; | ||
1247 | default: | ||
1248 | return FALSE; | ||
1249 | } | ||
1250 | return TRUE; | ||
1251 | } | ||
1252 | |||
1253 | /* | ||
1254 | ======================================================================== | ||
1255 | |||
1256 | Routine Description: | ||
1257 | The pseudo-random function(PRF) that hashes various inputs to | ||
1258 | derive a pseudo-random value. To add liveness to the pseudo-random | ||
1259 | value, a nonce should be one of the inputs. | ||
1260 | |||
1261 | It is used to generate PTK, GTK or some specific random value. | ||
1262 | |||
1263 | Arguments: | ||
1264 | u8 *key, - the key material for HMAC_SHA1 use | ||
1265 | int key_len - the length of key | ||
1266 | u8 *prefix - a prefix label | ||
1267 | int prefix_len - the length of the label | ||
1268 | u8 *data - a specific data with variable length | ||
1269 | int data_len - the length of a specific data | ||
1270 | int len - the output length | ||
1271 | |||
1272 | Return Value: | ||
1273 | u8 *output - the calculated result | ||
1274 | |||
1275 | Note: | ||
1276 | 802.11i-2004 Annex H.3 | ||
1277 | |||
1278 | ======================================================================== | ||
1279 | */ | ||
1280 | void PRF(u8 * key, | ||
1281 | int key_len, | ||
1282 | u8 * prefix, | ||
1283 | int prefix_len, | ||
1284 | u8 * data, int data_len, u8 * output, int len) | ||
1285 | { | ||
1286 | int i; | ||
1287 | u8 *input; | ||
1288 | int currentindex = 0; | ||
1289 | int total_len; | ||
1290 | |||
1291 | /* Allocate memory for input */ | ||
1292 | os_alloc_mem(NULL, (u8 **) & input, 1024); | ||
1293 | |||
1294 | if (input == NULL) { | ||
1295 | DBGPRINT(RT_DEBUG_ERROR, ("PRF: no memory!\n")); | ||
1296 | return; | ||
1297 | } | ||
1298 | /* Generate concatenation input */ | ||
1299 | NdisMoveMemory(input, prefix, prefix_len); | ||
1300 | |||
1301 | /* Concatenate a single octet containing 0 */ | ||
1302 | input[prefix_len] = 0; | ||
1303 | |||
1304 | /* Concatenate specific data */ | ||
1305 | NdisMoveMemory(&input[prefix_len + 1], data, data_len); | ||
1306 | total_len = prefix_len + 1 + data_len; | ||
1307 | |||
1308 | /* Concatenate a single octet containing 0 */ | ||
1309 | /* This octet shall be update later */ | ||
1310 | input[total_len] = 0; | ||
1311 | total_len++; | ||
1312 | |||
1313 | /* Iterate to calculate the result by hmac-sha-1 */ | ||
1314 | /* Then concatenate to last result */ | ||
1315 | for (i = 0; i < (len + 19) / 20; i++) { | ||
1316 | HMAC_SHA1(key, key_len, input, total_len, &output[currentindex], | ||
1317 | SHA1_DIGEST_SIZE); | ||
1318 | currentindex += 20; | ||
1319 | |||
1320 | /* update the last octet */ | ||
1321 | input[total_len - 1]++; | ||
1322 | } | ||
1323 | os_free_mem(NULL, input); | ||
1324 | } | ||
1325 | |||
1326 | /* | ||
1327 | * F(P, S, c, i) = U1 xor U2 xor ... Uc | ||
1328 | * U1 = PRF(P, S || Int(i)) | ||
1329 | * U2 = PRF(P, U1) | ||
1330 | * Uc = PRF(P, Uc-1) | ||
1331 | */ | ||
1332 | |||
1333 | static void F(char *password, unsigned char *ssid, int ssidlength, | ||
1334 | int iterations, int count, unsigned char *output) | ||
1335 | { | ||
1336 | unsigned char digest[36], digest1[SHA1_DIGEST_SIZE]; | ||
1337 | int i, j; | ||
1338 | |||
1339 | /* U1 = PRF(P, S || int(i)) */ | ||
1340 | memcpy(digest, ssid, ssidlength); | ||
1341 | digest[ssidlength] = (unsigned char)((count >> 24) & 0xff); | ||
1342 | digest[ssidlength + 1] = (unsigned char)((count >> 16) & 0xff); | ||
1343 | digest[ssidlength + 2] = (unsigned char)((count >> 8) & 0xff); | ||
1344 | digest[ssidlength + 3] = (unsigned char)(count & 0xff); | ||
1345 | HMAC_SHA1((unsigned char *)password, (int)strlen(password), digest, ssidlength + 4, digest1, SHA1_DIGEST_SIZE); /* for WPA update */ | ||
1346 | |||
1347 | /* output = U1 */ | ||
1348 | memcpy(output, digest1, SHA1_DIGEST_SIZE); | ||
1349 | |||
1350 | for (i = 1; i < iterations; i++) { | ||
1351 | /* Un = PRF(P, Un-1) */ | ||
1352 | HMAC_SHA1((unsigned char *)password, (int)strlen(password), digest1, SHA1_DIGEST_SIZE, digest, SHA1_DIGEST_SIZE); /* for WPA update */ | ||
1353 | memcpy(digest1, digest, SHA1_DIGEST_SIZE); | ||
1354 | |||
1355 | /* output = output xor Un */ | ||
1356 | for (j = 0; j < SHA1_DIGEST_SIZE; j++) { | ||
1357 | output[j] ^= digest[j]; | ||
1358 | } | ||
1359 | } | ||
1360 | } | ||
1361 | |||
1362 | /* | ||
1363 | * password - ascii string up to 63 characters in length | ||
1364 | * ssid - octet string up to 32 octets | ||
1365 | * ssidlength - length of ssid in octets | ||
1366 | * output must be 40 octets in length and outputs 256 bits of key | ||
1367 | */ | ||
1368 | int PasswordHash(char *password, u8 *ssid, int ssidlength, u8 *output) | ||
1369 | { | ||
1370 | if ((strlen(password) > 63) || (ssidlength > 32)) | ||
1371 | return 0; | ||
1372 | |||
1373 | F(password, ssid, ssidlength, 4096, 1, output); | ||
1374 | F(password, ssid, ssidlength, 4096, 2, &output[SHA1_DIGEST_SIZE]); | ||
1375 | return 1; | ||
1376 | } | ||
1377 | |||
1378 | /* | ||
1379 | ======================================================================== | ||
1380 | |||
1381 | Routine Description: | ||
1382 | It utilizes PRF-384 or PRF-512 to derive session-specific keys from a PMK. | ||
1383 | It shall be called by 4-way handshake processing. | ||
1384 | |||
1385 | Arguments: | ||
1386 | pAd - pointer to our pAdapter context | ||
1387 | PMK - pointer to PMK | ||
1388 | ANonce - pointer to ANonce | ||
1389 | AA - pointer to Authenticator Address | ||
1390 | SNonce - pointer to SNonce | ||
1391 | SA - pointer to Supplicant Address | ||
1392 | len - indicate the length of PTK (octet) | ||
1393 | |||
1394 | Return Value: | ||
1395 | Output pointer to the PTK | ||
1396 | |||
1397 | Note: | ||
1398 | Refer to IEEE 802.11i-2004 8.5.1.2 | ||
1399 | |||
1400 | ======================================================================== | ||
1401 | */ | ||
1402 | void WpaDerivePTK(struct rt_rtmp_adapter *pAd, | ||
1403 | u8 * PMK, | ||
1404 | u8 * ANonce, | ||
1405 | u8 * AA, | ||
1406 | u8 * SNonce, | ||
1407 | u8 * SA, u8 * output, u32 len) | ||
1408 | { | ||
1409 | u8 concatenation[76]; | ||
1410 | u32 CurrPos = 0; | ||
1411 | u8 temp[32]; | ||
1412 | u8 Prefix[] = | ||
1413 | { 'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ', | ||
1414 | 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n' | ||
1415 | }; | ||
1416 | |||
1417 | /* initiate the concatenation input */ | ||
1418 | NdisZeroMemory(temp, sizeof(temp)); | ||
1419 | NdisZeroMemory(concatenation, 76); | ||
1420 | |||
1421 | /* Get smaller address */ | ||
1422 | if (RTMPCompareMemory(SA, AA, 6) == 1) | ||
1423 | NdisMoveMemory(concatenation, AA, 6); | ||
1424 | else | ||
1425 | NdisMoveMemory(concatenation, SA, 6); | ||
1426 | CurrPos += 6; | ||
1427 | |||
1428 | /* Get larger address */ | ||
1429 | if (RTMPCompareMemory(SA, AA, 6) == 1) | ||
1430 | NdisMoveMemory(&concatenation[CurrPos], SA, 6); | ||
1431 | else | ||
1432 | NdisMoveMemory(&concatenation[CurrPos], AA, 6); | ||
1433 | |||
1434 | /* store the larger mac address for backward compatible of */ | ||
1435 | /* ralink proprietary STA-key issue */ | ||
1436 | NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN); | ||
1437 | CurrPos += 6; | ||
1438 | |||
1439 | /* Get smaller Nonce */ | ||
1440 | if (RTMPCompareMemory(ANonce, SNonce, 32) == 0) | ||
1441 | NdisMoveMemory(&concatenation[CurrPos], temp, 32); /* patch for ralink proprietary STA-key issue */ | ||
1442 | else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1) | ||
1443 | NdisMoveMemory(&concatenation[CurrPos], SNonce, 32); | ||
1444 | else | ||
1445 | NdisMoveMemory(&concatenation[CurrPos], ANonce, 32); | ||
1446 | CurrPos += 32; | ||
1447 | |||
1448 | /* Get larger Nonce */ | ||
1449 | if (RTMPCompareMemory(ANonce, SNonce, 32) == 0) | ||
1450 | NdisMoveMemory(&concatenation[CurrPos], temp, 32); /* patch for ralink proprietary STA-key issue */ | ||
1451 | else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1) | ||
1452 | NdisMoveMemory(&concatenation[CurrPos], ANonce, 32); | ||
1453 | else | ||
1454 | NdisMoveMemory(&concatenation[CurrPos], SNonce, 32); | ||
1455 | CurrPos += 32; | ||
1456 | |||
1457 | hex_dump("concatenation=", concatenation, 76); | ||
1458 | |||
1459 | /* Use PRF to generate PTK */ | ||
1460 | PRF(PMK, LEN_MASTER_KEY, Prefix, 22, concatenation, 76, output, len); | ||
1461 | |||
1462 | } | ||
1463 | |||
1464 | /* | ||
1465 | ======================================================================== | ||
1466 | |||
1467 | Routine Description: | ||
1468 | Generate random number by software. | ||
1469 | |||
1470 | Arguments: | ||
1471 | pAd - pointer to our pAdapter context | ||
1472 | macAddr - pointer to local MAC address | ||
1473 | |||
1474 | Return Value: | ||
1475 | |||
1476 | Note: | ||
1477 | 802.1ii-2004 Annex H.5 | ||
1478 | |||
1479 | ======================================================================== | ||
1480 | */ | ||
1481 | void GenRandom(struct rt_rtmp_adapter *pAd, u8 * macAddr, u8 * random) | ||
1482 | { | ||
1483 | int i, curr; | ||
1484 | u8 local[80], KeyCounter[32]; | ||
1485 | u8 result[80]; | ||
1486 | unsigned long CurrentTime; | ||
1487 | u8 prefix[] = | ||
1488 | { 'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r' }; | ||
1489 | |||
1490 | /* Zero the related information */ | ||
1491 | NdisZeroMemory(result, 80); | ||
1492 | NdisZeroMemory(local, 80); | ||
1493 | NdisZeroMemory(KeyCounter, 32); | ||
1494 | |||
1495 | for (i = 0; i < 32; i++) { | ||
1496 | /* copy the local MAC address */ | ||
1497 | COPY_MAC_ADDR(local, macAddr); | ||
1498 | curr = MAC_ADDR_LEN; | ||
1499 | |||
1500 | /* concatenate the current time */ | ||
1501 | NdisGetSystemUpTime(&CurrentTime); | ||
1502 | NdisMoveMemory(&local[curr], &CurrentTime, sizeof(CurrentTime)); | ||
1503 | curr += sizeof(CurrentTime); | ||
1504 | |||
1505 | /* concatenate the last result */ | ||
1506 | NdisMoveMemory(&local[curr], result, 32); | ||
1507 | curr += 32; | ||
1508 | |||
1509 | /* concatenate a variable */ | ||
1510 | NdisMoveMemory(&local[curr], &i, 2); | ||
1511 | curr += 2; | ||
1512 | |||
1513 | /* calculate the result */ | ||
1514 | PRF(KeyCounter, 32, prefix, 12, local, curr, result, 32); | ||
1515 | } | ||
1516 | |||
1517 | NdisMoveMemory(random, result, 32); | ||
1518 | } | ||
1519 | |||
1520 | /* | ||
1521 | ======================================================================== | ||
1522 | |||
1523 | Routine Description: | ||
1524 | Build cipher suite in RSN-IE. | ||
1525 | It only shall be called by RTMPMakeRSNIE. | ||
1526 | |||
1527 | Arguments: | ||
1528 | pAd - pointer to our pAdapter context | ||
1529 | ElementID - indicate the WPA1 or WPA2 | ||
1530 | WepStatus - indicate the encryption type | ||
1531 | bMixCipher - a boolean to indicate the pairwise cipher and group | ||
1532 | cipher are the same or not | ||
1533 | |||
1534 | Return Value: | ||
1535 | |||
1536 | Note: | ||
1537 | |||
1538 | ======================================================================== | ||
1539 | */ | ||
1540 | static void RTMPMakeRsnIeCipher(struct rt_rtmp_adapter *pAd, | ||
1541 | u8 ElementID, | ||
1542 | u32 WepStatus, | ||
1543 | IN BOOLEAN bMixCipher, | ||
1544 | u8 FlexibleCipher, | ||
1545 | u8 *pRsnIe, u8 * rsn_len) | ||
1546 | { | ||
1547 | u8 PairwiseCnt; | ||
1548 | |||
1549 | *rsn_len = 0; | ||
1550 | |||
1551 | /* decide WPA2 or WPA1 */ | ||
1552 | if (ElementID == Wpa2Ie) { | ||
1553 | struct rt_rsnie2 *pRsnie_cipher = (struct rt_rsnie2 *)pRsnIe; | ||
1554 | |||
1555 | /* Assign the verson as 1 */ | ||
1556 | pRsnie_cipher->version = 1; | ||
1557 | |||
1558 | switch (WepStatus) { | ||
1559 | /* TKIP mode */ | ||
1560 | case Ndis802_11Encryption2Enabled: | ||
1561 | NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); | ||
1562 | pRsnie_cipher->ucount = 1; | ||
1563 | NdisMoveMemory(pRsnie_cipher->ucast[0].oui, | ||
1564 | OUI_WPA2_TKIP, 4); | ||
1565 | *rsn_len = sizeof(struct rt_rsnie2); | ||
1566 | break; | ||
1567 | |||
1568 | /* AES mode */ | ||
1569 | case Ndis802_11Encryption3Enabled: | ||
1570 | if (bMixCipher) | ||
1571 | NdisMoveMemory(pRsnie_cipher->mcast, | ||
1572 | OUI_WPA2_TKIP, 4); | ||
1573 | else | ||
1574 | NdisMoveMemory(pRsnie_cipher->mcast, | ||
1575 | OUI_WPA2_CCMP, 4); | ||
1576 | pRsnie_cipher->ucount = 1; | ||
1577 | NdisMoveMemory(pRsnie_cipher->ucast[0].oui, | ||
1578 | OUI_WPA2_CCMP, 4); | ||
1579 | *rsn_len = sizeof(struct rt_rsnie2); | ||
1580 | break; | ||
1581 | |||
1582 | /* TKIP-AES mix mode */ | ||
1583 | case Ndis802_11Encryption4Enabled: | ||
1584 | NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); | ||
1585 | |||
1586 | PairwiseCnt = 1; | ||
1587 | /* Insert WPA2 TKIP as the first pairwise cipher */ | ||
1588 | if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher)) { | ||
1589 | NdisMoveMemory(pRsnie_cipher->ucast[0].oui, | ||
1590 | OUI_WPA2_TKIP, 4); | ||
1591 | /* Insert WPA2 AES as the secondary pairwise cipher */ | ||
1592 | if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher)) { | ||
1593 | NdisMoveMemory(pRsnie_cipher->ucast[0]. | ||
1594 | oui + 4, OUI_WPA2_CCMP, | ||
1595 | 4); | ||
1596 | PairwiseCnt = 2; | ||
1597 | } | ||
1598 | } else { | ||
1599 | /* Insert WPA2 AES as the first pairwise cipher */ | ||
1600 | NdisMoveMemory(pRsnie_cipher->ucast[0].oui, | ||
1601 | OUI_WPA2_CCMP, 4); | ||
1602 | } | ||
1603 | |||
1604 | pRsnie_cipher->ucount = PairwiseCnt; | ||
1605 | *rsn_len = sizeof(struct rt_rsnie2) + (4 * (PairwiseCnt - 1)); | ||
1606 | break; | ||
1607 | } | ||
1608 | |||
1609 | if ((pAd->OpMode == OPMODE_STA) && | ||
1610 | (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) && | ||
1611 | (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled)) { | ||
1612 | u32 GroupCipher = pAd->StaCfg.GroupCipher; | ||
1613 | switch (GroupCipher) { | ||
1614 | case Ndis802_11GroupWEP40Enabled: | ||
1615 | NdisMoveMemory(pRsnie_cipher->mcast, | ||
1616 | OUI_WPA2_WEP40, 4); | ||
1617 | break; | ||
1618 | case Ndis802_11GroupWEP104Enabled: | ||
1619 | NdisMoveMemory(pRsnie_cipher->mcast, | ||
1620 | OUI_WPA2_WEP104, 4); | ||
1621 | break; | ||
1622 | } | ||
1623 | } | ||
1624 | /* swap for big-endian platform */ | ||
1625 | pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version); | ||
1626 | pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount); | ||
1627 | } else { | ||
1628 | struct rt_rsnie *pRsnie_cipher = (struct rt_rsnie *)pRsnIe; | ||
1629 | |||
1630 | /* Assign OUI and version */ | ||
1631 | NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4); | ||
1632 | pRsnie_cipher->version = 1; | ||
1633 | |||
1634 | switch (WepStatus) { | ||
1635 | /* TKIP mode */ | ||
1636 | case Ndis802_11Encryption2Enabled: | ||
1637 | NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); | ||
1638 | pRsnie_cipher->ucount = 1; | ||
1639 | NdisMoveMemory(pRsnie_cipher->ucast[0].oui, | ||
1640 | OUI_WPA_TKIP, 4); | ||
1641 | *rsn_len = sizeof(struct rt_rsnie); | ||
1642 | break; | ||
1643 | |||
1644 | /* AES mode */ | ||
1645 | case Ndis802_11Encryption3Enabled: | ||
1646 | if (bMixCipher) | ||
1647 | NdisMoveMemory(pRsnie_cipher->mcast, | ||
1648 | OUI_WPA_TKIP, 4); | ||
1649 | else | ||
1650 | NdisMoveMemory(pRsnie_cipher->mcast, | ||
1651 | OUI_WPA_CCMP, 4); | ||
1652 | pRsnie_cipher->ucount = 1; | ||
1653 | NdisMoveMemory(pRsnie_cipher->ucast[0].oui, | ||
1654 | OUI_WPA_CCMP, 4); | ||
1655 | *rsn_len = sizeof(struct rt_rsnie); | ||
1656 | break; | ||
1657 | |||
1658 | /* TKIP-AES mix mode */ | ||
1659 | case Ndis802_11Encryption4Enabled: | ||
1660 | NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); | ||
1661 | |||
1662 | PairwiseCnt = 1; | ||
1663 | /* Insert WPA TKIP as the first pairwise cipher */ | ||
1664 | if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher)) { | ||
1665 | NdisMoveMemory(pRsnie_cipher->ucast[0].oui, | ||
1666 | OUI_WPA_TKIP, 4); | ||
1667 | /* Insert WPA AES as the secondary pairwise cipher */ | ||
1668 | if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher)) { | ||
1669 | NdisMoveMemory(pRsnie_cipher->ucast[0]. | ||
1670 | oui + 4, OUI_WPA_CCMP, | ||
1671 | 4); | ||
1672 | PairwiseCnt = 2; | ||
1673 | } | ||
1674 | } else { | ||
1675 | /* Insert WPA AES as the first pairwise cipher */ | ||
1676 | NdisMoveMemory(pRsnie_cipher->ucast[0].oui, | ||
1677 | OUI_WPA_CCMP, 4); | ||
1678 | } | ||
1679 | |||
1680 | pRsnie_cipher->ucount = PairwiseCnt; | ||
1681 | *rsn_len = sizeof(struct rt_rsnie) + (4 * (PairwiseCnt - 1)); | ||
1682 | break; | ||
1683 | } | ||
1684 | |||
1685 | if ((pAd->OpMode == OPMODE_STA) && | ||
1686 | (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) && | ||
1687 | (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled)) { | ||
1688 | u32 GroupCipher = pAd->StaCfg.GroupCipher; | ||
1689 | switch (GroupCipher) { | ||
1690 | case Ndis802_11GroupWEP40Enabled: | ||
1691 | NdisMoveMemory(pRsnie_cipher->mcast, | ||
1692 | OUI_WPA_WEP40, 4); | ||
1693 | break; | ||
1694 | case Ndis802_11GroupWEP104Enabled: | ||
1695 | NdisMoveMemory(pRsnie_cipher->mcast, | ||
1696 | OUI_WPA_WEP104, 4); | ||
1697 | break; | ||
1698 | } | ||
1699 | } | ||
1700 | /* swap for big-endian platform */ | ||
1701 | pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version); | ||
1702 | pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount); | ||
1703 | } | ||
1704 | } | ||
1705 | |||
1706 | /* | ||
1707 | ======================================================================== | ||
1708 | |||
1709 | Routine Description: | ||
1710 | Build AKM suite in RSN-IE. | ||
1711 | It only shall be called by RTMPMakeRSNIE. | ||
1712 | |||
1713 | Arguments: | ||
1714 | pAd - pointer to our pAdapter context | ||
1715 | ElementID - indicate the WPA1 or WPA2 | ||
1716 | AuthMode - indicate the authentication mode | ||
1717 | apidx - indicate the interface index | ||
1718 | |||
1719 | Return Value: | ||
1720 | |||
1721 | Note: | ||
1722 | |||
1723 | ======================================================================== | ||
1724 | */ | ||
1725 | static void RTMPMakeRsnIeAKM(struct rt_rtmp_adapter *pAd, | ||
1726 | u8 ElementID, | ||
1727 | u32 AuthMode, | ||
1728 | u8 apidx, | ||
1729 | u8 *pRsnIe, u8 * rsn_len) | ||
1730 | { | ||
1731 | struct rt_rsnie_auth *pRsnie_auth; | ||
1732 | u8 AkmCnt = 1; /* default as 1 */ | ||
1733 | |||
1734 | pRsnie_auth = (struct rt_rsnie_auth *) (pRsnIe + (*rsn_len)); | ||
1735 | |||
1736 | /* decide WPA2 or WPA1 */ | ||
1737 | if (ElementID == Wpa2Ie) { | ||
1738 | |||
1739 | switch (AuthMode) { | ||
1740 | case Ndis802_11AuthModeWPA2: | ||
1741 | case Ndis802_11AuthModeWPA1WPA2: | ||
1742 | NdisMoveMemory(pRsnie_auth->auth[0].oui, | ||
1743 | OUI_WPA2_8021X_AKM, 4); | ||
1744 | break; | ||
1745 | |||
1746 | case Ndis802_11AuthModeWPA2PSK: | ||
1747 | case Ndis802_11AuthModeWPA1PSKWPA2PSK: | ||
1748 | NdisMoveMemory(pRsnie_auth->auth[0].oui, | ||
1749 | OUI_WPA2_PSK_AKM, 4); | ||
1750 | break; | ||
1751 | default: | ||
1752 | AkmCnt = 0; | ||
1753 | break; | ||
1754 | |||
1755 | } | ||
1756 | } else { | ||
1757 | switch (AuthMode) { | ||
1758 | case Ndis802_11AuthModeWPA: | ||
1759 | case Ndis802_11AuthModeWPA1WPA2: | ||
1760 | NdisMoveMemory(pRsnie_auth->auth[0].oui, | ||
1761 | OUI_WPA_8021X_AKM, 4); | ||
1762 | break; | ||
1763 | |||
1764 | case Ndis802_11AuthModeWPAPSK: | ||
1765 | case Ndis802_11AuthModeWPA1PSKWPA2PSK: | ||
1766 | NdisMoveMemory(pRsnie_auth->auth[0].oui, | ||
1767 | OUI_WPA_PSK_AKM, 4); | ||
1768 | break; | ||
1769 | |||
1770 | case Ndis802_11AuthModeWPANone: | ||
1771 | NdisMoveMemory(pRsnie_auth->auth[0].oui, | ||
1772 | OUI_WPA_NONE_AKM, 4); | ||
1773 | break; | ||
1774 | default: | ||
1775 | AkmCnt = 0; | ||
1776 | break; | ||
1777 | } | ||
1778 | } | ||
1779 | |||
1780 | pRsnie_auth->acount = AkmCnt; | ||
1781 | pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount); | ||
1782 | |||
1783 | /* update current RSNIE length */ | ||
1784 | (*rsn_len) += (sizeof(struct rt_rsnie_auth) + (4 * (AkmCnt - 1))); | ||
1785 | |||
1786 | } | ||
1787 | |||
1788 | /* | ||
1789 | ======================================================================== | ||
1790 | |||
1791 | Routine Description: | ||
1792 | Build capability in RSN-IE. | ||
1793 | It only shall be called by RTMPMakeRSNIE. | ||
1794 | |||
1795 | Arguments: | ||
1796 | pAd - pointer to our pAdapter context | ||
1797 | ElementID - indicate the WPA1 or WPA2 | ||
1798 | apidx - indicate the interface index | ||
1799 | |||
1800 | Return Value: | ||
1801 | |||
1802 | Note: | ||
1803 | |||
1804 | ======================================================================== | ||
1805 | */ | ||
1806 | static void RTMPMakeRsnIeCap(struct rt_rtmp_adapter *pAd, | ||
1807 | u8 ElementID, | ||
1808 | u8 apidx, | ||
1809 | u8 *pRsnIe, u8 * rsn_len) | ||
1810 | { | ||
1811 | RSN_CAPABILITIES *pRSN_Cap; | ||
1812 | |||
1813 | /* it could be ignored in WPA1 mode */ | ||
1814 | if (ElementID == WpaIe) | ||
1815 | return; | ||
1816 | |||
1817 | pRSN_Cap = (RSN_CAPABILITIES *) (pRsnIe + (*rsn_len)); | ||
1818 | |||
1819 | pRSN_Cap->word = cpu2le16(pRSN_Cap->word); | ||
1820 | |||
1821 | (*rsn_len) += sizeof(RSN_CAPABILITIES); /* update current RSNIE length */ | ||
1822 | |||
1823 | } | ||
1824 | |||
1825 | /* | ||
1826 | ======================================================================== | ||
1827 | |||
1828 | Routine Description: | ||
1829 | Build RSN IE context. It is not included element-ID and length. | ||
1830 | |||
1831 | Arguments: | ||
1832 | pAd - pointer to our pAdapter context | ||
1833 | AuthMode - indicate the authentication mode | ||
1834 | WepStatus - indicate the encryption type | ||
1835 | apidx - indicate the interface index | ||
1836 | |||
1837 | Return Value: | ||
1838 | |||
1839 | Note: | ||
1840 | |||
1841 | ======================================================================== | ||
1842 | */ | ||
1843 | void RTMPMakeRSNIE(struct rt_rtmp_adapter *pAd, | ||
1844 | u32 AuthMode, u32 WepStatus, u8 apidx) | ||
1845 | { | ||
1846 | u8 *pRsnIe = NULL; /* primary RSNIE */ | ||
1847 | u8 *rsnielen_cur_p = 0; /* the length of the primary RSNIE */ | ||
1848 | u8 *rsnielen_ex_cur_p = 0; /* the length of the secondary RSNIE */ | ||
1849 | u8 PrimaryRsnie; | ||
1850 | BOOLEAN bMixCipher = FALSE; /* indicate the pairwise and group cipher are different */ | ||
1851 | u8 p_offset; | ||
1852 | WPA_MIX_PAIR_CIPHER FlexibleCipher = WPA_TKIPAES_WPA2_TKIPAES; /* it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode */ | ||
1853 | |||
1854 | rsnielen_cur_p = NULL; | ||
1855 | rsnielen_ex_cur_p = NULL; | ||
1856 | |||
1857 | { | ||
1858 | { | ||
1859 | if (pAd->StaCfg.WpaSupplicantUP != | ||
1860 | WPA_SUPPLICANT_DISABLE) { | ||
1861 | if (AuthMode < Ndis802_11AuthModeWPA) | ||
1862 | return; | ||
1863 | } else { | ||
1864 | /* Support WPAPSK or WPA2PSK in STA-Infra mode */ | ||
1865 | /* Support WPANone in STA-Adhoc mode */ | ||
1866 | if ((AuthMode != Ndis802_11AuthModeWPAPSK) && | ||
1867 | (AuthMode != Ndis802_11AuthModeWPA2PSK) && | ||
1868 | (AuthMode != Ndis802_11AuthModeWPANone) | ||
1869 | ) | ||
1870 | return; | ||
1871 | } | ||
1872 | |||
1873 | DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPMakeRSNIE(STA)\n")); | ||
1874 | |||
1875 | /* Zero RSNIE context */ | ||
1876 | pAd->StaCfg.RSNIE_Len = 0; | ||
1877 | NdisZeroMemory(pAd->StaCfg.RSN_IE, MAX_LEN_OF_RSNIE); | ||
1878 | |||
1879 | /* Pointer to RSNIE */ | ||
1880 | rsnielen_cur_p = &pAd->StaCfg.RSNIE_Len; | ||
1881 | pRsnIe = pAd->StaCfg.RSN_IE; | ||
1882 | |||
1883 | bMixCipher = pAd->StaCfg.bMixCipher; | ||
1884 | } | ||
1885 | } | ||
1886 | |||
1887 | /* indicate primary RSNIE as WPA or WPA2 */ | ||
1888 | if ((AuthMode == Ndis802_11AuthModeWPA) || | ||
1889 | (AuthMode == Ndis802_11AuthModeWPAPSK) || | ||
1890 | (AuthMode == Ndis802_11AuthModeWPANone) || | ||
1891 | (AuthMode == Ndis802_11AuthModeWPA1WPA2) || | ||
1892 | (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) | ||
1893 | PrimaryRsnie = WpaIe; | ||
1894 | else | ||
1895 | PrimaryRsnie = Wpa2Ie; | ||
1896 | |||
1897 | { | ||
1898 | /* Build the primary RSNIE */ | ||
1899 | /* 1. insert cipher suite */ | ||
1900 | RTMPMakeRsnIeCipher(pAd, PrimaryRsnie, WepStatus, bMixCipher, | ||
1901 | FlexibleCipher, pRsnIe, &p_offset); | ||
1902 | |||
1903 | /* 2. insert AKM */ | ||
1904 | RTMPMakeRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe, | ||
1905 | &p_offset); | ||
1906 | |||
1907 | /* 3. insert capability */ | ||
1908 | RTMPMakeRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset); | ||
1909 | } | ||
1910 | |||
1911 | /* 4. update the RSNIE length */ | ||
1912 | *rsnielen_cur_p = p_offset; | ||
1913 | |||
1914 | hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p)); | ||
1915 | |||
1916 | } | ||
1917 | |||
1918 | /* | ||
1919 | ========================================================================== | ||
1920 | Description: | ||
1921 | Check whether the received frame is EAP frame. | ||
1922 | |||
1923 | Arguments: | ||
1924 | pAd - pointer to our pAdapter context | ||
1925 | pEntry - pointer to active entry | ||
1926 | pData - the received frame | ||
1927 | DataByteCount - the received frame's length | ||
1928 | FromWhichBSSID - indicate the interface index | ||
1929 | |||
1930 | Return: | ||
1931 | TRUE - This frame is EAP frame | ||
1932 | FALSE - otherwise | ||
1933 | ========================================================================== | ||
1934 | */ | ||
1935 | BOOLEAN RTMPCheckWPAframe(struct rt_rtmp_adapter *pAd, | ||
1936 | struct rt_mac_table_entry *pEntry, | ||
1937 | u8 *pData, | ||
1938 | unsigned long DataByteCount, u8 FromWhichBSSID) | ||
1939 | { | ||
1940 | unsigned long Body_len; | ||
1941 | BOOLEAN Cancelled; | ||
1942 | |||
1943 | if (DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H)) | ||
1944 | return FALSE; | ||
1945 | |||
1946 | /* Skip LLC header */ | ||
1947 | if (NdisEqualMemory(SNAP_802_1H, pData, 6) || | ||
1948 | /* Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL */ | ||
1949 | NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6)) { | ||
1950 | pData += 6; | ||
1951 | } | ||
1952 | /* Skip 2-bytes EAPoL type */ | ||
1953 | if (NdisEqualMemory(EAPOL, pData, 2)) { | ||
1954 | pData += 2; | ||
1955 | } else | ||
1956 | return FALSE; | ||
1957 | |||
1958 | switch (*(pData + 1)) { | ||
1959 | case EAPPacket: | ||
1960 | Body_len = (*(pData + 2) << 8) | (*(pData + 3)); | ||
1961 | DBGPRINT(RT_DEBUG_TRACE, | ||
1962 | ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n", | ||
1963 | Body_len)); | ||
1964 | break; | ||
1965 | case EAPOLStart: | ||
1966 | DBGPRINT(RT_DEBUG_TRACE, | ||
1967 | ("Receive EAPOL-Start frame, TYPE = 1 \n")); | ||
1968 | if (pEntry->EnqueueEapolStartTimerRunning != | ||
1969 | EAPOL_START_DISABLE) { | ||
1970 | DBGPRINT(RT_DEBUG_TRACE, | ||
1971 | ("Cancel the EnqueueEapolStartTimerRunning \n")); | ||
1972 | RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, | ||
1973 | &Cancelled); | ||
1974 | pEntry->EnqueueEapolStartTimerRunning = | ||
1975 | EAPOL_START_DISABLE; | ||
1976 | } | ||
1977 | break; | ||
1978 | case EAPOLLogoff: | ||
1979 | DBGPRINT(RT_DEBUG_TRACE, | ||
1980 | ("Receive EAPOLLogoff frame, TYPE = 2 \n")); | ||
1981 | break; | ||
1982 | case EAPOLKey: | ||
1983 | Body_len = (*(pData + 2) << 8) | (*(pData + 3)); | ||
1984 | DBGPRINT(RT_DEBUG_TRACE, | ||
1985 | ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", | ||
1986 | Body_len)); | ||
1987 | break; | ||
1988 | case EAPOLASFAlert: | ||
1989 | DBGPRINT(RT_DEBUG_TRACE, | ||
1990 | ("Receive EAPOLASFAlert frame, TYPE = 4 \n")); | ||
1991 | break; | ||
1992 | default: | ||
1993 | return FALSE; | ||
1994 | |||
1995 | } | ||
1996 | return TRUE; | ||
1997 | } | ||
1998 | |||
1999 | /* | ||
2000 | ========================================================================== | ||
2001 | Description: | ||
2002 | Report the EAP message type | ||
2003 | |||
2004 | Arguments: | ||
2005 | msg - EAPOL_PAIR_MSG_1 | ||
2006 | EAPOL_PAIR_MSG_2 | ||
2007 | EAPOL_PAIR_MSG_3 | ||
2008 | EAPOL_PAIR_MSG_4 | ||
2009 | EAPOL_GROUP_MSG_1 | ||
2010 | EAPOL_GROUP_MSG_2 | ||
2011 | |||
2012 | Return: | ||
2013 | message type string | ||
2014 | |||
2015 | ========================================================================== | ||
2016 | */ | ||
2017 | char *GetEapolMsgType(char msg) | ||
2018 | { | ||
2019 | if (msg == EAPOL_PAIR_MSG_1) | ||
2020 | return "Pairwise Message 1"; | ||
2021 | else if (msg == EAPOL_PAIR_MSG_2) | ||
2022 | return "Pairwise Message 2"; | ||
2023 | else if (msg == EAPOL_PAIR_MSG_3) | ||
2024 | return "Pairwise Message 3"; | ||
2025 | else if (msg == EAPOL_PAIR_MSG_4) | ||
2026 | return "Pairwise Message 4"; | ||
2027 | else if (msg == EAPOL_GROUP_MSG_1) | ||
2028 | return "Group Message 1"; | ||
2029 | else if (msg == EAPOL_GROUP_MSG_2) | ||
2030 | return "Group Message 2"; | ||
2031 | else | ||
2032 | return "Invalid Message"; | ||
2033 | } | ||
2034 | |||
2035 | /* | ||
2036 | ======================================================================== | ||
2037 | |||
2038 | Routine Description: | ||
2039 | Check Sanity RSN IE of EAPoL message | ||
2040 | |||
2041 | Arguments: | ||
2042 | |||
2043 | Return Value: | ||
2044 | |||
2045 | ======================================================================== | ||
2046 | */ | ||
2047 | BOOLEAN RTMPCheckRSNIE(struct rt_rtmp_adapter *pAd, | ||
2048 | u8 *pData, | ||
2049 | u8 DataLen, | ||
2050 | struct rt_mac_table_entry *pEntry, u8 * Offset) | ||
2051 | { | ||
2052 | u8 *pVIE; | ||
2053 | u8 len; | ||
2054 | struct rt_eid * pEid; | ||
2055 | BOOLEAN result = FALSE; | ||
2056 | |||
2057 | pVIE = pData; | ||
2058 | len = DataLen; | ||
2059 | *Offset = 0; | ||
2060 | |||
2061 | while (len > sizeof(struct rt_rsnie2)) { | ||
2062 | pEid = (struct rt_eid *) pVIE; | ||
2063 | /* WPA RSN IE */ | ||
2064 | if ((pEid->Eid == IE_WPA) | ||
2065 | && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))) { | ||
2066 | if ((pEntry->AuthMode == Ndis802_11AuthModeWPA | ||
2067 | || pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) | ||
2068 | && | ||
2069 | (NdisEqualMemory | ||
2070 | (pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) | ||
2071 | && (pEntry->RSNIE_Len == (pEid->Len + 2))) { | ||
2072 | result = TRUE; | ||
2073 | } | ||
2074 | |||
2075 | *Offset += (pEid->Len + 2); | ||
2076 | } | ||
2077 | /* WPA2 RSN IE */ | ||
2078 | else if ((pEid->Eid == IE_RSN) | ||
2079 | && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))) { | ||
2080 | if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2 | ||
2081 | || pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) | ||
2082 | && (pEid->Eid == pEntry->RSN_IE[0]) | ||
2083 | && ((pEid->Len + 2) >= pEntry->RSNIE_Len) | ||
2084 | && | ||
2085 | (NdisEqualMemory | ||
2086 | (pEid->Octet, &pEntry->RSN_IE[2], | ||
2087 | pEntry->RSNIE_Len - 2))) { | ||
2088 | |||
2089 | result = TRUE; | ||
2090 | } | ||
2091 | |||
2092 | *Offset += (pEid->Len + 2); | ||
2093 | } else { | ||
2094 | break; | ||
2095 | } | ||
2096 | |||
2097 | pVIE += (pEid->Len + 2); | ||
2098 | len -= (pEid->Len + 2); | ||
2099 | } | ||
2100 | |||
2101 | return result; | ||
2102 | |||
2103 | } | ||
2104 | |||
2105 | /* | ||
2106 | ======================================================================== | ||
2107 | |||
2108 | Routine Description: | ||
2109 | Parse KEYDATA field. KEYDATA[] May contain 2 RSN IE and optionally GTK. | ||
2110 | GTK is encaptulated in KDE format at p.83 802.11i D10 | ||
2111 | |||
2112 | Arguments: | ||
2113 | |||
2114 | Return Value: | ||
2115 | |||
2116 | Note: | ||
2117 | 802.11i D10 | ||
2118 | |||
2119 | ======================================================================== | ||
2120 | */ | ||
2121 | BOOLEAN RTMPParseEapolKeyData(struct rt_rtmp_adapter *pAd, | ||
2122 | u8 *pKeyData, | ||
2123 | u8 KeyDataLen, | ||
2124 | u8 GroupKeyIndex, | ||
2125 | u8 MsgType, | ||
2126 | IN BOOLEAN bWPA2, struct rt_mac_table_entry *pEntry) | ||
2127 | { | ||
2128 | struct rt_kde_encap * pKDE = NULL; | ||
2129 | u8 *pMyKeyData = pKeyData; | ||
2130 | u8 KeyDataLength = KeyDataLen; | ||
2131 | u8 GTKLEN = 0; | ||
2132 | u8 DefaultIdx = 0; | ||
2133 | u8 skip_offset; | ||
2134 | |||
2135 | /* Verify The RSN IE contained in pairewise_msg_2 && pairewise_msg_3 and skip it */ | ||
2136 | if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_3) { | ||
2137 | /* Check RSN IE whether it is WPA2/WPA2PSK */ | ||
2138 | if (!RTMPCheckRSNIE | ||
2139 | (pAd, pKeyData, KeyDataLen, pEntry, &skip_offset)) { | ||
2140 | /* send wireless event - for RSN IE different */ | ||
2141 | if (pAd->CommonCfg.bWirelessEvent) | ||
2142 | RTMPSendWirelessEvent(pAd, | ||
2143 | IW_RSNIE_DIFF_EVENT_FLAG, | ||
2144 | pEntry->Addr, | ||
2145 | pEntry->apidx, 0); | ||
2146 | |||
2147 | DBGPRINT(RT_DEBUG_ERROR, | ||
2148 | ("RSN_IE Different in msg %d of 4-way handshake!\n", | ||
2149 | MsgType)); | ||
2150 | hex_dump("Receive RSN_IE ", pKeyData, KeyDataLen); | ||
2151 | hex_dump("Desired RSN_IE ", pEntry->RSN_IE, | ||
2152 | pEntry->RSNIE_Len); | ||
2153 | |||
2154 | return FALSE; | ||
2155 | } else { | ||
2156 | if (bWPA2 && MsgType == EAPOL_PAIR_MSG_3) { | ||
2157 | WpaShowAllsuite(pMyKeyData, skip_offset); | ||
2158 | |||
2159 | /* skip RSN IE */ | ||
2160 | pMyKeyData += skip_offset; | ||
2161 | KeyDataLength -= skip_offset; | ||
2162 | DBGPRINT(RT_DEBUG_TRACE, | ||
2163 | ("RTMPParseEapolKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", | ||
2164 | skip_offset)); | ||
2165 | } else | ||
2166 | return TRUE; | ||
2167 | } | ||
2168 | } | ||
2169 | |||
2170 | DBGPRINT(RT_DEBUG_TRACE, | ||
2171 | ("RTMPParseEapolKeyData ==> KeyDataLength %d without RSN_IE \n", | ||
2172 | KeyDataLength)); | ||
2173 | /*hex_dump("remain data", pMyKeyData, KeyDataLength); */ | ||
2174 | |||
2175 | /* Parse EKD format in pairwise_msg_3_WPA2 && group_msg_1_WPA2 */ | ||
2176 | if (bWPA2 | ||
2177 | && (MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1)) { | ||
2178 | if (KeyDataLength >= 8) /* KDE format exclude GTK length */ | ||
2179 | { | ||
2180 | pKDE = (struct rt_kde_encap *) pMyKeyData; | ||
2181 | |||
2182 | DefaultIdx = pKDE->GTKEncap.Kid; | ||
2183 | |||
2184 | /* Sanity check - KED length */ | ||
2185 | if (KeyDataLength < (pKDE->Len + 2)) { | ||
2186 | DBGPRINT(RT_DEBUG_ERROR, | ||
2187 | ("ERROR: The len from KDE is too short \n")); | ||
2188 | return FALSE; | ||
2189 | } | ||
2190 | /* Get GTK length - refer to IEEE 802.11i-2004 p.82 */ | ||
2191 | GTKLEN = pKDE->Len - 6; | ||
2192 | if (GTKLEN < LEN_AES_KEY) { | ||
2193 | DBGPRINT(RT_DEBUG_ERROR, | ||
2194 | ("ERROR: GTK Key length is too short (%d) \n", | ||
2195 | GTKLEN)); | ||
2196 | return FALSE; | ||
2197 | } | ||
2198 | |||
2199 | } else { | ||
2200 | DBGPRINT(RT_DEBUG_ERROR, | ||
2201 | ("ERROR: KDE format length is too short \n")); | ||
2202 | return FALSE; | ||
2203 | } | ||
2204 | |||
2205 | DBGPRINT(RT_DEBUG_TRACE, | ||
2206 | ("GTK in KDE format ,DefaultKeyID=%d, KeyLen=%d \n", | ||
2207 | DefaultIdx, GTKLEN)); | ||
2208 | /* skip it */ | ||
2209 | pMyKeyData += 8; | ||
2210 | KeyDataLength -= 8; | ||
2211 | |||
2212 | } else if (!bWPA2 && MsgType == EAPOL_GROUP_MSG_1) { | ||
2213 | DefaultIdx = GroupKeyIndex; | ||
2214 | DBGPRINT(RT_DEBUG_TRACE, | ||
2215 | ("GTK DefaultKeyID=%d \n", DefaultIdx)); | ||
2216 | } | ||
2217 | /* Sanity check - shared key index must be 1 ~ 3 */ | ||
2218 | if (DefaultIdx < 1 || DefaultIdx > 3) { | ||
2219 | DBGPRINT(RT_DEBUG_ERROR, | ||
2220 | ("ERROR: GTK Key index(%d) is invalid in %s %s \n", | ||
2221 | DefaultIdx, ((bWPA2) ? "WPA2" : "WPA"), | ||
2222 | GetEapolMsgType(MsgType))); | ||
2223 | return FALSE; | ||
2224 | } | ||
2225 | |||
2226 | { | ||
2227 | struct rt_cipher_key *pSharedKey; | ||
2228 | |||
2229 | /* set key material, TxMic and RxMic */ | ||
2230 | NdisMoveMemory(pAd->StaCfg.GTK, pMyKeyData, 32); | ||
2231 | pAd->StaCfg.DefaultKeyId = DefaultIdx; | ||
2232 | |||
2233 | pSharedKey = &pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId]; | ||
2234 | |||
2235 | /* Prepare pair-wise key information into shared key table */ | ||
2236 | NdisZeroMemory(pSharedKey, sizeof(struct rt_cipher_key)); | ||
2237 | pSharedKey->KeyLen = LEN_TKIP_EK; | ||
2238 | NdisMoveMemory(pSharedKey->Key, pAd->StaCfg.GTK, LEN_TKIP_EK); | ||
2239 | NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.GTK[16], | ||
2240 | LEN_TKIP_RXMICK); | ||
2241 | NdisMoveMemory(pSharedKey->TxMic, &pAd->StaCfg.GTK[24], | ||
2242 | LEN_TKIP_TXMICK); | ||
2243 | |||
2244 | /* Update Shared Key CipherAlg */ | ||
2245 | pSharedKey->CipherAlg = CIPHER_NONE; | ||
2246 | if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled) | ||
2247 | pSharedKey->CipherAlg = CIPHER_TKIP; | ||
2248 | else if (pAd->StaCfg.GroupCipher == | ||
2249 | Ndis802_11Encryption3Enabled) | ||
2250 | pSharedKey->CipherAlg = CIPHER_AES; | ||
2251 | else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled) | ||
2252 | pSharedKey->CipherAlg = CIPHER_WEP64; | ||
2253 | else if (pAd->StaCfg.GroupCipher == | ||
2254 | Ndis802_11GroupWEP104Enabled) | ||
2255 | pSharedKey->CipherAlg = CIPHER_WEP128; | ||
2256 | |||
2257 | /* Update group key information to ASIC Shared Key Table */ | ||
2258 | AsicAddSharedKeyEntry(pAd, | ||
2259 | BSS0, | ||
2260 | pAd->StaCfg.DefaultKeyId, | ||
2261 | pSharedKey->CipherAlg, | ||
2262 | pSharedKey->Key, | ||
2263 | pSharedKey->TxMic, pSharedKey->RxMic); | ||
2264 | |||
2265 | /* Update ASIC WCID attribute table and IVEIV table */ | ||
2266 | RTMPAddWcidAttributeEntry(pAd, | ||
2267 | BSS0, | ||
2268 | pAd->StaCfg.DefaultKeyId, | ||
2269 | pSharedKey->CipherAlg, NULL); | ||
2270 | } | ||
2271 | |||
2272 | return TRUE; | ||
2273 | |||
2274 | } | ||
2275 | |||
2276 | /* | ||
2277 | ======================================================================== | ||
2278 | |||
2279 | Routine Description: | ||
2280 | Construct EAPoL message for WPA handshaking | ||
2281 | Its format is below, | ||
2282 | |||
2283 | +--------------------+ | ||
2284 | | Protocol Version | 1 octet | ||
2285 | +--------------------+ | ||
2286 | | Protocol Type | 1 octet | ||
2287 | +--------------------+ | ||
2288 | | Body Length | 2 octets | ||
2289 | +--------------------+ | ||
2290 | | Descriptor Type | 1 octet | ||
2291 | +--------------------+ | ||
2292 | | Key Information | 2 octets | ||
2293 | +--------------------+ | ||
2294 | | Key Length | 1 octet | ||
2295 | +--------------------+ | ||
2296 | | Key Repaly Counter | 8 octets | ||
2297 | +--------------------+ | ||
2298 | | Key Nonce | 32 octets | ||
2299 | +--------------------+ | ||
2300 | | Key IV | 16 octets | ||
2301 | +--------------------+ | ||
2302 | | Key RSC | 8 octets | ||
2303 | +--------------------+ | ||
2304 | | Key ID or Reserved | 8 octets | ||
2305 | +--------------------+ | ||
2306 | | Key MIC | 16 octets | ||
2307 | +--------------------+ | ||
2308 | | Key Data Length | 2 octets | ||
2309 | +--------------------+ | ||
2310 | | Key Data | n octets | ||
2311 | +--------------------+ | ||
2312 | |||
2313 | Arguments: | ||
2314 | pAd Pointer to our adapter | ||
2315 | |||
2316 | Return Value: | ||
2317 | None | ||
2318 | |||
2319 | Note: | ||
2320 | |||
2321 | ======================================================================== | ||
2322 | */ | ||
2323 | void ConstructEapolMsg(struct rt_mac_table_entry *pEntry, | ||
2324 | u8 GroupKeyWepStatus, | ||
2325 | u8 MsgType, | ||
2326 | u8 DefaultKeyIdx, | ||
2327 | u8 * KeyNonce, | ||
2328 | u8 * TxRSC, | ||
2329 | u8 * GTK, | ||
2330 | u8 * RSNIE, | ||
2331 | u8 RSNIE_Len, struct rt_eapol_packet * pMsg) | ||
2332 | { | ||
2333 | BOOLEAN bWPA2 = FALSE; | ||
2334 | u8 KeyDescVer; | ||
2335 | |||
2336 | /* Choose WPA2 or not */ | ||
2337 | if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || | ||
2338 | (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) | ||
2339 | bWPA2 = TRUE; | ||
2340 | |||
2341 | /* Init Packet and Fill header */ | ||
2342 | pMsg->ProVer = EAPOL_VER; | ||
2343 | pMsg->ProType = EAPOLKey; | ||
2344 | |||
2345 | /* Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field */ | ||
2346 | SET_u16_TO_ARRARY(pMsg->Body_Len, LEN_EAPOL_KEY_MSG); | ||
2347 | |||
2348 | /* Fill in EAPoL descriptor */ | ||
2349 | if (bWPA2) | ||
2350 | pMsg->KeyDesc.Type = WPA2_KEY_DESC; | ||
2351 | else | ||
2352 | pMsg->KeyDesc.Type = WPA1_KEY_DESC; | ||
2353 | |||
2354 | /* Key Descriptor Version (bits 0-2) specifies the key descriptor version type */ | ||
2355 | { | ||
2356 | /* Fill in Key information, refer to IEEE Std 802.11i-2004 page 78 */ | ||
2357 | /* When either the pairwise or the group cipher is AES, the DESC_TYPE_AES(2) shall be used. */ | ||
2358 | KeyDescVer = | ||
2359 | (((pEntry->WepStatus == Ndis802_11Encryption3Enabled) | ||
2360 | || (GroupKeyWepStatus == | ||
2361 | Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) | ||
2362 | : (DESC_TYPE_TKIP)); | ||
2363 | } | ||
2364 | |||
2365 | pMsg->KeyDesc.KeyInfo.KeyDescVer = KeyDescVer; | ||
2366 | |||
2367 | /* Specify Key Type as Group(0) or Pairwise(1) */ | ||
2368 | if (MsgType >= EAPOL_GROUP_MSG_1) | ||
2369 | pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY; | ||
2370 | else | ||
2371 | pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY; | ||
2372 | |||
2373 | /* Specify Key Index, only group_msg1_WPA1 */ | ||
2374 | if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1)) | ||
2375 | pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx; | ||
2376 | |||
2377 | if (MsgType == EAPOL_PAIR_MSG_3) | ||
2378 | pMsg->KeyDesc.KeyInfo.Install = 1; | ||
2379 | |||
2380 | if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3) | ||
2381 | || (MsgType == EAPOL_GROUP_MSG_1)) | ||
2382 | pMsg->KeyDesc.KeyInfo.KeyAck = 1; | ||
2383 | |||
2384 | if (MsgType != EAPOL_PAIR_MSG_1) | ||
2385 | pMsg->KeyDesc.KeyInfo.KeyMic = 1; | ||
2386 | |||
2387 | if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) || | ||
2388 | (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))) { | ||
2389 | pMsg->KeyDesc.KeyInfo.Secure = 1; | ||
2390 | } | ||
2391 | |||
2392 | if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) || | ||
2393 | (MsgType == EAPOL_GROUP_MSG_1))) { | ||
2394 | pMsg->KeyDesc.KeyInfo.EKD_DL = 1; | ||
2395 | } | ||
2396 | /* key Information element has done. */ | ||
2397 | *(u16 *) (&pMsg->KeyDesc.KeyInfo) = | ||
2398 | cpu2le16(*(u16 *) (&pMsg->KeyDesc.KeyInfo)); | ||
2399 | |||
2400 | /* Fill in Key Length */ | ||
2401 | { | ||
2402 | if (MsgType >= EAPOL_GROUP_MSG_1) { | ||
2403 | /* the length of group key cipher */ | ||
2404 | pMsg->KeyDesc.KeyLength[1] = | ||
2405 | ((GroupKeyWepStatus == | ||
2406 | Ndis802_11Encryption2Enabled) ? TKIP_GTK_LENGTH : | ||
2407 | LEN_AES_KEY); | ||
2408 | } else { | ||
2409 | /* the length of pairwise key cipher */ | ||
2410 | pMsg->KeyDesc.KeyLength[1] = | ||
2411 | ((pEntry->WepStatus == | ||
2412 | Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY : | ||
2413 | LEN_AES_KEY); | ||
2414 | } | ||
2415 | } | ||
2416 | |||
2417 | /* Fill in replay counter */ | ||
2418 | NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, | ||
2419 | LEN_KEY_DESC_REPLAY); | ||
2420 | |||
2421 | /* Fill Key Nonce field */ | ||
2422 | /* ANonce : pairwise_msg1 & pairwise_msg3 */ | ||
2423 | /* SNonce : pairwise_msg2 */ | ||
2424 | /* GNonce : group_msg1_wpa1 */ | ||
2425 | if ((MsgType <= EAPOL_PAIR_MSG_3) | ||
2426 | || ((!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)))) | ||
2427 | NdisMoveMemory(pMsg->KeyDesc.KeyNonce, KeyNonce, | ||
2428 | LEN_KEY_DESC_NONCE); | ||
2429 | |||
2430 | /* Fill key IV - WPA2 as 0, WPA1 as random */ | ||
2431 | if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)) { | ||
2432 | /* Suggest IV be random number plus some number, */ | ||
2433 | NdisMoveMemory(pMsg->KeyDesc.KeyIv, &KeyNonce[16], | ||
2434 | LEN_KEY_DESC_IV); | ||
2435 | pMsg->KeyDesc.KeyIv[15] += 2; | ||
2436 | } | ||
2437 | /* Fill Key RSC field */ | ||
2438 | /* It contains the RSC for the GTK being installed. */ | ||
2439 | if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) | ||
2440 | || (MsgType == EAPOL_GROUP_MSG_1)) { | ||
2441 | NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6); | ||
2442 | } | ||
2443 | /* Clear Key MIC field for MIC calculation later */ | ||
2444 | NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); | ||
2445 | |||
2446 | ConstructEapolKeyData(pEntry, | ||
2447 | GroupKeyWepStatus, | ||
2448 | KeyDescVer, | ||
2449 | MsgType, | ||
2450 | DefaultKeyIdx, GTK, RSNIE, RSNIE_Len, pMsg); | ||
2451 | |||
2452 | /* Calculate MIC and fill in KeyMic Field except Pairwise Msg 1. */ | ||
2453 | if (MsgType != EAPOL_PAIR_MSG_1) { | ||
2454 | CalculateMIC(KeyDescVer, pEntry->PTK, pMsg); | ||
2455 | } | ||
2456 | |||
2457 | DBGPRINT(RT_DEBUG_TRACE, | ||
2458 | ("===> ConstructEapolMsg for %s %s\n", | ||
2459 | ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType))); | ||
2460 | DBGPRINT(RT_DEBUG_TRACE, | ||
2461 | (" Body length = %d \n", | ||
2462 | CONV_ARRARY_TO_u16(pMsg->Body_Len))); | ||
2463 | DBGPRINT(RT_DEBUG_TRACE, | ||
2464 | (" Key length = %d \n", | ||
2465 | CONV_ARRARY_TO_u16(pMsg->KeyDesc.KeyLength))); | ||
2466 | |||
2467 | } | ||
2468 | |||
2469 | /* | ||
2470 | ======================================================================== | ||
2471 | |||
2472 | Routine Description: | ||
2473 | Construct the Key Data field of EAPoL message | ||
2474 | |||
2475 | Arguments: | ||
2476 | pAd Pointer to our adapter | ||
2477 | Elem Message body | ||
2478 | |||
2479 | Return Value: | ||
2480 | None | ||
2481 | |||
2482 | Note: | ||
2483 | |||
2484 | ======================================================================== | ||
2485 | */ | ||
2486 | void ConstructEapolKeyData(struct rt_mac_table_entry *pEntry, | ||
2487 | u8 GroupKeyWepStatus, | ||
2488 | u8 keyDescVer, | ||
2489 | u8 MsgType, | ||
2490 | u8 DefaultKeyIdx, | ||
2491 | u8 * GTK, | ||
2492 | u8 * RSNIE, | ||
2493 | u8 RSNIE_LEN, struct rt_eapol_packet * pMsg) | ||
2494 | { | ||
2495 | u8 *mpool, *Key_Data, *Rc4GTK; | ||
2496 | u8 ekey[(LEN_KEY_DESC_IV + LEN_EAP_EK)]; | ||
2497 | unsigned long data_offset; | ||
2498 | BOOLEAN bWPA2Capable = FALSE; | ||
2499 | struct rt_rtmp_adapter *pAd = pEntry->pAd; | ||
2500 | BOOLEAN GTK_Included = FALSE; | ||
2501 | |||
2502 | /* Choose WPA2 or not */ | ||
2503 | if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || | ||
2504 | (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) | ||
2505 | bWPA2Capable = TRUE; | ||
2506 | |||
2507 | if (MsgType == EAPOL_PAIR_MSG_1 || | ||
2508 | MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2) | ||
2509 | return; | ||
2510 | |||
2511 | /* allocate memory pool */ | ||
2512 | os_alloc_mem(NULL, (u8 **) & mpool, 1500); | ||
2513 | |||
2514 | if (mpool == NULL) | ||
2515 | return; | ||
2516 | |||
2517 | /* Rc4GTK Len = 512 */ | ||
2518 | Rc4GTK = (u8 *) ROUND_UP(mpool, 4); | ||
2519 | /* Key_Data Len = 512 */ | ||
2520 | Key_Data = (u8 *) ROUND_UP(Rc4GTK + 512, 4); | ||
2521 | |||
2522 | NdisZeroMemory(Key_Data, 512); | ||
2523 | SET_u16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, 0); | ||
2524 | data_offset = 0; | ||
2525 | |||
2526 | /* Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3 */ | ||
2527 | if (RSNIE_LEN | ||
2528 | && ((MsgType == EAPOL_PAIR_MSG_2) | ||
2529 | || (MsgType == EAPOL_PAIR_MSG_3))) { | ||
2530 | u8 *pmkid_ptr = NULL; | ||
2531 | u8 pmkid_len = 0; | ||
2532 | |||
2533 | RTMPInsertRSNIE(&Key_Data[data_offset], | ||
2534 | &data_offset, | ||
2535 | RSNIE, RSNIE_LEN, pmkid_ptr, pmkid_len); | ||
2536 | } | ||
2537 | |||
2538 | /* Encapsulate KDE format in pairwise_msg3_WPA2 & group_msg1_WPA2 */ | ||
2539 | if (bWPA2Capable | ||
2540 | && ((MsgType == EAPOL_PAIR_MSG_3) | ||
2541 | || (MsgType == EAPOL_GROUP_MSG_1))) { | ||
2542 | /* Key Data Encapsulation (KDE) format - 802.11i-2004 Figure-43w and Table-20h */ | ||
2543 | Key_Data[data_offset + 0] = 0xDD; | ||
2544 | |||
2545 | if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) { | ||
2546 | Key_Data[data_offset + 1] = 0x16; /* 4+2+16(OUI+DataType+DataField) */ | ||
2547 | } else { | ||
2548 | Key_Data[data_offset + 1] = 0x26; /* 4+2+32(OUI+DataType+DataField) */ | ||
2549 | } | ||
2550 | |||
2551 | Key_Data[data_offset + 2] = 0x00; | ||
2552 | Key_Data[data_offset + 3] = 0x0F; | ||
2553 | Key_Data[data_offset + 4] = 0xAC; | ||
2554 | Key_Data[data_offset + 5] = 0x01; | ||
2555 | |||
2556 | /* GTK KDE format - 802.11i-2004 Figure-43x */ | ||
2557 | Key_Data[data_offset + 6] = (DefaultKeyIdx & 0x03); | ||
2558 | Key_Data[data_offset + 7] = 0x00; /* Reserved Byte */ | ||
2559 | |||
2560 | data_offset += 8; | ||
2561 | } | ||
2562 | |||
2563 | /* Encapsulate GTK */ | ||
2564 | /* Only for pairwise_msg3_WPA2 and group_msg1 */ | ||
2565 | if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) | ||
2566 | || (MsgType == EAPOL_GROUP_MSG_1)) { | ||
2567 | /* Fill in GTK */ | ||
2568 | if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) { | ||
2569 | NdisMoveMemory(&Key_Data[data_offset], GTK, | ||
2570 | LEN_AES_KEY); | ||
2571 | data_offset += LEN_AES_KEY; | ||
2572 | } else { | ||
2573 | NdisMoveMemory(&Key_Data[data_offset], GTK, | ||
2574 | TKIP_GTK_LENGTH); | ||
2575 | data_offset += TKIP_GTK_LENGTH; | ||
2576 | } | ||
2577 | |||
2578 | GTK_Included = TRUE; | ||
2579 | } | ||
2580 | |||
2581 | /* This whole key-data field shall be encrypted if a GTK is included. */ | ||
2582 | /* Encrypt the data material in key data field with KEK */ | ||
2583 | if (GTK_Included) { | ||
2584 | /*hex_dump("GTK_Included", Key_Data, data_offset); */ | ||
2585 | |||
2586 | if ((keyDescVer == DESC_TYPE_AES)) { | ||
2587 | u8 remainder = 0; | ||
2588 | u8 pad_len = 0; | ||
2589 | |||
2590 | /* Key Descriptor Version 2 or 3: AES key wrap, defined in IETF RFC 3394, */ | ||
2591 | /* shall be used to encrypt the Key Data field using the KEK field from */ | ||
2592 | /* the derived PTK. */ | ||
2593 | |||
2594 | /* If the Key Data field uses the NIST AES key wrap, then the Key Data field */ | ||
2595 | /* shall be padded before encrypting if the key data length is less than 16 */ | ||
2596 | /* octets or if it is not a multiple of 8. The padding consists of appending */ | ||
2597 | /* a single octet 0xdd followed by zero or more 0x00 octets. */ | ||
2598 | if ((remainder = data_offset & 0x07) != 0) { | ||
2599 | int i; | ||
2600 | |||
2601 | pad_len = (8 - remainder); | ||
2602 | Key_Data[data_offset] = 0xDD; | ||
2603 | for (i = 1; i < pad_len; i++) | ||
2604 | Key_Data[data_offset + i] = 0; | ||
2605 | |||
2606 | data_offset += pad_len; | ||
2607 | } | ||
2608 | |||
2609 | AES_GTK_KEY_WRAP(&pEntry->PTK[16], Key_Data, | ||
2610 | data_offset, Rc4GTK); | ||
2611 | /* AES wrap function will grow 8 bytes in length */ | ||
2612 | data_offset += 8; | ||
2613 | } else { | ||
2614 | /* Key Descriptor Version 1: ARC4 is used to encrypt the Key Data field | ||
2615 | using the KEK field from the derived PTK. */ | ||
2616 | |||
2617 | /* PREPARE Encrypted "Key DATA" field. (Encrypt GTK with RC4, usinf PTK[16]->[31] as Key, IV-field as IV) */ | ||
2618 | /* put TxTsc in Key RSC field */ | ||
2619 | pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32; /*Init crc32. */ | ||
2620 | |||
2621 | /* ekey is the contanetion of IV-field, and PTK[16]->PTK[31] */ | ||
2622 | NdisMoveMemory(ekey, pMsg->KeyDesc.KeyIv, | ||
2623 | LEN_KEY_DESC_IV); | ||
2624 | NdisMoveMemory(&ekey[LEN_KEY_DESC_IV], &pEntry->PTK[16], | ||
2625 | LEN_EAP_EK); | ||
2626 | ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, ekey, sizeof(ekey)); /*INIT SBOX, KEYLEN+3(IV) */ | ||
2627 | pAd->PrivateInfo.FCSCRC32 = | ||
2628 | RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, Key_Data, | ||
2629 | data_offset); | ||
2630 | WPAARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, Rc4GTK, | ||
2631 | Key_Data, data_offset); | ||
2632 | } | ||
2633 | |||
2634 | NdisMoveMemory(pMsg->KeyDesc.KeyData, Rc4GTK, data_offset); | ||
2635 | } else { | ||
2636 | NdisMoveMemory(pMsg->KeyDesc.KeyData, Key_Data, data_offset); | ||
2637 | } | ||
2638 | |||
2639 | /* Update key data length field and total body length */ | ||
2640 | SET_u16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, data_offset); | ||
2641 | INC_u16_TO_ARRARY(pMsg->Body_Len, data_offset); | ||
2642 | |||
2643 | os_free_mem(NULL, mpool); | ||
2644 | |||
2645 | } | ||
2646 | |||
2647 | /* | ||
2648 | ======================================================================== | ||
2649 | |||
2650 | Routine Description: | ||
2651 | Calcaulate MIC. It is used during 4-ways handsharking. | ||
2652 | |||
2653 | Arguments: | ||
2654 | pAd - pointer to our pAdapter context | ||
2655 | PeerWepStatus - indicate the encryption type | ||
2656 | |||
2657 | Return Value: | ||
2658 | |||
2659 | Note: | ||
2660 | |||
2661 | ======================================================================== | ||
2662 | */ | ||
2663 | static void CalculateMIC(u8 KeyDescVer, | ||
2664 | u8 * PTK, struct rt_eapol_packet * pMsg) | ||
2665 | { | ||
2666 | u8 *OutBuffer; | ||
2667 | unsigned long FrameLen = 0; | ||
2668 | u8 mic[LEN_KEY_DESC_MIC]; | ||
2669 | u8 digest[80]; | ||
2670 | |||
2671 | /* allocate memory for MIC calculation */ | ||
2672 | os_alloc_mem(NULL, (u8 **) & OutBuffer, 512); | ||
2673 | |||
2674 | if (OutBuffer == NULL) { | ||
2675 | DBGPRINT(RT_DEBUG_ERROR, ("CalculateMIC: no memory!\n")); | ||
2676 | return; | ||
2677 | } | ||
2678 | /* make a frame for calculating MIC. */ | ||
2679 | MakeOutgoingFrame(OutBuffer, &FrameLen, | ||
2680 | CONV_ARRARY_TO_u16(pMsg->Body_Len) + 4, pMsg, | ||
2681 | END_OF_ARGS); | ||
2682 | |||
2683 | NdisZeroMemory(mic, sizeof(mic)); | ||
2684 | |||
2685 | /* Calculate MIC */ | ||
2686 | if (KeyDescVer == DESC_TYPE_AES) { | ||
2687 | HMAC_SHA1(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, digest, | ||
2688 | SHA1_DIGEST_SIZE); | ||
2689 | NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC); | ||
2690 | } else { | ||
2691 | HMAC_MD5(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, mic, | ||
2692 | MD5_DIGEST_SIZE); | ||
2693 | } | ||
2694 | |||
2695 | /* store the calculated MIC */ | ||
2696 | NdisMoveMemory(pMsg->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC); | ||
2697 | |||
2698 | os_free_mem(NULL, OutBuffer); | ||
2699 | } | ||
2700 | |||
2701 | /* | ||
2702 | ======================================================================== | ||
2703 | |||
2704 | Routine Description: | ||
2705 | Some received frames can't decrypt by Asic, so decrypt them by software. | ||
2706 | |||
2707 | Arguments: | ||
2708 | pAd - pointer to our pAdapter context | ||
2709 | PeerWepStatus - indicate the encryption type | ||
2710 | |||
2711 | Return Value: | ||
2712 | NDIS_STATUS_SUCCESS - decryption successful | ||
2713 | NDIS_STATUS_FAILURE - decryption failure | ||
2714 | |||
2715 | ======================================================================== | ||
2716 | */ | ||
2717 | int RTMPSoftDecryptBroadCastData(struct rt_rtmp_adapter *pAd, | ||
2718 | struct rt_rx_blk *pRxBlk, | ||
2719 | IN NDIS_802_11_ENCRYPTION_STATUS | ||
2720 | GroupCipher, struct rt_cipher_key *pShard_key) | ||
2721 | { | ||
2722 | struct rt_rxwi * pRxWI = pRxBlk->pRxWI; | ||
2723 | |||
2724 | /* handle WEP decryption */ | ||
2725 | if (GroupCipher == Ndis802_11Encryption1Enabled) { | ||
2726 | if (RTMPSoftDecryptWEP | ||
2727 | (pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, | ||
2728 | pShard_key)) { | ||
2729 | |||
2730 | /*Minus IV[4] & ICV[4] */ | ||
2731 | pRxWI->MPDUtotalByteCount -= 8; | ||
2732 | } else { | ||
2733 | DBGPRINT(RT_DEBUG_ERROR, | ||
2734 | ("ERROR : Software decrypt WEP data fails.\n")); | ||
2735 | /* give up this frame */ | ||
2736 | return NDIS_STATUS_FAILURE; | ||
2737 | } | ||
2738 | } | ||
2739 | /* handle TKIP decryption */ | ||
2740 | else if (GroupCipher == Ndis802_11Encryption2Enabled) { | ||
2741 | if (RTMPSoftDecryptTKIP | ||
2742 | (pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, 0, | ||
2743 | pShard_key)) { | ||
2744 | |||
2745 | /*Minus 8 bytes MIC, 8 bytes IV/EIV, 4 bytes ICV */ | ||
2746 | pRxWI->MPDUtotalByteCount -= 20; | ||
2747 | } else { | ||
2748 | DBGPRINT(RT_DEBUG_ERROR, | ||
2749 | ("ERROR : RTMPSoftDecryptTKIP Failed\n")); | ||
2750 | /* give up this frame */ | ||
2751 | return NDIS_STATUS_FAILURE; | ||
2752 | } | ||
2753 | } | ||
2754 | /* handle AES decryption */ | ||
2755 | else if (GroupCipher == Ndis802_11Encryption3Enabled) { | ||
2756 | if (RTMPSoftDecryptAES | ||
2757 | (pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, | ||
2758 | pShard_key)) { | ||
2759 | |||
2760 | /*8 bytes MIC, 8 bytes IV/EIV (CCMP Header) */ | ||
2761 | pRxWI->MPDUtotalByteCount -= 16; | ||
2762 | } else { | ||
2763 | DBGPRINT(RT_DEBUG_ERROR, | ||
2764 | ("ERROR : RTMPSoftDecryptAES Failed\n")); | ||
2765 | /* give up this frame */ | ||
2766 | return NDIS_STATUS_FAILURE; | ||
2767 | } | ||
2768 | } else { | ||
2769 | /* give up this frame */ | ||
2770 | return NDIS_STATUS_FAILURE; | ||
2771 | } | ||
2772 | |||
2773 | return NDIS_STATUS_SUCCESS; | ||
2774 | |||
2775 | } | ||
2776 | |||
2777 | u8 *GetSuiteFromRSNIE(u8 *rsnie, | ||
2778 | u32 rsnie_len, u8 type, u8 * count) | ||
2779 | { | ||
2780 | struct rt_eid * pEid; | ||
2781 | int len; | ||
2782 | u8 *pBuf; | ||
2783 | int offset = 0; | ||
2784 | struct rt_rsnie_auth *pAkm; | ||
2785 | u16 acount; | ||
2786 | BOOLEAN isWPA2 = FALSE; | ||
2787 | |||
2788 | pEid = (struct rt_eid *) rsnie; | ||
2789 | len = rsnie_len - 2; /* exclude IE and length */ | ||
2790 | pBuf = (u8 *)& pEid->Octet[0]; | ||
2791 | |||
2792 | /* set default value */ | ||
2793 | *count = 0; | ||
2794 | |||
2795 | /* Check length */ | ||
2796 | if ((len <= 0) || (pEid->Len != len)) { | ||
2797 | DBGPRINT_ERR("%s : The length is invalid\n", __func__); | ||
2798 | return NULL; | ||
2799 | } | ||
2800 | /* Check WPA or WPA2 */ | ||
2801 | if (pEid->Eid == IE_WPA) { | ||
2802 | struct rt_rsnie *pRsnie = (struct rt_rsnie *)pBuf; | ||
2803 | u16 ucount; | ||
2804 | |||
2805 | if (len < sizeof(struct rt_rsnie)) { | ||
2806 | DBGPRINT_ERR("%s : The length is too short for WPA\n", __func__); | ||
2807 | return NULL; | ||
2808 | } | ||
2809 | /* Get the count of pairwise cipher */ | ||
2810 | ucount = cpu2le16(pRsnie->ucount); | ||
2811 | if (ucount > 2) { | ||
2812 | DBGPRINT_ERR("%s : The count(%d) of pairwise cipher is invlaid\n", __func__, ucount); | ||
2813 | return NULL; | ||
2814 | } | ||
2815 | /* Get the group cipher */ | ||
2816 | if (type == GROUP_SUITE) { | ||
2817 | *count = 1; | ||
2818 | return pRsnie->mcast; | ||
2819 | } | ||
2820 | /* Get the pairwise cipher suite */ | ||
2821 | else if (type == PAIRWISE_SUITE) { | ||
2822 | DBGPRINT(RT_DEBUG_TRACE, | ||
2823 | ("%s : The count of pairwise cipher is %d\n", | ||
2824 | __func__, ucount)); | ||
2825 | *count = ucount; | ||
2826 | return pRsnie->ucast[0].oui; | ||
2827 | } | ||
2828 | |||
2829 | offset = sizeof(struct rt_rsnie) + (4 * (ucount - 1)); | ||
2830 | |||
2831 | } else if (pEid->Eid == IE_RSN) { | ||
2832 | struct rt_rsnie2 *pRsnie = (struct rt_rsnie2 *)pBuf; | ||
2833 | u16 ucount; | ||
2834 | |||
2835 | isWPA2 = TRUE; | ||
2836 | |||
2837 | if (len < sizeof(struct rt_rsnie2)) { | ||
2838 | DBGPRINT_ERR("%s : The length is too short for WPA2\n", __func__); | ||
2839 | return NULL; | ||
2840 | } | ||
2841 | /* Get the count of pairwise cipher */ | ||
2842 | ucount = cpu2le16(pRsnie->ucount); | ||
2843 | if (ucount > 2) { | ||
2844 | DBGPRINT_ERR("%s : The count(%d) of pairwise cipher is invlaid\n", __func__, ucount); | ||
2845 | return NULL; | ||
2846 | } | ||
2847 | /* Get the group cipher */ | ||
2848 | if (type == GROUP_SUITE) { | ||
2849 | *count = 1; | ||
2850 | return pRsnie->mcast; | ||
2851 | } | ||
2852 | /* Get the pairwise cipher suite */ | ||
2853 | else if (type == PAIRWISE_SUITE) { | ||
2854 | DBGPRINT(RT_DEBUG_TRACE, | ||
2855 | ("%s : The count of pairwise cipher is %d\n", | ||
2856 | __func__, ucount)); | ||
2857 | *count = ucount; | ||
2858 | return pRsnie->ucast[0].oui; | ||
2859 | } | ||
2860 | |||
2861 | offset = sizeof(struct rt_rsnie2) + (4 * (ucount - 1)); | ||
2862 | |||
2863 | } else { | ||
2864 | DBGPRINT_ERR("%s : Unknown IE (%d)\n", __func__, pEid->Eid); | ||
2865 | return NULL; | ||
2866 | } | ||
2867 | |||
2868 | /* skip group cipher and pairwise cipher suite */ | ||
2869 | pBuf += offset; | ||
2870 | len -= offset; | ||
2871 | |||
2872 | if (len < sizeof(struct rt_rsnie_auth)) { | ||
2873 | DBGPRINT_ERR("%s : The length of RSNIE is too short\n", __func__); | ||
2874 | return NULL; | ||
2875 | } | ||
2876 | /* pointer to AKM count */ | ||
2877 | pAkm = (struct rt_rsnie_auth *)pBuf; | ||
2878 | |||
2879 | /* Get the count of pairwise cipher */ | ||
2880 | acount = cpu2le16(pAkm->acount); | ||
2881 | if (acount > 2) { | ||
2882 | DBGPRINT_ERR("%s : The count(%d) of AKM is invlaid\n", __func__, acount); | ||
2883 | return NULL; | ||
2884 | } | ||
2885 | /* Get the AKM suite */ | ||
2886 | if (type == AKM_SUITE) { | ||
2887 | DBGPRINT(RT_DEBUG_TRACE, ("%s : The count of AKM is %d\n", | ||
2888 | __func__, acount)); | ||
2889 | *count = acount; | ||
2890 | return pAkm->auth[0].oui; | ||
2891 | } | ||
2892 | offset = sizeof(struct rt_rsnie_auth) + (4 * (acount - 1)); | ||
2893 | |||
2894 | pBuf += offset; | ||
2895 | len -= offset; | ||
2896 | |||
2897 | /* The remaining length must larger than (RSN-Capability(2) + PMKID-Count(2) + PMKID(16~)) */ | ||
2898 | if (len >= (sizeof(RSN_CAPABILITIES) + 2 + LEN_PMKID)) { | ||
2899 | /* Skip RSN capability and PMKID-Count */ | ||
2900 | pBuf += (sizeof(RSN_CAPABILITIES) + 2); | ||
2901 | len -= (sizeof(RSN_CAPABILITIES) + 2); | ||
2902 | |||
2903 | /* Get PMKID */ | ||
2904 | if (type == PMKID_LIST) { | ||
2905 | *count = 1; | ||
2906 | return pBuf; | ||
2907 | } | ||
2908 | } else { | ||
2909 | DBGPRINT_ERR("%s : it can't get any more information beyond AKM \n", __func__); | ||
2910 | return NULL; | ||
2911 | } | ||
2912 | |||
2913 | *count = 0; | ||
2914 | /*DBGPRINT_ERR(("%s : The type(%d) doesn't support \n", __func__, type)); */ | ||
2915 | return NULL; | ||
2916 | |||
2917 | } | ||
2918 | |||
2919 | void WpaShowAllsuite(u8 *rsnie, u32 rsnie_len) | ||
2920 | { | ||
2921 | u8 *pSuite = NULL; | ||
2922 | u8 count; | ||
2923 | |||
2924 | hex_dump("RSNIE", rsnie, rsnie_len); | ||
2925 | |||
2926 | /* group cipher */ | ||
2927 | pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, GROUP_SUITE, &count); | ||
2928 | if (pSuite != NULL) { | ||
2929 | hex_dump("group cipher", pSuite, 4 * count); | ||
2930 | } | ||
2931 | /* pairwise cipher */ | ||
2932 | pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, PAIRWISE_SUITE, &count); | ||
2933 | if (pSuite != NULL) { | ||
2934 | hex_dump("pairwise cipher", pSuite, 4 * count); | ||
2935 | } | ||
2936 | /* AKM */ | ||
2937 | pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, AKM_SUITE, &count); | ||
2938 | if (pSuite != NULL) { | ||
2939 | hex_dump("AKM suite", pSuite, 4 * count); | ||
2940 | } | ||
2941 | /* PMKID */ | ||
2942 | pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, PMKID_LIST, &count); | ||
2943 | if (pSuite != NULL) { | ||
2944 | hex_dump("PMKID", pSuite, LEN_PMKID); | ||
2945 | } | ||
2946 | |||
2947 | } | ||
2948 | |||
2949 | void RTMPInsertRSNIE(u8 *pFrameBuf, | ||
2950 | unsigned long *pFrameLen, | ||
2951 | u8 *rsnie_ptr, | ||
2952 | u8 rsnie_len, | ||
2953 | u8 *pmkid_ptr, u8 pmkid_len) | ||
2954 | { | ||
2955 | u8 *pTmpBuf; | ||
2956 | unsigned long TempLen = 0; | ||
2957 | u8 extra_len = 0; | ||
2958 | u16 pmk_count = 0; | ||
2959 | u8 ie_num; | ||
2960 | u8 total_len = 0; | ||
2961 | u8 WPA2_OUI[3] = { 0x00, 0x0F, 0xAC }; | ||
2962 | |||
2963 | pTmpBuf = pFrameBuf; | ||
2964 | |||
2965 | /* PMKID-List Must larger than 0 and the multiple of 16. */ | ||
2966 | if (pmkid_len > 0 && ((pmkid_len & 0x0f) == 0)) { | ||
2967 | extra_len = sizeof(u16)+ pmkid_len; | ||
2968 | |||
2969 | pmk_count = (pmkid_len >> 4); | ||
2970 | pmk_count = cpu2le16(pmk_count); | ||
2971 | } else { | ||
2972 | DBGPRINT(RT_DEBUG_WARN, | ||
2973 | ("%s : The length is PMKID-List is invalid (%d), so don't insert it.\n", | ||
2974 | __func__, pmkid_len)); | ||
2975 | } | ||
2976 | |||
2977 | if (rsnie_len != 0) { | ||
2978 | ie_num = IE_WPA; | ||
2979 | total_len = rsnie_len; | ||
2980 | |||
2981 | if (NdisEqualMemory(rsnie_ptr + 2, WPA2_OUI, sizeof(WPA2_OUI))) { | ||
2982 | ie_num = IE_RSN; | ||
2983 | total_len += extra_len; | ||
2984 | } | ||
2985 | |||
2986 | /* construct RSNIE body */ | ||
2987 | MakeOutgoingFrame(pTmpBuf, &TempLen, | ||
2988 | 1, &ie_num, | ||
2989 | 1, &total_len, | ||
2990 | rsnie_len, rsnie_ptr, END_OF_ARGS); | ||
2991 | |||
2992 | pTmpBuf += TempLen; | ||
2993 | *pFrameLen = *pFrameLen + TempLen; | ||
2994 | |||
2995 | if (ie_num == IE_RSN) { | ||
2996 | /* Insert PMKID-List field */ | ||
2997 | if (extra_len > 0) { | ||
2998 | MakeOutgoingFrame(pTmpBuf, &TempLen, | ||
2999 | 2, &pmk_count, | ||
3000 | pmkid_len, pmkid_ptr, | ||
3001 | END_OF_ARGS); | ||
3002 | |||
3003 | pTmpBuf += TempLen; | ||
3004 | *pFrameLen = *pFrameLen + TempLen; | ||
3005 | } | ||
3006 | } | ||
3007 | } | ||
3008 | |||
3009 | return; | ||
3010 | } | ||
diff --git a/drivers/staging/rt2860/common/crypt_hmac.c b/drivers/staging/rt2860/common/crypt_hmac.c deleted file mode 100644 index d7ab08ec1a4..00000000000 --- a/drivers/staging/rt2860/common/crypt_hmac.c +++ /dev/null | |||
@@ -1,187 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | *************************************************************************/ | ||
26 | |||
27 | #include "../crypt_hmac.h" | ||
28 | |||
29 | #ifdef HMAC_SHA1_SUPPORT | ||
30 | /* | ||
31 | ======================================================================== | ||
32 | Routine Description: | ||
33 | HMAC using SHA1 hash function | ||
34 | |||
35 | Arguments: | ||
36 | key Secret key | ||
37 | key_len The length of the key in bytes | ||
38 | message Message context | ||
39 | message_len The length of message in bytes | ||
40 | macLen Request the length of message authentication code | ||
41 | |||
42 | Return Value: | ||
43 | mac Message authentication code | ||
44 | |||
45 | Note: | ||
46 | None | ||
47 | ======================================================================== | ||
48 | */ | ||
49 | void HMAC_SHA1(IN const u8 Key[], | ||
50 | u32 KeyLen, | ||
51 | IN const u8 Message[], | ||
52 | u32 MessageLen, u8 MAC[], u32 MACLen) | ||
53 | { | ||
54 | struct rt_sha1_ctx sha_ctx1; | ||
55 | struct rt_sha1_ctx sha_ctx2; | ||
56 | u8 K0[SHA1_BLOCK_SIZE]; | ||
57 | u8 Digest[SHA1_DIGEST_SIZE]; | ||
58 | u32 index; | ||
59 | |||
60 | NdisZeroMemory(&sha_ctx1, sizeof(struct rt_sha1_ctx)); | ||
61 | NdisZeroMemory(&sha_ctx2, sizeof(struct rt_sha1_ctx)); | ||
62 | /* | ||
63 | * If the length of K = B(Block size): K0 = K. | ||
64 | * If the length of K > B: hash K to obtain an L byte string, | ||
65 | * then append (B-L) zeros to create a B-byte string K0 (i.e., K0 = H(K) || 00...00). | ||
66 | * If the length of K < B: append zeros to the end of K to create a B-byte string K0 | ||
67 | */ | ||
68 | NdisZeroMemory(K0, SHA1_BLOCK_SIZE); | ||
69 | if (KeyLen <= SHA1_BLOCK_SIZE) | ||
70 | NdisMoveMemory(K0, Key, KeyLen); | ||
71 | else | ||
72 | RT_SHA1(Key, KeyLen, K0); | ||
73 | /* End of if */ | ||
74 | |||
75 | /* Exclusive-Or K0 with ipad */ | ||
76 | /* ipad: Inner pad; the byte x¡¦36¡¦ repeated B times. */ | ||
77 | for (index = 0; index < SHA1_BLOCK_SIZE; index++) | ||
78 | K0[index] ^= 0x36; | ||
79 | /* End of for */ | ||
80 | |||
81 | RT_SHA1_Init(&sha_ctx1); | ||
82 | /* H(K0^ipad) */ | ||
83 | SHA1_Append(&sha_ctx1, K0, sizeof(K0)); | ||
84 | /* H((K0^ipad)||text) */ | ||
85 | SHA1_Append(&sha_ctx1, Message, MessageLen); | ||
86 | SHA1_End(&sha_ctx1, Digest); | ||
87 | |||
88 | /* Exclusive-Or K0 with opad and remove ipad */ | ||
89 | /* opad: Outer pad; the byte x¡¦5c¡¦ repeated B times. */ | ||
90 | for (index = 0; index < SHA1_BLOCK_SIZE; index++) | ||
91 | K0[index] ^= 0x36 ^ 0x5c; | ||
92 | /* End of for */ | ||
93 | |||
94 | RT_SHA1_Init(&sha_ctx2); | ||
95 | /* H(K0^opad) */ | ||
96 | SHA1_Append(&sha_ctx2, K0, sizeof(K0)); | ||
97 | /* H( (K0^opad) || H((K0^ipad)||text) ) */ | ||
98 | SHA1_Append(&sha_ctx2, Digest, SHA1_DIGEST_SIZE); | ||
99 | SHA1_End(&sha_ctx2, Digest); | ||
100 | |||
101 | if (MACLen > SHA1_DIGEST_SIZE) | ||
102 | NdisMoveMemory(MAC, Digest, SHA1_DIGEST_SIZE); | ||
103 | else | ||
104 | NdisMoveMemory(MAC, Digest, MACLen); | ||
105 | } /* End of HMAC_SHA1 */ | ||
106 | #endif /* HMAC_SHA1_SUPPORT */ | ||
107 | |||
108 | #ifdef HMAC_MD5_SUPPORT | ||
109 | /* | ||
110 | ======================================================================== | ||
111 | Routine Description: | ||
112 | HMAC using MD5 hash function | ||
113 | |||
114 | Arguments: | ||
115 | key Secret key | ||
116 | key_len The length of the key in bytes | ||
117 | message Message context | ||
118 | message_len The length of message in bytes | ||
119 | macLen Request the length of message authentication code | ||
120 | |||
121 | Return Value: | ||
122 | mac Message authentication code | ||
123 | |||
124 | Note: | ||
125 | None | ||
126 | ======================================================================== | ||
127 | */ | ||
128 | void HMAC_MD5(IN const u8 Key[], | ||
129 | u32 KeyLen, | ||
130 | IN const u8 Message[], | ||
131 | u32 MessageLen, u8 MAC[], u32 MACLen) | ||
132 | { | ||
133 | struct rt_md5_ctx_struc md5_ctx1; | ||
134 | struct rt_md5_ctx_struc md5_ctx2; | ||
135 | u8 K0[MD5_BLOCK_SIZE]; | ||
136 | u8 Digest[MD5_DIGEST_SIZE]; | ||
137 | u32 index; | ||
138 | |||
139 | NdisZeroMemory(&md5_ctx1, sizeof(struct rt_md5_ctx_struc)); | ||
140 | NdisZeroMemory(&md5_ctx2, sizeof(struct rt_md5_ctx_struc)); | ||
141 | /* | ||
142 | * If the length of K = B(Block size): K0 = K. | ||
143 | * If the length of K > B: hash K to obtain an L byte string, | ||
144 | * then append (B-L) zeros to create a B-byte string K0 (i.e., K0 = H(K) || 00...00). | ||
145 | * If the length of K < B: append zeros to the end of K to create a B-byte string K0 | ||
146 | */ | ||
147 | NdisZeroMemory(K0, MD5_BLOCK_SIZE); | ||
148 | if (KeyLen <= MD5_BLOCK_SIZE) { | ||
149 | NdisMoveMemory(K0, Key, KeyLen); | ||
150 | } else { | ||
151 | RT_MD5(Key, KeyLen, K0); | ||
152 | } | ||
153 | |||
154 | /* Exclusive-Or K0 with ipad */ | ||
155 | /* ipad: Inner pad; the byte x¡¦36¡¦ repeated B times. */ | ||
156 | for (index = 0; index < MD5_BLOCK_SIZE; index++) | ||
157 | K0[index] ^= 0x36; | ||
158 | /* End of for */ | ||
159 | |||
160 | MD5_Init(&md5_ctx1); | ||
161 | /* H(K0^ipad) */ | ||
162 | MD5_Append(&md5_ctx1, K0, sizeof(K0)); | ||
163 | /* H((K0^ipad)||text) */ | ||
164 | MD5_Append(&md5_ctx1, Message, MessageLen); | ||
165 | MD5_End(&md5_ctx1, Digest); | ||
166 | |||
167 | /* Exclusive-Or K0 with opad and remove ipad */ | ||
168 | /* opad: Outer pad; the byte x¡¦5c¡¦ repeated B times. */ | ||
169 | for (index = 0; index < MD5_BLOCK_SIZE; index++) | ||
170 | K0[index] ^= 0x36 ^ 0x5c; | ||
171 | /* End of for */ | ||
172 | |||
173 | MD5_Init(&md5_ctx2); | ||
174 | /* H(K0^opad) */ | ||
175 | MD5_Append(&md5_ctx2, K0, sizeof(K0)); | ||
176 | /* H( (K0^opad) || H((K0^ipad)||text) ) */ | ||
177 | MD5_Append(&md5_ctx2, Digest, MD5_DIGEST_SIZE); | ||
178 | MD5_End(&md5_ctx2, Digest); | ||
179 | |||
180 | if (MACLen > MD5_DIGEST_SIZE) | ||
181 | NdisMoveMemory(MAC, Digest, MD5_DIGEST_SIZE); | ||
182 | else | ||
183 | NdisMoveMemory(MAC, Digest, MACLen); | ||
184 | } /* End of HMAC_SHA256 */ | ||
185 | #endif /* HMAC_MD5_SUPPORT */ | ||
186 | |||
187 | /* End of crypt_hmac.c */ | ||
diff --git a/drivers/staging/rt2860/common/crypt_md5.c b/drivers/staging/rt2860/common/crypt_md5.c deleted file mode 100644 index 6deab659c22..00000000000 --- a/drivers/staging/rt2860/common/crypt_md5.c +++ /dev/null | |||
@@ -1,339 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | *************************************************************************/ | ||
26 | |||
27 | #include "../crypt_md5.h" | ||
28 | |||
29 | #ifdef MD5_SUPPORT | ||
30 | /* | ||
31 | * F, G, H and I are basic MD5 functions. | ||
32 | */ | ||
33 | #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) | ||
34 | #define G(x, y, z) (((x) & (z)) | ((y) & (~z))) | ||
35 | #define H(x, y, z) ((x) ^ (y) ^ (z)) | ||
36 | #define I(x, y, z) ((y) ^ ((x) | (~z))) | ||
37 | |||
38 | #define ROTL(x,n,w) ((x << n) | (x >> (w - n))) | ||
39 | #define ROTL32(x,n) ROTL(x,n,32) /* 32 bits word */ | ||
40 | |||
41 | #define ROUND1(a, b, c, d, x, s, ac) { \ | ||
42 | (a) += F((b),(c),(d)) + (x) + (u32)(ac); \ | ||
43 | (a) = ROTL32((a),(s)); \ | ||
44 | (a) += (b); \ | ||
45 | } | ||
46 | #define ROUND2(a, b, c, d, x, s, ac) { \ | ||
47 | (a) += G((b),(c),(d)) + (x) + (u32)(ac); \ | ||
48 | (a) = ROTL32((a),(s)); \ | ||
49 | (a) += (b); \ | ||
50 | } | ||
51 | #define ROUND3(a, b, c, d, x, s, ac) { \ | ||
52 | (a) += H((b),(c),(d)) + (x) + (u32)(ac); \ | ||
53 | (a) = ROTL32((a),(s)); \ | ||
54 | (a) += (b); \ | ||
55 | } | ||
56 | #define ROUND4(a, b, c, d, x, s, ac) { \ | ||
57 | (a) += I((b),(c),(d)) + (x) + (u32)(ac); \ | ||
58 | (a) = ROTL32((a),(s)); \ | ||
59 | (a) += (b); \ | ||
60 | } | ||
61 | static const u32 MD5_DefaultHashValue[4] = { | ||
62 | 0x67452301UL, 0xefcdab89UL, 0x98badcfeUL, 0x10325476UL | ||
63 | }; | ||
64 | #endif /* MD5_SUPPORT */ | ||
65 | |||
66 | #ifdef MD5_SUPPORT | ||
67 | /* | ||
68 | ======================================================================== | ||
69 | Routine Description: | ||
70 | Initial Md5_CTX_STRUC | ||
71 | |||
72 | Arguments: | ||
73 | pMD5_CTX Pointer to Md5_CTX_STRUC | ||
74 | |||
75 | Return Value: | ||
76 | None | ||
77 | |||
78 | Note: | ||
79 | None | ||
80 | ======================================================================== | ||
81 | */ | ||
82 | void MD5_Init(struct rt_md5_ctx_struc *pMD5_CTX) | ||
83 | { | ||
84 | NdisMoveMemory(pMD5_CTX->HashValue, MD5_DefaultHashValue, | ||
85 | sizeof(MD5_DefaultHashValue)); | ||
86 | NdisZeroMemory(pMD5_CTX->Block, MD5_BLOCK_SIZE); | ||
87 | pMD5_CTX->BlockLen = 0; | ||
88 | pMD5_CTX->MessageLen = 0; | ||
89 | } /* End of MD5_Init */ | ||
90 | |||
91 | /* | ||
92 | ======================================================================== | ||
93 | Routine Description: | ||
94 | MD5 computation for one block (512 bits) | ||
95 | |||
96 | Arguments: | ||
97 | pMD5_CTX Pointer to Md5_CTX_STRUC | ||
98 | |||
99 | Return Value: | ||
100 | None | ||
101 | |||
102 | Note: | ||
103 | T[i] := floor(abs(sin(i + 1)) * (2 pow 32)), i is number of round | ||
104 | ======================================================================== | ||
105 | */ | ||
106 | void MD5_Hash(struct rt_md5_ctx_struc *pMD5_CTX) | ||
107 | { | ||
108 | u32 X_i; | ||
109 | u32 X[16]; | ||
110 | u32 a, b, c, d; | ||
111 | |||
112 | /* Prepare the message schedule, {X_i} */ | ||
113 | NdisMoveMemory(X, pMD5_CTX->Block, MD5_BLOCK_SIZE); | ||
114 | for (X_i = 0; X_i < 16; X_i++) | ||
115 | X[X_i] = cpu2le32(X[X_i]); /* Endian Swap */ | ||
116 | /* End of for */ | ||
117 | |||
118 | /* MD5 hash computation */ | ||
119 | /* Initialize the working variables */ | ||
120 | a = pMD5_CTX->HashValue[0]; | ||
121 | b = pMD5_CTX->HashValue[1]; | ||
122 | c = pMD5_CTX->HashValue[2]; | ||
123 | d = pMD5_CTX->HashValue[3]; | ||
124 | |||
125 | /* | ||
126 | * Round 1 | ||
127 | * Let [abcd k s i] denote the operation | ||
128 | * a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s) | ||
129 | */ | ||
130 | ROUND1(a, b, c, d, X[0], 7, 0xd76aa478); /* 1 */ | ||
131 | ROUND1(d, a, b, c, X[1], 12, 0xe8c7b756); /* 2 */ | ||
132 | ROUND1(c, d, a, b, X[2], 17, 0x242070db); /* 3 */ | ||
133 | ROUND1(b, c, d, a, X[3], 22, 0xc1bdceee); /* 4 */ | ||
134 | ROUND1(a, b, c, d, X[4], 7, 0xf57c0faf); /* 5 */ | ||
135 | ROUND1(d, a, b, c, X[5], 12, 0x4787c62a); /* 6 */ | ||
136 | ROUND1(c, d, a, b, X[6], 17, 0xa8304613); /* 7 */ | ||
137 | ROUND1(b, c, d, a, X[7], 22, 0xfd469501); /* 8 */ | ||
138 | ROUND1(a, b, c, d, X[8], 7, 0x698098d8); /* 9 */ | ||
139 | ROUND1(d, a, b, c, X[9], 12, 0x8b44f7af); /* 10 */ | ||
140 | ROUND1(c, d, a, b, X[10], 17, 0xffff5bb1); /* 11 */ | ||
141 | ROUND1(b, c, d, a, X[11], 22, 0x895cd7be); /* 12 */ | ||
142 | ROUND1(a, b, c, d, X[12], 7, 0x6b901122); /* 13 */ | ||
143 | ROUND1(d, a, b, c, X[13], 12, 0xfd987193); /* 14 */ | ||
144 | ROUND1(c, d, a, b, X[14], 17, 0xa679438e); /* 15 */ | ||
145 | ROUND1(b, c, d, a, X[15], 22, 0x49b40821); /* 16 */ | ||
146 | |||
147 | /* | ||
148 | * Round 2 | ||
149 | * Let [abcd k s i] denote the operation | ||
150 | * a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s) | ||
151 | */ | ||
152 | ROUND2(a, b, c, d, X[1], 5, 0xf61e2562); /* 17 */ | ||
153 | ROUND2(d, a, b, c, X[6], 9, 0xc040b340); /* 18 */ | ||
154 | ROUND2(c, d, a, b, X[11], 14, 0x265e5a51); /* 19 */ | ||
155 | ROUND2(b, c, d, a, X[0], 20, 0xe9b6c7aa); /* 20 */ | ||
156 | ROUND2(a, b, c, d, X[5], 5, 0xd62f105d); /* 21 */ | ||
157 | ROUND2(d, a, b, c, X[10], 9, 0x2441453); /* 22 */ | ||
158 | ROUND2(c, d, a, b, X[15], 14, 0xd8a1e681); /* 23 */ | ||
159 | ROUND2(b, c, d, a, X[4], 20, 0xe7d3fbc8); /* 24 */ | ||
160 | ROUND2(a, b, c, d, X[9], 5, 0x21e1cde6); /* 25 */ | ||
161 | ROUND2(d, a, b, c, X[14], 9, 0xc33707d6); /* 26 */ | ||
162 | ROUND2(c, d, a, b, X[3], 14, 0xf4d50d87); /* 27 */ | ||
163 | ROUND2(b, c, d, a, X[8], 20, 0x455a14ed); /* 28 */ | ||
164 | ROUND2(a, b, c, d, X[13], 5, 0xa9e3e905); /* 29 */ | ||
165 | ROUND2(d, a, b, c, X[2], 9, 0xfcefa3f8); /* 30 */ | ||
166 | ROUND2(c, d, a, b, X[7], 14, 0x676f02d9); /* 31 */ | ||
167 | ROUND2(b, c, d, a, X[12], 20, 0x8d2a4c8a); /* 32 */ | ||
168 | |||
169 | /* | ||
170 | * Round 3 | ||
171 | * Let [abcd k s t] denote the operation | ||
172 | * a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s) | ||
173 | */ | ||
174 | ROUND3(a, b, c, d, X[5], 4, 0xfffa3942); /* 33 */ | ||
175 | ROUND3(d, a, b, c, X[8], 11, 0x8771f681); /* 34 */ | ||
176 | ROUND3(c, d, a, b, X[11], 16, 0x6d9d6122); /* 35 */ | ||
177 | ROUND3(b, c, d, a, X[14], 23, 0xfde5380c); /* 36 */ | ||
178 | ROUND3(a, b, c, d, X[1], 4, 0xa4beea44); /* 37 */ | ||
179 | ROUND3(d, a, b, c, X[4], 11, 0x4bdecfa9); /* 38 */ | ||
180 | ROUND3(c, d, a, b, X[7], 16, 0xf6bb4b60); /* 39 */ | ||
181 | ROUND3(b, c, d, a, X[10], 23, 0xbebfbc70); /* 40 */ | ||
182 | ROUND3(a, b, c, d, X[13], 4, 0x289b7ec6); /* 41 */ | ||
183 | ROUND3(d, a, b, c, X[0], 11, 0xeaa127fa); /* 42 */ | ||
184 | ROUND3(c, d, a, b, X[3], 16, 0xd4ef3085); /* 43 */ | ||
185 | ROUND3(b, c, d, a, X[6], 23, 0x4881d05); /* 44 */ | ||
186 | ROUND3(a, b, c, d, X[9], 4, 0xd9d4d039); /* 45 */ | ||
187 | ROUND3(d, a, b, c, X[12], 11, 0xe6db99e5); /* 46 */ | ||
188 | ROUND3(c, d, a, b, X[15], 16, 0x1fa27cf8); /* 47 */ | ||
189 | ROUND3(b, c, d, a, X[2], 23, 0xc4ac5665); /* 48 */ | ||
190 | |||
191 | /* | ||
192 | * Round 4 | ||
193 | * Let [abcd k s t] denote the operation | ||
194 | * a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s) | ||
195 | */ | ||
196 | ROUND4(a, b, c, d, X[0], 6, 0xf4292244); /* 49 */ | ||
197 | ROUND4(d, a, b, c, X[7], 10, 0x432aff97); /* 50 */ | ||
198 | ROUND4(c, d, a, b, X[14], 15, 0xab9423a7); /* 51 */ | ||
199 | ROUND4(b, c, d, a, X[5], 21, 0xfc93a039); /* 52 */ | ||
200 | ROUND4(a, b, c, d, X[12], 6, 0x655b59c3); /* 53 */ | ||
201 | ROUND4(d, a, b, c, X[3], 10, 0x8f0ccc92); /* 54 */ | ||
202 | ROUND4(c, d, a, b, X[10], 15, 0xffeff47d); /* 55 */ | ||
203 | ROUND4(b, c, d, a, X[1], 21, 0x85845dd1); /* 56 */ | ||
204 | ROUND4(a, b, c, d, X[8], 6, 0x6fa87e4f); /* 57 */ | ||
205 | ROUND4(d, a, b, c, X[15], 10, 0xfe2ce6e0); /* 58 */ | ||
206 | ROUND4(c, d, a, b, X[6], 15, 0xa3014314); /* 59 */ | ||
207 | ROUND4(b, c, d, a, X[13], 21, 0x4e0811a1); /* 60 */ | ||
208 | ROUND4(a, b, c, d, X[4], 6, 0xf7537e82); /* 61 */ | ||
209 | ROUND4(d, a, b, c, X[11], 10, 0xbd3af235); /* 62 */ | ||
210 | ROUND4(c, d, a, b, X[2], 15, 0x2ad7d2bb); /* 63 */ | ||
211 | ROUND4(b, c, d, a, X[9], 21, 0xeb86d391); /* 64 */ | ||
212 | |||
213 | /* Compute the i^th intermediate hash value H^(i) */ | ||
214 | pMD5_CTX->HashValue[0] += a; | ||
215 | pMD5_CTX->HashValue[1] += b; | ||
216 | pMD5_CTX->HashValue[2] += c; | ||
217 | pMD5_CTX->HashValue[3] += d; | ||
218 | |||
219 | NdisZeroMemory(pMD5_CTX->Block, MD5_BLOCK_SIZE); | ||
220 | pMD5_CTX->BlockLen = 0; | ||
221 | } /* End of MD5_Hash */ | ||
222 | |||
223 | /* | ||
224 | ======================================================================== | ||
225 | Routine Description: | ||
226 | The message is appended to block. If block size > 64 bytes, the MD5_Hash | ||
227 | will be called. | ||
228 | |||
229 | Arguments: | ||
230 | pMD5_CTX Pointer to struct rt_md5_ctx_struc | ||
231 | message Message context | ||
232 | messageLen The length of message in bytes | ||
233 | |||
234 | Return Value: | ||
235 | None | ||
236 | |||
237 | Note: | ||
238 | None | ||
239 | ======================================================================== | ||
240 | */ | ||
241 | void MD5_Append(struct rt_md5_ctx_struc *pMD5_CTX, | ||
242 | IN const u8 Message[], u32 MessageLen) | ||
243 | { | ||
244 | u32 appendLen = 0; | ||
245 | u32 diffLen = 0; | ||
246 | |||
247 | while (appendLen != MessageLen) { | ||
248 | diffLen = MessageLen - appendLen; | ||
249 | if ((pMD5_CTX->BlockLen + diffLen) < MD5_BLOCK_SIZE) { | ||
250 | NdisMoveMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen, | ||
251 | Message + appendLen, diffLen); | ||
252 | pMD5_CTX->BlockLen += diffLen; | ||
253 | appendLen += diffLen; | ||
254 | } else { | ||
255 | NdisMoveMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen, | ||
256 | Message + appendLen, | ||
257 | MD5_BLOCK_SIZE - pMD5_CTX->BlockLen); | ||
258 | appendLen += (MD5_BLOCK_SIZE - pMD5_CTX->BlockLen); | ||
259 | pMD5_CTX->BlockLen = MD5_BLOCK_SIZE; | ||
260 | MD5_Hash(pMD5_CTX); | ||
261 | } /* End of if */ | ||
262 | } /* End of while */ | ||
263 | pMD5_CTX->MessageLen += MessageLen; | ||
264 | } /* End of MD5_Append */ | ||
265 | |||
266 | /* | ||
267 | ======================================================================== | ||
268 | Routine Description: | ||
269 | 1. Append bit 1 to end of the message | ||
270 | 2. Append the length of message in rightmost 64 bits | ||
271 | 3. Transform the Hash Value to digest message | ||
272 | |||
273 | Arguments: | ||
274 | pMD5_CTX Pointer to struct rt_md5_ctx_struc | ||
275 | |||
276 | Return Value: | ||
277 | digestMessage Digest message | ||
278 | |||
279 | Note: | ||
280 | None | ||
281 | ======================================================================== | ||
282 | */ | ||
283 | void MD5_End(struct rt_md5_ctx_struc *pMD5_CTX, u8 DigestMessage[]) | ||
284 | { | ||
285 | u32 index; | ||
286 | u64 message_length_bits; | ||
287 | |||
288 | /* append 1 bits to end of the message */ | ||
289 | NdisFillMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen, 1, 0x80); | ||
290 | |||
291 | /* 55 = 64 - 8 - 1: append 1 bit(1 byte) and message length (8 bytes) */ | ||
292 | if (pMD5_CTX->BlockLen > 55) | ||
293 | MD5_Hash(pMD5_CTX); | ||
294 | /* End of if */ | ||
295 | |||
296 | /* Append the length of message in rightmost 64 bits */ | ||
297 | message_length_bits = pMD5_CTX->MessageLen * 8; | ||
298 | message_length_bits = cpu2le64(message_length_bits); | ||
299 | NdisMoveMemory(&pMD5_CTX->Block[56], &message_length_bits, 8); | ||
300 | MD5_Hash(pMD5_CTX); | ||
301 | |||
302 | /* Return message digest, transform the u32 hash value to bytes */ | ||
303 | for (index = 0; index < 4; index++) | ||
304 | pMD5_CTX->HashValue[index] = | ||
305 | cpu2le32(pMD5_CTX->HashValue[index]); | ||
306 | /* End of for */ | ||
307 | NdisMoveMemory(DigestMessage, pMD5_CTX->HashValue, MD5_DIGEST_SIZE); | ||
308 | } /* End of MD5_End */ | ||
309 | |||
310 | /* | ||
311 | ======================================================================== | ||
312 | Routine Description: | ||
313 | MD5 algorithm | ||
314 | |||
315 | Arguments: | ||
316 | message Message context | ||
317 | messageLen The length of message in bytes | ||
318 | |||
319 | Return Value: | ||
320 | digestMessage Digest message | ||
321 | |||
322 | Note: | ||
323 | None | ||
324 | ======================================================================== | ||
325 | */ | ||
326 | void RT_MD5(IN const u8 Message[], | ||
327 | u32 MessageLen, u8 DigestMessage[]) | ||
328 | { | ||
329 | struct rt_md5_ctx_struc md5_ctx; | ||
330 | |||
331 | NdisZeroMemory(&md5_ctx, sizeof(struct rt_md5_ctx_struc)); | ||
332 | MD5_Init(&md5_ctx); | ||
333 | MD5_Append(&md5_ctx, Message, MessageLen); | ||
334 | MD5_End(&md5_ctx, DigestMessage); | ||
335 | } /* End of RT_MD5 */ | ||
336 | |||
337 | #endif /* MD5_SUPPORT */ | ||
338 | |||
339 | /* End of crypt_md5.c */ | ||
diff --git a/drivers/staging/rt2860/common/crypt_sha2.c b/drivers/staging/rt2860/common/crypt_sha2.c deleted file mode 100644 index fa83fb287fe..00000000000 --- a/drivers/staging/rt2860/common/crypt_sha2.c +++ /dev/null | |||
@@ -1,269 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | *************************************************************************/ | ||
26 | |||
27 | #include "../crypt_sha2.h" | ||
28 | |||
29 | /* Basic operations */ | ||
30 | #define SHR(x,n) (x >> n) /* SHR(x)^n, right shift n bits , x is w-bit word, 0 <= n <= w */ | ||
31 | #define ROTR(x,n,w) ((x >> n) | (x << (w - n))) /* ROTR(x)^n, circular right shift n bits , x is w-bit word, 0 <= n <= w */ | ||
32 | #define ROTL(x,n,w) ((x << n) | (x >> (w - n))) /* ROTL(x)^n, circular left shift n bits , x is w-bit word, 0 <= n <= w */ | ||
33 | #define ROTR32(x,n) ROTR(x,n,32) /* 32 bits word */ | ||
34 | #define ROTL32(x,n) ROTL(x,n,32) /* 32 bits word */ | ||
35 | |||
36 | /* Basic functions */ | ||
37 | #define Ch(x,y,z) ((x & y) ^ ((~x) & z)) | ||
38 | #define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z)) | ||
39 | #define Parity(x,y,z) (x ^ y ^ z) | ||
40 | |||
41 | #ifdef SHA1_SUPPORT | ||
42 | /* SHA1 constants */ | ||
43 | #define SHA1_MASK 0x0000000f | ||
44 | static const u32 SHA1_K[4] = { | ||
45 | 0x5a827999UL, 0x6ed9eba1UL, 0x8f1bbcdcUL, 0xca62c1d6UL | ||
46 | }; | ||
47 | |||
48 | static const u32 SHA1_DefaultHashValue[5] = { | ||
49 | 0x67452301UL, 0xefcdab89UL, 0x98badcfeUL, 0x10325476UL, 0xc3d2e1f0UL | ||
50 | }; | ||
51 | |||
52 | /* | ||
53 | ======================================================================== | ||
54 | Routine Description: | ||
55 | Initial struct rt_sha1_ctx | ||
56 | |||
57 | Arguments: | ||
58 | pSHA_CTX Pointer to struct rt_sha1_ctx | ||
59 | |||
60 | Return Value: | ||
61 | None | ||
62 | |||
63 | Note: | ||
64 | None | ||
65 | ======================================================================== | ||
66 | */ | ||
67 | void RT_SHA1_Init(struct rt_sha1_ctx *pSHA_CTX) | ||
68 | { | ||
69 | NdisMoveMemory(pSHA_CTX->HashValue, SHA1_DefaultHashValue, | ||
70 | sizeof(SHA1_DefaultHashValue)); | ||
71 | NdisZeroMemory(pSHA_CTX->Block, SHA1_BLOCK_SIZE); | ||
72 | pSHA_CTX->MessageLen = 0; | ||
73 | pSHA_CTX->BlockLen = 0; | ||
74 | } /* End of RT_SHA1_Init */ | ||
75 | |||
76 | /* | ||
77 | ======================================================================== | ||
78 | Routine Description: | ||
79 | SHA1 computation for one block (512 bits) | ||
80 | |||
81 | Arguments: | ||
82 | pSHA_CTX Pointer to struct rt_sha1_ctx | ||
83 | |||
84 | Return Value: | ||
85 | None | ||
86 | |||
87 | Note: | ||
88 | None | ||
89 | ======================================================================== | ||
90 | */ | ||
91 | void SHA1_Hash(struct rt_sha1_ctx *pSHA_CTX) | ||
92 | { | ||
93 | u32 W_i, t, s; | ||
94 | u32 W[16]; | ||
95 | u32 a, b, c, d, e, T, f_t = 0; | ||
96 | |||
97 | /* Prepare the message schedule, {W_i}, 0 < t < 15 */ | ||
98 | NdisMoveMemory(W, pSHA_CTX->Block, SHA1_BLOCK_SIZE); | ||
99 | for (W_i = 0; W_i < 16; W_i++) | ||
100 | W[W_i] = cpu2be32(W[W_i]); /* Endian Swap */ | ||
101 | /* End of for */ | ||
102 | |||
103 | /* SHA256 hash computation */ | ||
104 | /* Initialize the working variables */ | ||
105 | a = pSHA_CTX->HashValue[0]; | ||
106 | b = pSHA_CTX->HashValue[1]; | ||
107 | c = pSHA_CTX->HashValue[2]; | ||
108 | d = pSHA_CTX->HashValue[3]; | ||
109 | e = pSHA_CTX->HashValue[4]; | ||
110 | |||
111 | /* 80 rounds */ | ||
112 | for (t = 0; t < 80; t++) { | ||
113 | s = t & SHA1_MASK; | ||
114 | if (t > 15) { /* Prepare the message schedule, {W_i}, 16 < t < 79 */ | ||
115 | W[s] = | ||
116 | (W[(s + 13) & SHA1_MASK]) ^ (W[(s + 8) & SHA1_MASK]) | ||
117 | ^ (W[(s + 2) & SHA1_MASK]) ^ W[s]; | ||
118 | W[s] = ROTL32(W[s], 1); | ||
119 | } /* End of if */ | ||
120 | switch (t / 20) { | ||
121 | case 0: | ||
122 | f_t = Ch(b, c, d); | ||
123 | break; | ||
124 | case 1: | ||
125 | f_t = Parity(b, c, d); | ||
126 | break; | ||
127 | case 2: | ||
128 | f_t = Maj(b, c, d); | ||
129 | break; | ||
130 | case 3: | ||
131 | f_t = Parity(b, c, d); | ||
132 | break; | ||
133 | } /* End of switch */ | ||
134 | T = ROTL32(a, 5) + f_t + e + SHA1_K[t / 20] + W[s]; | ||
135 | e = d; | ||
136 | d = c; | ||
137 | c = ROTL32(b, 30); | ||
138 | b = a; | ||
139 | a = T; | ||
140 | } /* End of for */ | ||
141 | |||
142 | /* Compute the i^th intermediate hash value H^(i) */ | ||
143 | pSHA_CTX->HashValue[0] += a; | ||
144 | pSHA_CTX->HashValue[1] += b; | ||
145 | pSHA_CTX->HashValue[2] += c; | ||
146 | pSHA_CTX->HashValue[3] += d; | ||
147 | pSHA_CTX->HashValue[4] += e; | ||
148 | |||
149 | NdisZeroMemory(pSHA_CTX->Block, SHA1_BLOCK_SIZE); | ||
150 | pSHA_CTX->BlockLen = 0; | ||
151 | } /* End of SHA1_Hash */ | ||
152 | |||
153 | /* | ||
154 | ======================================================================== | ||
155 | Routine Description: | ||
156 | The message is appended to block. If block size > 64 bytes, the SHA1_Hash | ||
157 | will be called. | ||
158 | |||
159 | Arguments: | ||
160 | pSHA_CTX Pointer to struct rt_sha1_ctx | ||
161 | message Message context | ||
162 | messageLen The length of message in bytes | ||
163 | |||
164 | Return Value: | ||
165 | None | ||
166 | |||
167 | Note: | ||
168 | None | ||
169 | ======================================================================== | ||
170 | */ | ||
171 | void SHA1_Append(struct rt_sha1_ctx *pSHA_CTX, | ||
172 | IN const u8 Message[], u32 MessageLen) | ||
173 | { | ||
174 | u32 appendLen = 0; | ||
175 | u32 diffLen = 0; | ||
176 | |||
177 | while (appendLen != MessageLen) { | ||
178 | diffLen = MessageLen - appendLen; | ||
179 | if ((pSHA_CTX->BlockLen + diffLen) < SHA1_BLOCK_SIZE) { | ||
180 | NdisMoveMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen, | ||
181 | Message + appendLen, diffLen); | ||
182 | pSHA_CTX->BlockLen += diffLen; | ||
183 | appendLen += diffLen; | ||
184 | } else { | ||
185 | NdisMoveMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen, | ||
186 | Message + appendLen, | ||
187 | SHA1_BLOCK_SIZE - pSHA_CTX->BlockLen); | ||
188 | appendLen += (SHA1_BLOCK_SIZE - pSHA_CTX->BlockLen); | ||
189 | pSHA_CTX->BlockLen = SHA1_BLOCK_SIZE; | ||
190 | SHA1_Hash(pSHA_CTX); | ||
191 | } /* End of if */ | ||
192 | } /* End of while */ | ||
193 | pSHA_CTX->MessageLen += MessageLen; | ||
194 | } /* End of SHA1_Append */ | ||
195 | |||
196 | /* | ||
197 | ======================================================================== | ||
198 | Routine Description: | ||
199 | 1. Append bit 1 to end of the message | ||
200 | 2. Append the length of message in rightmost 64 bits | ||
201 | 3. Transform the Hash Value to digest message | ||
202 | |||
203 | Arguments: | ||
204 | pSHA_CTX Pointer to struct rt_sha1_ctx | ||
205 | |||
206 | Return Value: | ||
207 | digestMessage Digest message | ||
208 | |||
209 | Note: | ||
210 | None | ||
211 | ======================================================================== | ||
212 | */ | ||
213 | void SHA1_End(struct rt_sha1_ctx *pSHA_CTX, u8 DigestMessage[]) | ||
214 | { | ||
215 | u32 index; | ||
216 | u64 message_length_bits; | ||
217 | |||
218 | /* Append bit 1 to end of the message */ | ||
219 | NdisFillMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen, 1, 0x80); | ||
220 | |||
221 | /* 55 = 64 - 8 - 1: append 1 bit(1 byte) and message length (8 bytes) */ | ||
222 | if (pSHA_CTX->BlockLen > 55) | ||
223 | SHA1_Hash(pSHA_CTX); | ||
224 | /* End of if */ | ||
225 | |||
226 | /* Append the length of message in rightmost 64 bits */ | ||
227 | message_length_bits = pSHA_CTX->MessageLen * 8; | ||
228 | message_length_bits = cpu2be64(message_length_bits); | ||
229 | NdisMoveMemory(&pSHA_CTX->Block[56], &message_length_bits, 8); | ||
230 | SHA1_Hash(pSHA_CTX); | ||
231 | |||
232 | /* Return message digest, transform the u32 hash value to bytes */ | ||
233 | for (index = 0; index < 5; index++) | ||
234 | pSHA_CTX->HashValue[index] = | ||
235 | cpu2be32(pSHA_CTX->HashValue[index]); | ||
236 | /* End of for */ | ||
237 | NdisMoveMemory(DigestMessage, pSHA_CTX->HashValue, SHA1_DIGEST_SIZE); | ||
238 | } /* End of SHA1_End */ | ||
239 | |||
240 | /* | ||
241 | ======================================================================== | ||
242 | Routine Description: | ||
243 | SHA1 algorithm | ||
244 | |||
245 | Arguments: | ||
246 | message Message context | ||
247 | messageLen The length of message in bytes | ||
248 | |||
249 | Return Value: | ||
250 | digestMessage Digest message | ||
251 | |||
252 | Note: | ||
253 | None | ||
254 | ======================================================================== | ||
255 | */ | ||
256 | void RT_SHA1(IN const u8 Message[], | ||
257 | u32 MessageLen, u8 DigestMessage[]) | ||
258 | { | ||
259 | |||
260 | struct rt_sha1_ctx sha_ctx; | ||
261 | |||
262 | NdisZeroMemory(&sha_ctx, sizeof(struct rt_sha1_ctx)); | ||
263 | RT_SHA1_Init(&sha_ctx); | ||
264 | SHA1_Append(&sha_ctx, Message, MessageLen); | ||
265 | SHA1_End(&sha_ctx, DigestMessage); | ||
266 | } /* End of RT_SHA1 */ | ||
267 | #endif /* SHA1_SUPPORT */ | ||
268 | |||
269 | /* End of crypt_sha2.c */ | ||
diff --git a/drivers/staging/rt2860/common/dfs.c b/drivers/staging/rt2860/common/dfs.c deleted file mode 100644 index 71cbb266524..00000000000 --- a/drivers/staging/rt2860/common/dfs.c +++ /dev/null | |||
@@ -1,68 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | |||
27 | Module Name: | ||
28 | ap_dfs.c | ||
29 | |||
30 | Abstract: | ||
31 | Support DFS function. | ||
32 | |||
33 | Revision History: | ||
34 | Who When What | ||
35 | -------- ---------- ---------------------------------------------- | ||
36 | */ | ||
37 | |||
38 | #include "../rt_config.h" | ||
39 | |||
40 | /* | ||
41 | ======================================================================== | ||
42 | |||
43 | Routine Description: | ||
44 | Radar channel check routine | ||
45 | |||
46 | Arguments: | ||
47 | pAd Pointer to our adapter | ||
48 | |||
49 | Return Value: | ||
50 | TRUE need to do radar detect | ||
51 | FALSE need not to do radar detect | ||
52 | |||
53 | ======================================================================== | ||
54 | */ | ||
55 | BOOLEAN RadarChannelCheck(struct rt_rtmp_adapter *pAd, u8 Ch) | ||
56 | { | ||
57 | int i; | ||
58 | BOOLEAN result = FALSE; | ||
59 | |||
60 | for (i = 0; i < pAd->ChannelListNum; i++) { | ||
61 | if (Ch == pAd->ChannelList[i].Channel) { | ||
62 | result = pAd->ChannelList[i].DfsReq; | ||
63 | break; | ||
64 | } | ||
65 | } | ||
66 | |||
67 | return result; | ||
68 | } | ||
diff --git a/drivers/staging/rt2860/common/ee_efuse.c b/drivers/staging/rt2860/common/ee_efuse.c deleted file mode 100644 index fed0ba45227..00000000000 --- a/drivers/staging/rt2860/common/ee_efuse.c +++ /dev/null | |||
@@ -1,351 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | |||
27 | Module Name: | ||
28 | ee_efuse.c | ||
29 | |||
30 | Abstract: | ||
31 | Miniport generic portion header file | ||
32 | |||
33 | Revision History: | ||
34 | Who When What | ||
35 | -------- ---------- ---------------------------------------------- | ||
36 | */ | ||
37 | |||
38 | #include "../rt_config.h" | ||
39 | |||
40 | #define EFUSE_USAGE_MAP_START 0x2d0 | ||
41 | #define EFUSE_USAGE_MAP_END 0x2fc | ||
42 | #define EFUSE_USAGE_MAP_SIZE 45 | ||
43 | |||
44 | #define EFUSE_EEPROM_DEFULT_FILE "RT30xxEEPROM.bin" | ||
45 | #define MAX_EEPROM_BIN_FILE_SIZE 1024 | ||
46 | |||
47 | #define EFUSE_TAG 0x2fe | ||
48 | |||
49 | typedef union _EFUSE_CTRL_STRUC { | ||
50 | struct { | ||
51 | u32 EFSROM_AOUT:6; | ||
52 | u32 EFSROM_MODE:2; | ||
53 | u32 EFSROM_LDO_OFF_TIME:6; | ||
54 | u32 EFSROM_LDO_ON_TIME:2; | ||
55 | u32 EFSROM_AIN:10; | ||
56 | u32 RESERVED:4; | ||
57 | u32 EFSROM_KICK:1; | ||
58 | u32 SEL_EFUSE:1; | ||
59 | } field; | ||
60 | u32 word; | ||
61 | } EFUSE_CTRL_STRUC, *PEFUSE_CTRL_STRUC; | ||
62 | |||
63 | /* | ||
64 | ======================================================================== | ||
65 | |||
66 | Routine Description: | ||
67 | |||
68 | Arguments: | ||
69 | |||
70 | Return Value: | ||
71 | |||
72 | Note: | ||
73 | |||
74 | ======================================================================== | ||
75 | */ | ||
76 | u8 eFuseReadRegisters(struct rt_rtmp_adapter *pAd, | ||
77 | u16 Offset, u16 Length, u16 * pData) | ||
78 | { | ||
79 | EFUSE_CTRL_STRUC eFuseCtrlStruc; | ||
80 | int i; | ||
81 | u16 efuseDataOffset; | ||
82 | u32 data; | ||
83 | |||
84 | RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word); | ||
85 | |||
86 | /*Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment. */ | ||
87 | /*Use the eeprom logical address and covert to address to block number */ | ||
88 | eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; | ||
89 | |||
90 | /*Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 0. */ | ||
91 | eFuseCtrlStruc.field.EFSROM_MODE = 0; | ||
92 | |||
93 | /*Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure. */ | ||
94 | eFuseCtrlStruc.field.EFSROM_KICK = 1; | ||
95 | |||
96 | NdisMoveMemory(&data, &eFuseCtrlStruc, 4); | ||
97 | RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data); | ||
98 | |||
99 | /*Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. */ | ||
100 | i = 0; | ||
101 | while (i < 500) { | ||
102 | /*rtmp.HwMemoryReadDword(EFUSE_CTRL, (DWORD *) &eFuseCtrlStruc, 4); */ | ||
103 | RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word); | ||
104 | if (eFuseCtrlStruc.field.EFSROM_KICK == 0) { | ||
105 | break; | ||
106 | } | ||
107 | RTMPusecDelay(2); | ||
108 | i++; | ||
109 | } | ||
110 | |||
111 | /*if EFSROM_AOUT is not found in physical address, write 0xffff */ | ||
112 | if (eFuseCtrlStruc.field.EFSROM_AOUT == 0x3f) { | ||
113 | for (i = 0; i < Length / 2; i++) | ||
114 | *(pData + 2 * i) = 0xffff; | ||
115 | } else { | ||
116 | /*Step4. Read 16-byte of data from EFUSE_DATA0-3 (0x590-0x59C) */ | ||
117 | efuseDataOffset = EFUSE_DATA3 - (Offset & 0xC); | ||
118 | /*data hold 4 bytes data. */ | ||
119 | /*In RTMP_IO_READ32 will automatically execute 32-bytes swapping */ | ||
120 | RTMP_IO_READ32(pAd, efuseDataOffset, &data); | ||
121 | /*Decide the upper 2 bytes or the bottom 2 bytes. */ | ||
122 | /* Little-endian S | S Big-endian */ | ||
123 | /* addr 3 2 1 0 | 0 1 2 3 */ | ||
124 | /* Ori-V D C B A | A B C D */ | ||
125 | /*After swapping */ | ||
126 | /* D C B A | D C B A */ | ||
127 | /*Return 2-bytes */ | ||
128 | /*The return byte statrs from S. Therefore, the little-endian will return BA, the Big-endian will return DC. */ | ||
129 | /*For returning the bottom 2 bytes, the Big-endian should shift right 2-bytes. */ | ||
130 | data = data >> (8 * (Offset & 0x3)); | ||
131 | |||
132 | NdisMoveMemory(pData, &data, Length); | ||
133 | } | ||
134 | |||
135 | return (u8)eFuseCtrlStruc.field.EFSROM_AOUT; | ||
136 | |||
137 | } | ||
138 | |||
139 | /* | ||
140 | ======================================================================== | ||
141 | |||
142 | Routine Description: | ||
143 | |||
144 | Arguments: | ||
145 | |||
146 | Return Value: | ||
147 | |||
148 | Note: | ||
149 | |||
150 | ======================================================================== | ||
151 | */ | ||
152 | void eFusePhysicalReadRegisters(struct rt_rtmp_adapter *pAd, | ||
153 | u16 Offset, | ||
154 | u16 Length, u16 * pData) | ||
155 | { | ||
156 | EFUSE_CTRL_STRUC eFuseCtrlStruc; | ||
157 | int i; | ||
158 | u16 efuseDataOffset; | ||
159 | u32 data; | ||
160 | |||
161 | RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word); | ||
162 | |||
163 | /*Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment. */ | ||
164 | eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; | ||
165 | |||
166 | /*Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 1. */ | ||
167 | /*Read in physical view */ | ||
168 | eFuseCtrlStruc.field.EFSROM_MODE = 1; | ||
169 | |||
170 | /*Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure. */ | ||
171 | eFuseCtrlStruc.field.EFSROM_KICK = 1; | ||
172 | |||
173 | NdisMoveMemory(&data, &eFuseCtrlStruc, 4); | ||
174 | RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data); | ||
175 | |||
176 | /*Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. */ | ||
177 | i = 0; | ||
178 | while (i < 500) { | ||
179 | RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word); | ||
180 | if (eFuseCtrlStruc.field.EFSROM_KICK == 0) | ||
181 | break; | ||
182 | RTMPusecDelay(2); | ||
183 | i++; | ||
184 | } | ||
185 | |||
186 | /*Step4. Read 16-byte of data from EFUSE_DATA0-3 (0x59C-0x590) */ | ||
187 | /*Because the size of each EFUSE_DATA is 4 Bytes, the size of address of each is 2 bits. */ | ||
188 | /*The previous 2 bits is the EFUSE_DATA number, the last 2 bits is used to decide which bytes */ | ||
189 | /*Decide which EFUSE_DATA to read */ | ||
190 | /*590:F E D C */ | ||
191 | /*594:B A 9 8 */ | ||
192 | /*598:7 6 5 4 */ | ||
193 | /*59C:3 2 1 0 */ | ||
194 | efuseDataOffset = EFUSE_DATA3 - (Offset & 0xC); | ||
195 | |||
196 | RTMP_IO_READ32(pAd, efuseDataOffset, &data); | ||
197 | |||
198 | data = data >> (8 * (Offset & 0x3)); | ||
199 | |||
200 | NdisMoveMemory(pData, &data, Length); | ||
201 | |||
202 | } | ||
203 | |||
204 | /* | ||
205 | ======================================================================== | ||
206 | |||
207 | Routine Description: | ||
208 | |||
209 | Arguments: | ||
210 | |||
211 | Return Value: | ||
212 | |||
213 | Note: | ||
214 | |||
215 | ======================================================================== | ||
216 | */ | ||
217 | static void eFuseReadPhysical(struct rt_rtmp_adapter *pAd, | ||
218 | u16 *lpInBuffer, | ||
219 | unsigned long nInBufferSize, | ||
220 | u16 *lpOutBuffer, unsigned long nOutBufferSize) | ||
221 | { | ||
222 | u16 *pInBuf = (u16 *) lpInBuffer; | ||
223 | u16 *pOutBuf = (u16 *) lpOutBuffer; | ||
224 | |||
225 | u16 Offset = pInBuf[0]; /*addr */ | ||
226 | u16 Length = pInBuf[1]; /*length */ | ||
227 | int i; | ||
228 | |||
229 | for (i = 0; i < Length; i += 2) { | ||
230 | eFusePhysicalReadRegisters(pAd, Offset + i, 2, &pOutBuf[i / 2]); | ||
231 | } | ||
232 | } | ||
233 | |||
234 | /* | ||
235 | ======================================================================== | ||
236 | |||
237 | Routine Description: | ||
238 | |||
239 | Arguments: | ||
240 | |||
241 | Return Value: | ||
242 | |||
243 | Note: | ||
244 | |||
245 | ======================================================================== | ||
246 | */ | ||
247 | int set_eFuseGetFreeBlockCount_Proc(struct rt_rtmp_adapter *pAd, char *arg) | ||
248 | { | ||
249 | u16 i; | ||
250 | u16 LogicalAddress; | ||
251 | u16 efusefreenum = 0; | ||
252 | if (!pAd->bUseEfuse) | ||
253 | return FALSE; | ||
254 | for (i = EFUSE_USAGE_MAP_START; i <= EFUSE_USAGE_MAP_END; i += 2) { | ||
255 | eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); | ||
256 | if ((LogicalAddress & 0xff) == 0) { | ||
257 | efusefreenum = (u8)(EFUSE_USAGE_MAP_END - i + 1); | ||
258 | break; | ||
259 | } else if (((LogicalAddress >> 8) & 0xff) == 0) { | ||
260 | efusefreenum = (u8)(EFUSE_USAGE_MAP_END - i); | ||
261 | break; | ||
262 | } | ||
263 | |||
264 | if (i == EFUSE_USAGE_MAP_END) | ||
265 | efusefreenum = 0; | ||
266 | } | ||
267 | printk(KERN_DEBUG "efuseFreeNumber is %d\n", efusefreenum); | ||
268 | return TRUE; | ||
269 | } | ||
270 | |||
271 | int set_eFusedump_Proc(struct rt_rtmp_adapter *pAd, char *arg) | ||
272 | { | ||
273 | u16 InBuf[3]; | ||
274 | int i = 0; | ||
275 | if (!pAd->bUseEfuse) | ||
276 | return FALSE; | ||
277 | |||
278 | printk(KERN_DEBUG "Block 0: "); | ||
279 | |||
280 | for (i = 0; i < EFUSE_USAGE_MAP_END / 2; i++) { | ||
281 | InBuf[0] = 2 * i; | ||
282 | InBuf[1] = 2; | ||
283 | InBuf[2] = 0x0; | ||
284 | |||
285 | eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); | ||
286 | if (i && i % 4 == 0) { | ||
287 | printk(KERN_CONT "\n"); | ||
288 | printk(KERN_DEBUG "Block %x:", i / 8); | ||
289 | } | ||
290 | printk(KERN_CONT "%04x ", InBuf[2]); | ||
291 | } | ||
292 | printk(KERN_CONT "\n"); | ||
293 | |||
294 | return TRUE; | ||
295 | } | ||
296 | |||
297 | int rtmp_ee_efuse_read16(struct rt_rtmp_adapter *pAd, | ||
298 | u16 Offset, u16 * pValue) | ||
299 | { | ||
300 | eFuseReadRegisters(pAd, Offset, 2, pValue); | ||
301 | return (*pValue); | ||
302 | } | ||
303 | |||
304 | int RtmpEfuseSupportCheck(struct rt_rtmp_adapter *pAd) | ||
305 | { | ||
306 | u16 value; | ||
307 | |||
308 | if (IS_RT30xx(pAd)) { | ||
309 | eFusePhysicalReadRegisters(pAd, EFUSE_TAG, 2, &value); | ||
310 | pAd->EFuseTag = (value & 0xff); | ||
311 | } | ||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | void eFuseGetFreeBlockCount(struct rt_rtmp_adapter *pAd, u32 *EfuseFreeBlock) | ||
316 | { | ||
317 | u16 i; | ||
318 | u16 LogicalAddress; | ||
319 | if (!pAd->bUseEfuse) { | ||
320 | DBGPRINT(RT_DEBUG_TRACE, | ||
321 | ("eFuseGetFreeBlockCount Only supports efuse Mode\n")); | ||
322 | return; | ||
323 | } | ||
324 | for (i = EFUSE_USAGE_MAP_START; i <= EFUSE_USAGE_MAP_END; i += 2) { | ||
325 | eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); | ||
326 | if ((LogicalAddress & 0xff) == 0) { | ||
327 | *EfuseFreeBlock = (u8)(EFUSE_USAGE_MAP_END - i + 1); | ||
328 | break; | ||
329 | } else if (((LogicalAddress >> 8) & 0xff) == 0) { | ||
330 | *EfuseFreeBlock = (u8)(EFUSE_USAGE_MAP_END - i); | ||
331 | break; | ||
332 | } | ||
333 | |||
334 | if (i == EFUSE_USAGE_MAP_END) | ||
335 | *EfuseFreeBlock = 0; | ||
336 | } | ||
337 | DBGPRINT(RT_DEBUG_TRACE, | ||
338 | ("eFuseGetFreeBlockCount is 0x%x\n", *EfuseFreeBlock)); | ||
339 | } | ||
340 | |||
341 | int eFuse_init(struct rt_rtmp_adapter *pAd) | ||
342 | { | ||
343 | u32 EfuseFreeBlock = 0; | ||
344 | DBGPRINT(RT_DEBUG_ERROR, | ||
345 | ("NVM is Efuse and its size =%x[%x-%x] \n", | ||
346 | EFUSE_USAGE_MAP_SIZE, EFUSE_USAGE_MAP_START, | ||
347 | EFUSE_USAGE_MAP_END)); | ||
348 | eFuseGetFreeBlockCount(pAd, &EfuseFreeBlock); | ||
349 | |||
350 | return 0; | ||
351 | } | ||
diff --git a/drivers/staging/rt2860/common/ee_prom.c b/drivers/staging/rt2860/common/ee_prom.c deleted file mode 100644 index 2083740a844..00000000000 --- a/drivers/staging/rt2860/common/ee_prom.c +++ /dev/null | |||
@@ -1,197 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | |||
27 | Module Name: | ||
28 | ee_prom.c | ||
29 | |||
30 | Abstract: | ||
31 | Miniport generic portion header file | ||
32 | |||
33 | Revision History: | ||
34 | Who When What | ||
35 | -------- ---------- ---------------------------------------------- | ||
36 | */ | ||
37 | |||
38 | #include "../rt_config.h" | ||
39 | |||
40 | /* IRQL = PASSIVE_LEVEL */ | ||
41 | static inline void RaiseClock(struct rt_rtmp_adapter *pAd, u32 * x) | ||
42 | { | ||
43 | *x = *x | EESK; | ||
44 | RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x); | ||
45 | RTMPusecDelay(1); /* Max frequency = 1MHz in Spec. definition */ | ||
46 | } | ||
47 | |||
48 | /* IRQL = PASSIVE_LEVEL */ | ||
49 | static inline void LowerClock(struct rt_rtmp_adapter *pAd, u32 * x) | ||
50 | { | ||
51 | *x = *x & ~EESK; | ||
52 | RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x); | ||
53 | RTMPusecDelay(1); | ||
54 | } | ||
55 | |||
56 | /* IRQL = PASSIVE_LEVEL */ | ||
57 | static inline u16 ShiftInBits(struct rt_rtmp_adapter *pAd) | ||
58 | { | ||
59 | u32 x, i; | ||
60 | u16 data = 0; | ||
61 | |||
62 | RTMP_IO_READ32(pAd, E2PROM_CSR, &x); | ||
63 | |||
64 | x &= ~(EEDO | EEDI); | ||
65 | |||
66 | for (i = 0; i < 16; i++) { | ||
67 | data = data << 1; | ||
68 | RaiseClock(pAd, &x); | ||
69 | |||
70 | RTMP_IO_READ32(pAd, E2PROM_CSR, &x); | ||
71 | LowerClock(pAd, &x); /*prevent read failed */ | ||
72 | |||
73 | x &= ~(EEDI); | ||
74 | if (x & EEDO) | ||
75 | data |= 1; | ||
76 | } | ||
77 | |||
78 | return data; | ||
79 | } | ||
80 | |||
81 | /* IRQL = PASSIVE_LEVEL */ | ||
82 | static inline void ShiftOutBits(struct rt_rtmp_adapter *pAd, | ||
83 | u16 data, u16 count) | ||
84 | { | ||
85 | u32 x, mask; | ||
86 | |||
87 | mask = 0x01 << (count - 1); | ||
88 | RTMP_IO_READ32(pAd, E2PROM_CSR, &x); | ||
89 | |||
90 | x &= ~(EEDO | EEDI); | ||
91 | |||
92 | do { | ||
93 | x &= ~EEDI; | ||
94 | if (data & mask) | ||
95 | x |= EEDI; | ||
96 | |||
97 | RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); | ||
98 | |||
99 | RaiseClock(pAd, &x); | ||
100 | LowerClock(pAd, &x); | ||
101 | |||
102 | mask = mask >> 1; | ||
103 | } while (mask); | ||
104 | |||
105 | x &= ~EEDI; | ||
106 | RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); | ||
107 | } | ||
108 | |||
109 | /* IRQL = PASSIVE_LEVEL */ | ||
110 | static inline void EEpromCleanup(struct rt_rtmp_adapter *pAd) | ||
111 | { | ||
112 | u32 x; | ||
113 | |||
114 | RTMP_IO_READ32(pAd, E2PROM_CSR, &x); | ||
115 | |||
116 | x &= ~(EECS | EEDI); | ||
117 | RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); | ||
118 | |||
119 | RaiseClock(pAd, &x); | ||
120 | LowerClock(pAd, &x); | ||
121 | } | ||
122 | |||
123 | static inline void EWEN(struct rt_rtmp_adapter *pAd) | ||
124 | { | ||
125 | u32 x; | ||
126 | |||
127 | /* reset bits and set EECS */ | ||
128 | RTMP_IO_READ32(pAd, E2PROM_CSR, &x); | ||
129 | x &= ~(EEDI | EEDO | EESK); | ||
130 | x |= EECS; | ||
131 | RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); | ||
132 | |||
133 | /* kick a pulse */ | ||
134 | RaiseClock(pAd, &x); | ||
135 | LowerClock(pAd, &x); | ||
136 | |||
137 | /* output the read_opcode and six pulse in that order */ | ||
138 | ShiftOutBits(pAd, EEPROM_EWEN_OPCODE, 5); | ||
139 | ShiftOutBits(pAd, 0, 6); | ||
140 | |||
141 | EEpromCleanup(pAd); | ||
142 | } | ||
143 | |||
144 | static inline void EWDS(struct rt_rtmp_adapter *pAd) | ||
145 | { | ||
146 | u32 x; | ||
147 | |||
148 | /* reset bits and set EECS */ | ||
149 | RTMP_IO_READ32(pAd, E2PROM_CSR, &x); | ||
150 | x &= ~(EEDI | EEDO | EESK); | ||
151 | x |= EECS; | ||
152 | RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); | ||
153 | |||
154 | /* kick a pulse */ | ||
155 | RaiseClock(pAd, &x); | ||
156 | LowerClock(pAd, &x); | ||
157 | |||
158 | /* output the read_opcode and six pulse in that order */ | ||
159 | ShiftOutBits(pAd, EEPROM_EWDS_OPCODE, 5); | ||
160 | ShiftOutBits(pAd, 0, 6); | ||
161 | |||
162 | EEpromCleanup(pAd); | ||
163 | } | ||
164 | |||
165 | /* IRQL = PASSIVE_LEVEL */ | ||
166 | int rtmp_ee_prom_read16(struct rt_rtmp_adapter *pAd, | ||
167 | u16 Offset, u16 * pValue) | ||
168 | { | ||
169 | u32 x; | ||
170 | u16 data; | ||
171 | |||
172 | Offset /= 2; | ||
173 | /* reset bits and set EECS */ | ||
174 | RTMP_IO_READ32(pAd, E2PROM_CSR, &x); | ||
175 | x &= ~(EEDI | EEDO | EESK); | ||
176 | x |= EECS; | ||
177 | RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); | ||
178 | |||
179 | /* patch can not access e-Fuse issue */ | ||
180 | if (!(IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))) { | ||
181 | /* kick a pulse */ | ||
182 | RaiseClock(pAd, &x); | ||
183 | LowerClock(pAd, &x); | ||
184 | } | ||
185 | /* output the read_opcode and register number in that order */ | ||
186 | ShiftOutBits(pAd, EEPROM_READ_OPCODE, 3); | ||
187 | ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum); | ||
188 | |||
189 | /* Now read the data (16 bits) in from the selected EEPROM word */ | ||
190 | data = ShiftInBits(pAd); | ||
191 | |||
192 | EEpromCleanup(pAd); | ||
193 | |||
194 | *pValue = data; | ||
195 | |||
196 | return NDIS_STATUS_SUCCESS; | ||
197 | } | ||
diff --git a/drivers/staging/rt2860/common/eeprom.c b/drivers/staging/rt2860/common/eeprom.c deleted file mode 100644 index 94670076d32..00000000000 --- a/drivers/staging/rt2860/common/eeprom.c +++ /dev/null | |||
@@ -1,91 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | |||
27 | Module Name: | ||
28 | eeprom.c | ||
29 | |||
30 | Abstract: | ||
31 | |||
32 | Revision History: | ||
33 | Who When What | ||
34 | -------- ---------- ---------------------------------------------- | ||
35 | Name Date Modification logs | ||
36 | */ | ||
37 | #include "../rt_config.h" | ||
38 | |||
39 | int RtmpChipOpsEepromHook(struct rt_rtmp_adapter *pAd, int infType) | ||
40 | { | ||
41 | struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps; | ||
42 | #ifdef RT30xx | ||
43 | #ifdef RTMP_EFUSE_SUPPORT | ||
44 | u32 eFuseCtrl, MacCsr0; | ||
45 | int index; | ||
46 | |||
47 | index = 0; | ||
48 | do { | ||
49 | RTMP_IO_READ32(pAd, MAC_CSR0, &MacCsr0); | ||
50 | pAd->MACVersion = MacCsr0; | ||
51 | |||
52 | if ((pAd->MACVersion != 0x00) | ||
53 | && (pAd->MACVersion != 0xFFFFFFFF)) | ||
54 | break; | ||
55 | |||
56 | RTMPusecDelay(10); | ||
57 | } while (index++ < 100); | ||
58 | |||
59 | pAd->bUseEfuse = FALSE; | ||
60 | RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrl); | ||
61 | pAd->bUseEfuse = ((eFuseCtrl & 0x80000000) == 0x80000000) ? 1 : 0; | ||
62 | if (pAd->bUseEfuse) { | ||
63 | pChipOps->eeinit = eFuse_init; | ||
64 | pChipOps->eeread = rtmp_ee_efuse_read16; | ||
65 | return 0; | ||
66 | } else | ||
67 | DBGPRINT(RT_DEBUG_TRACE, ("NVM is EEPROM\n")); | ||
68 | #endif /* RTMP_EFUSE_SUPPORT // */ | ||
69 | #endif /* RT30xx // */ | ||
70 | |||
71 | switch (infType) { | ||
72 | #ifdef RTMP_PCI_SUPPORT | ||
73 | case RTMP_DEV_INF_PCI: | ||
74 | pChipOps->eeinit = NULL; | ||
75 | pChipOps->eeread = rtmp_ee_prom_read16; | ||
76 | break; | ||
77 | #endif /* RTMP_PCI_SUPPORT // */ | ||
78 | #ifdef RTMP_USB_SUPPORT | ||
79 | case RTMP_DEV_INF_USB: | ||
80 | pChipOps->eeinit = NULL; | ||
81 | pChipOps->eeread = RTUSBReadEEPROM16; | ||
82 | break; | ||
83 | #endif /* RTMP_USB_SUPPORT // */ | ||
84 | |||
85 | default: | ||
86 | DBGPRINT(RT_DEBUG_ERROR, ("RtmpChipOpsEepromHook() failed!\n")); | ||
87 | break; | ||
88 | } | ||
89 | |||
90 | return 0; | ||
91 | } | ||
diff --git a/drivers/staging/rt2860/common/mlme.c b/drivers/staging/rt2860/common/mlme.c deleted file mode 100644 index e48eac0f3a2..00000000000 --- a/drivers/staging/rt2860/common/mlme.c +++ /dev/null | |||
@@ -1,6068 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | |||
27 | Module Name: | ||
28 | mlme.c | ||
29 | |||
30 | Abstract: | ||
31 | |||
32 | Revision History: | ||
33 | Who When What | ||
34 | -------- ---------- ---------------------------------------------- | ||
35 | John Chang 2004-08-25 Modify from RT2500 code base | ||
36 | John Chang 2004-09-06 modified for RT2600 | ||
37 | */ | ||
38 | |||
39 | #include "../rt_config.h" | ||
40 | #include <stdarg.h> | ||
41 | #include <linux/kernel.h> | ||
42 | |||
43 | u8 CISCO_OUI[] = { 0x00, 0x40, 0x96 }; | ||
44 | |||
45 | u8 WPA_OUI[] = { 0x00, 0x50, 0xf2, 0x01 }; | ||
46 | u8 RSN_OUI[] = { 0x00, 0x0f, 0xac }; | ||
47 | u8 WME_INFO_ELEM[] = { 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01 }; | ||
48 | u8 WME_PARM_ELEM[] = { 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01 }; | ||
49 | u8 Ccx2QosInfo[] = { 0x00, 0x40, 0x96, 0x04 }; | ||
50 | u8 RALINK_OUI[] = { 0x00, 0x0c, 0x43 }; | ||
51 | u8 BROADCOM_OUI[] = { 0x00, 0x90, 0x4c }; | ||
52 | u8 WPS_OUI[] = { 0x00, 0x50, 0xf2, 0x04 }; | ||
53 | u8 PRE_N_HT_OUI[] = { 0x00, 0x90, 0x4c }; | ||
54 | |||
55 | u8 RateSwitchTable[] = { | ||
56 | /* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ | ||
57 | 0x11, 0x00, 0, 0, 0, /* Initial used item after association */ | ||
58 | 0x00, 0x00, 0, 40, 101, | ||
59 | 0x01, 0x00, 1, 40, 50, | ||
60 | 0x02, 0x00, 2, 35, 45, | ||
61 | 0x03, 0x00, 3, 20, 45, | ||
62 | 0x04, 0x21, 0, 30, 50, | ||
63 | 0x05, 0x21, 1, 20, 50, | ||
64 | 0x06, 0x21, 2, 20, 50, | ||
65 | 0x07, 0x21, 3, 15, 50, | ||
66 | 0x08, 0x21, 4, 15, 30, | ||
67 | 0x09, 0x21, 5, 10, 25, | ||
68 | 0x0a, 0x21, 6, 8, 25, | ||
69 | 0x0b, 0x21, 7, 8, 25, | ||
70 | 0x0c, 0x20, 12, 15, 30, | ||
71 | 0x0d, 0x20, 13, 8, 20, | ||
72 | 0x0e, 0x20, 14, 8, 20, | ||
73 | 0x0f, 0x20, 15, 8, 25, | ||
74 | 0x10, 0x22, 15, 8, 25, | ||
75 | 0x11, 0x00, 0, 0, 0, | ||
76 | 0x12, 0x00, 0, 0, 0, | ||
77 | 0x13, 0x00, 0, 0, 0, | ||
78 | 0x14, 0x00, 0, 0, 0, | ||
79 | 0x15, 0x00, 0, 0, 0, | ||
80 | 0x16, 0x00, 0, 0, 0, | ||
81 | 0x17, 0x00, 0, 0, 0, | ||
82 | 0x18, 0x00, 0, 0, 0, | ||
83 | 0x19, 0x00, 0, 0, 0, | ||
84 | 0x1a, 0x00, 0, 0, 0, | ||
85 | 0x1b, 0x00, 0, 0, 0, | ||
86 | 0x1c, 0x00, 0, 0, 0, | ||
87 | 0x1d, 0x00, 0, 0, 0, | ||
88 | 0x1e, 0x00, 0, 0, 0, | ||
89 | 0x1f, 0x00, 0, 0, 0, | ||
90 | }; | ||
91 | |||
92 | u8 RateSwitchTable11B[] = { | ||
93 | /* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ | ||
94 | 0x04, 0x03, 0, 0, 0, /* Initial used item after association */ | ||
95 | 0x00, 0x00, 0, 40, 101, | ||
96 | 0x01, 0x00, 1, 40, 50, | ||
97 | 0x02, 0x00, 2, 35, 45, | ||
98 | 0x03, 0x00, 3, 20, 45, | ||
99 | }; | ||
100 | |||
101 | u8 RateSwitchTable11BG[] = { | ||
102 | /* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ | ||
103 | 0x0a, 0x00, 0, 0, 0, /* Initial used item after association */ | ||
104 | 0x00, 0x00, 0, 40, 101, | ||
105 | 0x01, 0x00, 1, 40, 50, | ||
106 | 0x02, 0x00, 2, 35, 45, | ||
107 | 0x03, 0x00, 3, 20, 45, | ||
108 | 0x04, 0x10, 2, 20, 35, | ||
109 | 0x05, 0x10, 3, 16, 35, | ||
110 | 0x06, 0x10, 4, 10, 25, | ||
111 | 0x07, 0x10, 5, 16, 25, | ||
112 | 0x08, 0x10, 6, 10, 25, | ||
113 | 0x09, 0x10, 7, 10, 13, | ||
114 | }; | ||
115 | |||
116 | u8 RateSwitchTable11G[] = { | ||
117 | /* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ | ||
118 | 0x08, 0x00, 0, 0, 0, /* Initial used item after association */ | ||
119 | 0x00, 0x10, 0, 20, 101, | ||
120 | 0x01, 0x10, 1, 20, 35, | ||
121 | 0x02, 0x10, 2, 20, 35, | ||
122 | 0x03, 0x10, 3, 16, 35, | ||
123 | 0x04, 0x10, 4, 10, 25, | ||
124 | 0x05, 0x10, 5, 16, 25, | ||
125 | 0x06, 0x10, 6, 10, 25, | ||
126 | 0x07, 0x10, 7, 10, 13, | ||
127 | }; | ||
128 | |||
129 | u8 RateSwitchTable11N1S[] = { | ||
130 | /* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ | ||
131 | 0x0c, 0x0a, 0, 0, 0, /* Initial used item after association */ | ||
132 | 0x00, 0x00, 0, 40, 101, | ||
133 | 0x01, 0x00, 1, 40, 50, | ||
134 | 0x02, 0x00, 2, 25, 45, | ||
135 | 0x03, 0x21, 0, 20, 35, | ||
136 | 0x04, 0x21, 1, 20, 35, | ||
137 | 0x05, 0x21, 2, 20, 35, | ||
138 | 0x06, 0x21, 3, 15, 35, | ||
139 | 0x07, 0x21, 4, 15, 30, | ||
140 | 0x08, 0x21, 5, 10, 25, | ||
141 | 0x09, 0x21, 6, 8, 14, | ||
142 | 0x0a, 0x21, 7, 8, 14, | ||
143 | 0x0b, 0x23, 7, 8, 14, | ||
144 | }; | ||
145 | |||
146 | u8 RateSwitchTable11N2S[] = { | ||
147 | /* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ | ||
148 | 0x0e, 0x0c, 0, 0, 0, /* Initial used item after association */ | ||
149 | 0x00, 0x00, 0, 40, 101, | ||
150 | 0x01, 0x00, 1, 40, 50, | ||
151 | 0x02, 0x00, 2, 25, 45, | ||
152 | 0x03, 0x21, 0, 20, 35, | ||
153 | 0x04, 0x21, 1, 20, 35, | ||
154 | 0x05, 0x21, 2, 20, 35, | ||
155 | 0x06, 0x21, 3, 15, 35, | ||
156 | 0x07, 0x21, 4, 15, 30, | ||
157 | 0x08, 0x20, 11, 15, 30, | ||
158 | 0x09, 0x20, 12, 15, 30, | ||
159 | 0x0a, 0x20, 13, 8, 20, | ||
160 | 0x0b, 0x20, 14, 8, 20, | ||
161 | 0x0c, 0x20, 15, 8, 25, | ||
162 | 0x0d, 0x22, 15, 8, 15, | ||
163 | }; | ||
164 | |||
165 | u8 RateSwitchTable11N3S[] = { | ||
166 | /* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ | ||
167 | 0x0b, 0x00, 0, 0, 0, /* 0x0a, 0x00, 0, 0, 0, // Initial used item after association */ | ||
168 | 0x00, 0x21, 0, 30, 101, | ||
169 | 0x01, 0x21, 1, 20, 50, | ||
170 | 0x02, 0x21, 2, 20, 50, | ||
171 | 0x03, 0x21, 3, 15, 50, | ||
172 | 0x04, 0x21, 4, 15, 30, | ||
173 | 0x05, 0x20, 11, 15, 30, /* Required by System-Alan @ 20080812 */ | ||
174 | 0x06, 0x20, 12, 15, 30, /* 0x05, 0x20, 12, 15, 30, */ | ||
175 | 0x07, 0x20, 13, 8, 20, /* 0x06, 0x20, 13, 8, 20, */ | ||
176 | 0x08, 0x20, 14, 8, 20, /* 0x07, 0x20, 14, 8, 20, */ | ||
177 | 0x09, 0x20, 15, 8, 25, /* 0x08, 0x20, 15, 8, 25, */ | ||
178 | 0x0a, 0x22, 15, 8, 25, /* 0x09, 0x22, 15, 8, 25, */ | ||
179 | }; | ||
180 | |||
181 | u8 RateSwitchTable11N2SForABand[] = { | ||
182 | /* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ | ||
183 | 0x0b, 0x09, 0, 0, 0, /* Initial used item after association */ | ||
184 | 0x00, 0x21, 0, 30, 101, | ||
185 | 0x01, 0x21, 1, 20, 50, | ||
186 | 0x02, 0x21, 2, 20, 50, | ||
187 | 0x03, 0x21, 3, 15, 50, | ||
188 | 0x04, 0x21, 4, 15, 30, | ||
189 | 0x05, 0x21, 5, 15, 30, | ||
190 | 0x06, 0x20, 12, 15, 30, | ||
191 | 0x07, 0x20, 13, 8, 20, | ||
192 | 0x08, 0x20, 14, 8, 20, | ||
193 | 0x09, 0x20, 15, 8, 25, | ||
194 | 0x0a, 0x22, 15, 8, 25, | ||
195 | }; | ||
196 | |||
197 | u8 RateSwitchTable11N3SForABand[] = { /* 3*3 */ | ||
198 | /* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ | ||
199 | 0x0b, 0x09, 0, 0, 0, /* Initial used item after association */ | ||
200 | 0x00, 0x21, 0, 30, 101, | ||
201 | 0x01, 0x21, 1, 20, 50, | ||
202 | 0x02, 0x21, 2, 20, 50, | ||
203 | 0x03, 0x21, 3, 15, 50, | ||
204 | 0x04, 0x21, 4, 15, 30, | ||
205 | 0x05, 0x21, 5, 15, 30, | ||
206 | 0x06, 0x20, 12, 15, 30, | ||
207 | 0x07, 0x20, 13, 8, 20, | ||
208 | 0x08, 0x20, 14, 8, 20, | ||
209 | 0x09, 0x20, 15, 8, 25, | ||
210 | 0x0a, 0x22, 15, 8, 25, | ||
211 | }; | ||
212 | |||
213 | u8 RateSwitchTable11BGN1S[] = { | ||
214 | /* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ | ||
215 | 0x0c, 0x0a, 0, 0, 0, /* Initial used item after association */ | ||
216 | 0x00, 0x00, 0, 40, 101, | ||
217 | 0x01, 0x00, 1, 40, 50, | ||
218 | 0x02, 0x00, 2, 25, 45, | ||
219 | 0x03, 0x21, 0, 20, 35, | ||
220 | 0x04, 0x21, 1, 20, 35, | ||
221 | 0x05, 0x21, 2, 20, 35, | ||
222 | 0x06, 0x21, 3, 15, 35, | ||
223 | 0x07, 0x21, 4, 15, 30, | ||
224 | 0x08, 0x21, 5, 10, 25, | ||
225 | 0x09, 0x21, 6, 8, 14, | ||
226 | 0x0a, 0x21, 7, 8, 14, | ||
227 | 0x0b, 0x23, 7, 8, 14, | ||
228 | }; | ||
229 | |||
230 | u8 RateSwitchTable11BGN2S[] = { | ||
231 | /* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ | ||
232 | 0x0e, 0x0c, 0, 0, 0, /* Initial used item after association */ | ||
233 | 0x00, 0x00, 0, 40, 101, | ||
234 | 0x01, 0x00, 1, 40, 50, | ||
235 | 0x02, 0x00, 2, 25, 45, | ||
236 | 0x03, 0x21, 0, 20, 35, | ||
237 | 0x04, 0x21, 1, 20, 35, | ||
238 | 0x05, 0x21, 2, 20, 35, | ||
239 | 0x06, 0x21, 3, 15, 35, | ||
240 | 0x07, 0x21, 4, 15, 30, | ||
241 | 0x08, 0x20, 11, 15, 30, | ||
242 | 0x09, 0x20, 12, 15, 30, | ||
243 | 0x0a, 0x20, 13, 8, 20, | ||
244 | 0x0b, 0x20, 14, 8, 20, | ||
245 | 0x0c, 0x20, 15, 8, 25, | ||
246 | 0x0d, 0x22, 15, 8, 15, | ||
247 | }; | ||
248 | |||
249 | u8 RateSwitchTable11BGN3S[] = { /* 3*3 */ | ||
250 | /* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ | ||
251 | 0x0a, 0x00, 0, 0, 0, /* Initial used item after association */ | ||
252 | 0x00, 0x21, 0, 30, 101, /*50 */ | ||
253 | 0x01, 0x21, 1, 20, 50, | ||
254 | 0x02, 0x21, 2, 20, 50, | ||
255 | 0x03, 0x21, 3, 20, 50, | ||
256 | 0x04, 0x21, 4, 15, 50, | ||
257 | 0x05, 0x20, 20, 15, 30, | ||
258 | 0x06, 0x20, 21, 8, 20, | ||
259 | 0x07, 0x20, 22, 8, 20, | ||
260 | 0x08, 0x20, 23, 8, 25, | ||
261 | 0x09, 0x22, 23, 8, 25, | ||
262 | }; | ||
263 | |||
264 | u8 RateSwitchTable11BGN2SForABand[] = { | ||
265 | /* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ | ||
266 | 0x0b, 0x09, 0, 0, 0, /* Initial used item after association */ | ||
267 | 0x00, 0x21, 0, 30, 101, /*50 */ | ||
268 | 0x01, 0x21, 1, 20, 50, | ||
269 | 0x02, 0x21, 2, 20, 50, | ||
270 | 0x03, 0x21, 3, 15, 50, | ||
271 | 0x04, 0x21, 4, 15, 30, | ||
272 | 0x05, 0x21, 5, 15, 30, | ||
273 | 0x06, 0x20, 12, 15, 30, | ||
274 | 0x07, 0x20, 13, 8, 20, | ||
275 | 0x08, 0x20, 14, 8, 20, | ||
276 | 0x09, 0x20, 15, 8, 25, | ||
277 | 0x0a, 0x22, 15, 8, 25, | ||
278 | }; | ||
279 | |||
280 | u8 RateSwitchTable11BGN3SForABand[] = { /* 3*3 */ | ||
281 | /* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */ | ||
282 | 0x0c, 0x09, 0, 0, 0, /* Initial used item after association */ | ||
283 | 0x00, 0x21, 0, 30, 101, /*50 */ | ||
284 | 0x01, 0x21, 1, 20, 50, | ||
285 | 0x02, 0x21, 2, 20, 50, | ||
286 | 0x03, 0x21, 3, 15, 50, | ||
287 | 0x04, 0x21, 4, 15, 30, | ||
288 | 0x05, 0x21, 5, 15, 30, | ||
289 | 0x06, 0x21, 12, 15, 30, | ||
290 | 0x07, 0x20, 20, 15, 30, | ||
291 | 0x08, 0x20, 21, 8, 20, | ||
292 | 0x09, 0x20, 22, 8, 20, | ||
293 | 0x0a, 0x20, 23, 8, 25, | ||
294 | 0x0b, 0x22, 23, 8, 25, | ||
295 | }; | ||
296 | |||
297 | extern u8 OfdmRateToRxwiMCS[]; | ||
298 | /* since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate. */ | ||
299 | /* otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate */ | ||
300 | unsigned long BasicRateMask[12] = | ||
301 | { 0xfffff001 /* 1-Mbps */ , 0xfffff003 /* 2 Mbps */ , 0xfffff007 /* 5.5 */ , | ||
302 | 0xfffff00f /* 11 */ , | ||
303 | 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , | ||
304 | 0xfffff0ff /* 18 */ , | ||
305 | 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , | ||
306 | 0xffffffff /* 54 */ | ||
307 | }; | ||
308 | |||
309 | u8 BROADCAST_ADDR[MAC_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||
310 | u8 ZERO_MAC_ADDR[MAC_ADDR_LEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; | ||
311 | |||
312 | /* e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than */ | ||
313 | /* this value, then it's quaranteed capable of operating in 36 mbps TX rate in */ | ||
314 | /* clean environment. */ | ||
315 | /* TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100 */ | ||
316 | char RssiSafeLevelForTxRate[] = | ||
317 | { -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 }; | ||
318 | |||
319 | u8 RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100 }; | ||
320 | u16 RateIdTo500Kbps[] = | ||
321 | { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200 }; | ||
322 | |||
323 | u8 SsidIe = IE_SSID; | ||
324 | u8 SupRateIe = IE_SUPP_RATES; | ||
325 | u8 ExtRateIe = IE_EXT_SUPP_RATES; | ||
326 | u8 HtCapIe = IE_HT_CAP; | ||
327 | u8 AddHtInfoIe = IE_ADD_HT; | ||
328 | u8 NewExtChanIe = IE_SECONDARY_CH_OFFSET; | ||
329 | u8 ErpIe = IE_ERP; | ||
330 | u8 DsIe = IE_DS_PARM; | ||
331 | u8 TimIe = IE_TIM; | ||
332 | u8 WpaIe = IE_WPA; | ||
333 | u8 Wpa2Ie = IE_WPA2; | ||
334 | u8 IbssIe = IE_IBSS_PARM; | ||
335 | |||
336 | extern u8 WPA_OUI[]; | ||
337 | |||
338 | u8 SES_OUI[] = { 0x00, 0x90, 0x4c }; | ||
339 | |||
340 | u8 ZeroSsid[32] = | ||
341 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
342 | 0x00, 0x00, 0x00, 0x00, | ||
343 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
344 | 0x00, 0x00, 0x00, 0x00 | ||
345 | }; | ||
346 | |||
347 | /* | ||
348 | ========================================================================== | ||
349 | Description: | ||
350 | initialize the MLME task and its data structure (queue, spinlock, | ||
351 | timer, state machines). | ||
352 | |||
353 | IRQL = PASSIVE_LEVEL | ||
354 | |||
355 | Return: | ||
356 | always return NDIS_STATUS_SUCCESS | ||
357 | |||
358 | ========================================================================== | ||
359 | */ | ||
360 | int MlmeInit(struct rt_rtmp_adapter *pAd) | ||
361 | { | ||
362 | int Status = NDIS_STATUS_SUCCESS; | ||
363 | |||
364 | DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n")); | ||
365 | |||
366 | do { | ||
367 | Status = MlmeQueueInit(&pAd->Mlme.Queue); | ||
368 | if (Status != NDIS_STATUS_SUCCESS) | ||
369 | break; | ||
370 | |||
371 | pAd->Mlme.bRunning = FALSE; | ||
372 | NdisAllocateSpinLock(&pAd->Mlme.TaskLock); | ||
373 | |||
374 | { | ||
375 | BssTableInit(&pAd->ScanTab); | ||
376 | |||
377 | /* init STA state machines */ | ||
378 | AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, | ||
379 | pAd->Mlme.AssocFunc); | ||
380 | AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, | ||
381 | pAd->Mlme.AuthFunc); | ||
382 | AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, | ||
383 | pAd->Mlme.AuthRspFunc); | ||
384 | SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, | ||
385 | pAd->Mlme.SyncFunc); | ||
386 | |||
387 | /* Since we are using switch/case to implement it, the init is different from the above */ | ||
388 | /* state machine init */ | ||
389 | MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL); | ||
390 | } | ||
391 | |||
392 | WpaStateMachineInit(pAd, &pAd->Mlme.WpaMachine, | ||
393 | pAd->Mlme.WpaFunc); | ||
394 | |||
395 | ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, | ||
396 | pAd->Mlme.ActFunc); | ||
397 | |||
398 | /* Init mlme periodic timer */ | ||
399 | RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, | ||
400 | GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE); | ||
401 | |||
402 | /* Set mlme periodic timer */ | ||
403 | RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV); | ||
404 | |||
405 | /* software-based RX Antenna diversity */ | ||
406 | RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, | ||
407 | GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, | ||
408 | FALSE); | ||
409 | |||
410 | { | ||
411 | #ifdef RTMP_PCI_SUPPORT | ||
412 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) { | ||
413 | /* only PCIe cards need these two timers */ | ||
414 | RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, | ||
415 | GET_TIMER_FUNCTION | ||
416 | (PsPollWakeExec), pAd, FALSE); | ||
417 | RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, | ||
418 | GET_TIMER_FUNCTION(RadioOnExec), | ||
419 | pAd, FALSE); | ||
420 | } | ||
421 | #endif /* RTMP_PCI_SUPPORT // */ | ||
422 | |||
423 | RTMPInitTimer(pAd, &pAd->Mlme.LinkDownTimer, | ||
424 | GET_TIMER_FUNCTION(LinkDownExec), pAd, | ||
425 | FALSE); | ||
426 | |||
427 | #ifdef RTMP_MAC_USB | ||
428 | RTMPInitTimer(pAd, &pAd->Mlme.AutoWakeupTimer, | ||
429 | GET_TIMER_FUNCTION | ||
430 | (RtmpUsbStaAsicForceWakeupTimeout), pAd, | ||
431 | FALSE); | ||
432 | pAd->Mlme.AutoWakeupTimerRunning = FALSE; | ||
433 | #endif /* RTMP_MAC_USB // */ | ||
434 | } | ||
435 | |||
436 | } while (FALSE); | ||
437 | |||
438 | DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n")); | ||
439 | |||
440 | return Status; | ||
441 | } | ||
442 | |||
443 | /* | ||
444 | ========================================================================== | ||
445 | Description: | ||
446 | main loop of the MLME | ||
447 | Pre: | ||
448 | Mlme has to be initialized, and there are something inside the queue | ||
449 | Note: | ||
450 | This function is invoked from MPSetInformation and MPReceive; | ||
451 | This task guarantee only one MlmeHandler will run. | ||
452 | |||
453 | IRQL = DISPATCH_LEVEL | ||
454 | |||
455 | ========================================================================== | ||
456 | */ | ||
457 | void MlmeHandler(struct rt_rtmp_adapter *pAd) | ||
458 | { | ||
459 | struct rt_mlme_queue_elem *Elem = NULL; | ||
460 | |||
461 | /* Only accept MLME and Frame from peer side, no other (control/data) frame should */ | ||
462 | /* get into this state machine */ | ||
463 | |||
464 | NdisAcquireSpinLock(&pAd->Mlme.TaskLock); | ||
465 | if (pAd->Mlme.bRunning) { | ||
466 | NdisReleaseSpinLock(&pAd->Mlme.TaskLock); | ||
467 | return; | ||
468 | } else { | ||
469 | pAd->Mlme.bRunning = TRUE; | ||
470 | } | ||
471 | NdisReleaseSpinLock(&pAd->Mlme.TaskLock); | ||
472 | |||
473 | while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) { | ||
474 | if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) || | ||
475 | RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) || | ||
476 | RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) { | ||
477 | DBGPRINT(RT_DEBUG_TRACE, | ||
478 | ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", | ||
479 | pAd->Mlme.Queue.Num)); | ||
480 | break; | ||
481 | } | ||
482 | /*From message type, determine which state machine I should drive */ | ||
483 | if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) { | ||
484 | #ifdef RTMP_MAC_USB | ||
485 | if (Elem->MsgType == MT2_RESET_CONF) { | ||
486 | DBGPRINT_RAW(RT_DEBUG_TRACE, | ||
487 | ("reset MLME state machine!\n")); | ||
488 | MlmeRestartStateMachine(pAd); | ||
489 | Elem->Occupied = FALSE; | ||
490 | Elem->MsgLen = 0; | ||
491 | continue; | ||
492 | } | ||
493 | #endif /* RTMP_MAC_USB // */ | ||
494 | |||
495 | /* if dequeue success */ | ||
496 | switch (Elem->Machine) { | ||
497 | /* STA state machines */ | ||
498 | case ASSOC_STATE_MACHINE: | ||
499 | StateMachinePerformAction(pAd, | ||
500 | &pAd->Mlme. | ||
501 | AssocMachine, Elem); | ||
502 | break; | ||
503 | case AUTH_STATE_MACHINE: | ||
504 | StateMachinePerformAction(pAd, | ||
505 | &pAd->Mlme. | ||
506 | AuthMachine, Elem); | ||
507 | break; | ||
508 | case AUTH_RSP_STATE_MACHINE: | ||
509 | StateMachinePerformAction(pAd, | ||
510 | &pAd->Mlme. | ||
511 | AuthRspMachine, Elem); | ||
512 | break; | ||
513 | case SYNC_STATE_MACHINE: | ||
514 | StateMachinePerformAction(pAd, | ||
515 | &pAd->Mlme. | ||
516 | SyncMachine, Elem); | ||
517 | break; | ||
518 | case MLME_CNTL_STATE_MACHINE: | ||
519 | MlmeCntlMachinePerformAction(pAd, | ||
520 | &pAd->Mlme. | ||
521 | CntlMachine, Elem); | ||
522 | break; | ||
523 | case WPA_PSK_STATE_MACHINE: | ||
524 | StateMachinePerformAction(pAd, | ||
525 | &pAd->Mlme. | ||
526 | WpaPskMachine, Elem); | ||
527 | break; | ||
528 | |||
529 | case ACTION_STATE_MACHINE: | ||
530 | StateMachinePerformAction(pAd, | ||
531 | &pAd->Mlme.ActMachine, | ||
532 | Elem); | ||
533 | break; | ||
534 | |||
535 | case WPA_STATE_MACHINE: | ||
536 | StateMachinePerformAction(pAd, | ||
537 | &pAd->Mlme.WpaMachine, | ||
538 | Elem); | ||
539 | break; | ||
540 | |||
541 | default: | ||
542 | DBGPRINT(RT_DEBUG_TRACE, | ||
543 | ("ERROR: Illegal machine %ld in MlmeHandler()\n", | ||
544 | Elem->Machine)); | ||
545 | break; | ||
546 | } /* end of switch */ | ||
547 | |||
548 | /* free MLME element */ | ||
549 | Elem->Occupied = FALSE; | ||
550 | Elem->MsgLen = 0; | ||
551 | |||
552 | } else { | ||
553 | DBGPRINT_ERR("MlmeHandler: MlmeQueue empty\n"); | ||
554 | } | ||
555 | } | ||
556 | |||
557 | NdisAcquireSpinLock(&pAd->Mlme.TaskLock); | ||
558 | pAd->Mlme.bRunning = FALSE; | ||
559 | NdisReleaseSpinLock(&pAd->Mlme.TaskLock); | ||
560 | } | ||
561 | |||
562 | /* | ||
563 | ========================================================================== | ||
564 | Description: | ||
565 | Destructor of MLME (Destroy queue, state machine, spin lock and timer) | ||
566 | Parameters: | ||
567 | Adapter - NIC Adapter pointer | ||
568 | Post: | ||
569 | The MLME task will no longer work properly | ||
570 | |||
571 | IRQL = PASSIVE_LEVEL | ||
572 | |||
573 | ========================================================================== | ||
574 | */ | ||
575 | void MlmeHalt(struct rt_rtmp_adapter *pAd) | ||
576 | { | ||
577 | BOOLEAN Cancelled; | ||
578 | |||
579 | DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n")); | ||
580 | |||
581 | if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) { | ||
582 | /* disable BEACON generation and other BEACON related hardware timers */ | ||
583 | AsicDisableSync(pAd); | ||
584 | } | ||
585 | |||
586 | { | ||
587 | /* Cancel pending timers */ | ||
588 | RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled); | ||
589 | RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled); | ||
590 | RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled); | ||
591 | RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled); | ||
592 | RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled); | ||
593 | RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); | ||
594 | |||
595 | #ifdef RTMP_MAC_PCI | ||
596 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE) | ||
597 | && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) { | ||
598 | RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); | ||
599 | RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); | ||
600 | } | ||
601 | #endif /* RTMP_MAC_PCI // */ | ||
602 | |||
603 | RTMPCancelTimer(&pAd->Mlme.LinkDownTimer, &Cancelled); | ||
604 | |||
605 | #ifdef RTMP_MAC_USB | ||
606 | RTMPCancelTimer(&pAd->Mlme.AutoWakeupTimer, &Cancelled); | ||
607 | #endif /* RTMP_MAC_USB // */ | ||
608 | } | ||
609 | |||
610 | RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled); | ||
611 | RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled); | ||
612 | |||
613 | if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) { | ||
614 | struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps; | ||
615 | |||
616 | /* Set LED */ | ||
617 | RTMPSetLED(pAd, LED_HALT); | ||
618 | RTMPSetSignalLED(pAd, -100); /* Force signal strength Led to be turned off, firmware is not done it. */ | ||
619 | #ifdef RTMP_MAC_USB | ||
620 | { | ||
621 | LED_CFG_STRUC LedCfg; | ||
622 | RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word); | ||
623 | LedCfg.field.LedPolar = 0; | ||
624 | LedCfg.field.RLedMode = 0; | ||
625 | LedCfg.field.GLedMode = 0; | ||
626 | LedCfg.field.YLedMode = 0; | ||
627 | RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word); | ||
628 | } | ||
629 | #endif /* RTMP_MAC_USB // */ | ||
630 | |||
631 | if (pChipOps->AsicHaltAction) | ||
632 | pChipOps->AsicHaltAction(pAd); | ||
633 | } | ||
634 | |||
635 | RTMPusecDelay(5000); /* 5 msec to guarantee Ant Diversity timer canceled */ | ||
636 | |||
637 | MlmeQueueDestroy(&pAd->Mlme.Queue); | ||
638 | NdisFreeSpinLock(&pAd->Mlme.TaskLock); | ||
639 | |||
640 | DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n")); | ||
641 | } | ||
642 | |||
643 | void MlmeResetRalinkCounters(struct rt_rtmp_adapter *pAd) | ||
644 | { | ||
645 | pAd->RalinkCounters.LastOneSecRxOkDataCnt = | ||
646 | pAd->RalinkCounters.OneSecRxOkDataCnt; | ||
647 | /* clear all OneSecxxx counters. */ | ||
648 | pAd->RalinkCounters.OneSecBeaconSentCnt = 0; | ||
649 | pAd->RalinkCounters.OneSecFalseCCACnt = 0; | ||
650 | pAd->RalinkCounters.OneSecRxFcsErrCnt = 0; | ||
651 | pAd->RalinkCounters.OneSecRxOkCnt = 0; | ||
652 | pAd->RalinkCounters.OneSecTxFailCount = 0; | ||
653 | pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0; | ||
654 | pAd->RalinkCounters.OneSecTxRetryOkCount = 0; | ||
655 | pAd->RalinkCounters.OneSecRxOkDataCnt = 0; | ||
656 | pAd->RalinkCounters.OneSecReceivedByteCount = 0; | ||
657 | pAd->RalinkCounters.OneSecTransmittedByteCount = 0; | ||
658 | |||
659 | /* TODO: for debug only. to be removed */ | ||
660 | pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0; | ||
661 | pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0; | ||
662 | pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0; | ||
663 | pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0; | ||
664 | pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0; | ||
665 | pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0; | ||
666 | pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0; | ||
667 | pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0; | ||
668 | pAd->RalinkCounters.OneSecTxDoneCount = 0; | ||
669 | pAd->RalinkCounters.OneSecRxCount = 0; | ||
670 | pAd->RalinkCounters.OneSecTxAggregationCount = 0; | ||
671 | pAd->RalinkCounters.OneSecRxAggregationCount = 0; | ||
672 | |||
673 | return; | ||
674 | } | ||
675 | |||
676 | /* | ||
677 | ========================================================================== | ||
678 | Description: | ||
679 | This routine is executed periodically to - | ||
680 | 1. Decide if it's a right time to turn on PwrMgmt bit of all | ||
681 | outgoiing frames | ||
682 | 2. Calculate ChannelQuality based on statistics of the last | ||
683 | period, so that TX rate won't toggling very frequently between a | ||
684 | successful TX and a failed TX. | ||
685 | 3. If the calculated ChannelQuality indicated current connection not | ||
686 | healthy, then a ROAMing attempt is tried here. | ||
687 | |||
688 | IRQL = DISPATCH_LEVEL | ||
689 | |||
690 | ========================================================================== | ||
691 | */ | ||
692 | #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) /* 8 sec */ | ||
693 | void MlmePeriodicExec(void *SystemSpecific1, | ||
694 | void *FunctionContext, | ||
695 | void *SystemSpecific2, void *SystemSpecific3) | ||
696 | { | ||
697 | unsigned long TxTotalCnt; | ||
698 | struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; | ||
699 | |||
700 | #ifdef RTMP_MAC_PCI | ||
701 | { | ||
702 | /* If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second. */ | ||
703 | /* Move code to here, because following code will return when radio is off */ | ||
704 | if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == | ||
705 | 0) && (pAd->StaCfg.bHardwareRadio == TRUE) | ||
706 | && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) | ||
707 | && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) | ||
708 | /*&&(pAd->bPCIclkOff == FALSE) */ | ||
709 | ) { | ||
710 | u32 data = 0; | ||
711 | |||
712 | /* Read GPIO pin2 as Hardware controlled radio state */ | ||
713 | #ifndef RT3090 | ||
714 | RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data); | ||
715 | #endif /* RT3090 // */ | ||
716 | /*KH(PCIE PS):Added based on Jane<-- */ | ||
717 | #ifdef RT3090 | ||
718 | /* Read GPIO pin2 as Hardware controlled radio state */ | ||
719 | /* We need to Read GPIO if HW said so no mater what advance power saving */ | ||
720 | if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) | ||
721 | && | ||
722 | (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)) | ||
723 | && (pAd->StaCfg.PSControl.field.EnablePSinIdle == | ||
724 | TRUE)) { | ||
725 | /* Want to make sure device goes to L0 state before reading register. */ | ||
726 | RTMPPCIeLinkCtrlValueRestore(pAd, 0); | ||
727 | RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data); | ||
728 | RTMPPCIeLinkCtrlSetting(pAd, 3); | ||
729 | } else | ||
730 | RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data); | ||
731 | #endif /* RT3090 // */ | ||
732 | /*KH(PCIE PS):Added based on Jane--> */ | ||
733 | |||
734 | if (data & 0x04) { | ||
735 | pAd->StaCfg.bHwRadio = TRUE; | ||
736 | } else { | ||
737 | pAd->StaCfg.bHwRadio = FALSE; | ||
738 | } | ||
739 | if (pAd->StaCfg.bRadio != | ||
740 | (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) { | ||
741 | pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio | ||
742 | && pAd->StaCfg.bSwRadio); | ||
743 | if (pAd->StaCfg.bRadio == TRUE) { | ||
744 | MlmeRadioOn(pAd); | ||
745 | /* Update extra information */ | ||
746 | pAd->ExtraInfo = EXTRA_INFO_CLEAR; | ||
747 | } else { | ||
748 | MlmeRadioOff(pAd); | ||
749 | /* Update extra information */ | ||
750 | pAd->ExtraInfo = HW_RADIO_OFF; | ||
751 | } | ||
752 | } | ||
753 | } | ||
754 | } | ||
755 | #endif /* RTMP_MAC_PCI // */ | ||
756 | |||
757 | /* Do nothing if the driver is starting halt state. */ | ||
758 | /* This might happen when timer already been fired before cancel timer with mlmehalt */ | ||
759 | if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS | | ||
760 | fRTMP_ADAPTER_RADIO_OFF | | ||
761 | fRTMP_ADAPTER_RADIO_MEASUREMENT | | ||
762 | fRTMP_ADAPTER_RESET_IN_PROGRESS)))) | ||
763 | return; | ||
764 | |||
765 | RTMP_MLME_PRE_SANITY_CHECK(pAd); | ||
766 | |||
767 | { | ||
768 | /* Do nothing if monitor mode is on */ | ||
769 | if (MONITOR_ON(pAd)) | ||
770 | return; | ||
771 | |||
772 | if (pAd->Mlme.PeriodicRound & 0x1) { | ||
773 | /* This is the fix for wifi 11n extension channel overlapping test case. for 2860D */ | ||
774 | if (((pAd->MACVersion & 0xffff) == 0x0101) && | ||
775 | (STA_TGN_WIFI_ON(pAd)) && | ||
776 | (pAd->CommonCfg.IOTestParm.bToggle == FALSE)) | ||
777 | { | ||
778 | RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf); | ||
779 | pAd->CommonCfg.IOTestParm.bToggle = TRUE; | ||
780 | } else if ((STA_TGN_WIFI_ON(pAd)) && | ||
781 | ((pAd->MACVersion & 0xffff) == 0x0101)) { | ||
782 | RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f); | ||
783 | pAd->CommonCfg.IOTestParm.bToggle = FALSE; | ||
784 | } | ||
785 | } | ||
786 | } | ||
787 | |||
788 | pAd->bUpdateBcnCntDone = FALSE; | ||
789 | |||
790 | /* RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3); */ | ||
791 | pAd->Mlme.PeriodicRound++; | ||
792 | |||
793 | #ifdef RTMP_MAC_USB | ||
794 | /* execute every 100ms, update the Tx FIFO Cnt for update Tx Rate. */ | ||
795 | NICUpdateFifoStaCounters(pAd); | ||
796 | #endif /* RTMP_MAC_USB // */ | ||
797 | |||
798 | /* execute every 500ms */ | ||
799 | if ((pAd->Mlme.PeriodicRound % 5 == 0) | ||
800 | && RTMPAutoRateSwitchCheck(pAd) | ||
801 | /*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */ ) | ||
802 | { | ||
803 | /* perform dynamic tx rate switching based on past TX history */ | ||
804 | { | ||
805 | if ((OPSTATUS_TEST_FLAG | ||
806 | (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) | ||
807 | ) | ||
808 | && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))) | ||
809 | MlmeDynamicTxRateSwitching(pAd); | ||
810 | } | ||
811 | } | ||
812 | /* Normal 1 second Mlme PeriodicExec. */ | ||
813 | if (pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE == 0) { | ||
814 | pAd->Mlme.OneSecPeriodicRound++; | ||
815 | |||
816 | /*ORIBATimerTimeout(pAd); */ | ||
817 | |||
818 | /* Media status changed, report to NDIS */ | ||
819 | if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE)) { | ||
820 | RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE); | ||
821 | if (OPSTATUS_TEST_FLAG | ||
822 | (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) { | ||
823 | pAd->IndicateMediaState = | ||
824 | NdisMediaStateConnected; | ||
825 | RTMP_IndicateMediaState(pAd); | ||
826 | |||
827 | } else { | ||
828 | pAd->IndicateMediaState = | ||
829 | NdisMediaStateDisconnected; | ||
830 | RTMP_IndicateMediaState(pAd); | ||
831 | } | ||
832 | } | ||
833 | |||
834 | NdisGetSystemUpTime(&pAd->Mlme.Now32); | ||
835 | |||
836 | /* add the most up-to-date h/w raw counters into software variable, so that */ | ||
837 | /* the dynamic tuning mechanism below are based on most up-to-date information */ | ||
838 | NICUpdateRawCounters(pAd); | ||
839 | |||
840 | #ifdef RTMP_MAC_USB | ||
841 | RTUSBWatchDog(pAd); | ||
842 | #endif /* RTMP_MAC_USB // */ | ||
843 | |||
844 | /* Need statistics after read counter. So put after NICUpdateRawCounters */ | ||
845 | ORIBATimerTimeout(pAd); | ||
846 | |||
847 | /* if MGMT RING is full more than twice within 1 second, we consider there's */ | ||
848 | /* a hardware problem stucking the TX path. In this case, try a hardware reset */ | ||
849 | /* to recover the system */ | ||
850 | /* if (pAd->RalinkCounters.MgmtRingFullCount >= 2) */ | ||
851 | /* RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HARDWARE_ERROR); */ | ||
852 | /* else */ | ||
853 | /* pAd->RalinkCounters.MgmtRingFullCount = 0; */ | ||
854 | |||
855 | /* The time period for checking antenna is according to traffic */ | ||
856 | { | ||
857 | if (pAd->Mlme.bEnableAutoAntennaCheck) { | ||
858 | TxTotalCnt = | ||
859 | pAd->RalinkCounters.OneSecTxNoRetryOkCount + | ||
860 | pAd->RalinkCounters.OneSecTxRetryOkCount + | ||
861 | pAd->RalinkCounters.OneSecTxFailCount; | ||
862 | |||
863 | /* dynamic adjust antenna evaluation period according to the traffic */ | ||
864 | if (TxTotalCnt > 50) { | ||
865 | if (pAd->Mlme.OneSecPeriodicRound % | ||
866 | 10 == 0) { | ||
867 | AsicEvaluateRxAnt(pAd); | ||
868 | } | ||
869 | } else { | ||
870 | if (pAd->Mlme.OneSecPeriodicRound % 3 == | ||
871 | 0) { | ||
872 | AsicEvaluateRxAnt(pAd); | ||
873 | } | ||
874 | } | ||
875 | } | ||
876 | } | ||
877 | |||
878 | STAMlmePeriodicExec(pAd); | ||
879 | |||
880 | MlmeResetRalinkCounters(pAd); | ||
881 | |||
882 | { | ||
883 | #ifdef RTMP_MAC_PCI | ||
884 | if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) | ||
885 | && (pAd->bPCIclkOff == FALSE)) | ||
886 | #endif /* RTMP_MAC_PCI // */ | ||
887 | { | ||
888 | /* When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock */ | ||
889 | /* and sending CTS-to-self over and over. */ | ||
890 | /* Software Patch Solution: */ | ||
891 | /* 1. Polling debug state register 0x10F4 every one second. */ | ||
892 | /* 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred. */ | ||
893 | /* 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again. */ | ||
894 | |||
895 | u32 MacReg = 0; | ||
896 | |||
897 | RTMP_IO_READ32(pAd, 0x10F4, &MacReg); | ||
898 | if (((MacReg & 0x20000000) && (MacReg & 0x80)) | ||
899 | || ((MacReg & 0x20000000) | ||
900 | && (MacReg & 0x20))) { | ||
901 | RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1); | ||
902 | RTMPusecDelay(1); | ||
903 | RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC); | ||
904 | |||
905 | DBGPRINT(RT_DEBUG_WARN, | ||
906 | ("Warning, MAC specific condition occurs \n")); | ||
907 | } | ||
908 | } | ||
909 | } | ||
910 | |||
911 | RTMP_MLME_HANDLER(pAd); | ||
912 | } | ||
913 | |||
914 | pAd->bUpdateBcnCntDone = FALSE; | ||
915 | } | ||
916 | |||
917 | /* | ||
918 | ========================================================================== | ||
919 | Validate SSID for connection try and rescan purpose | ||
920 | Valid SSID will have visible chars only. | ||
921 | The valid length is from 0 to 32. | ||
922 | IRQL = DISPATCH_LEVEL | ||
923 | ========================================================================== | ||
924 | */ | ||
925 | BOOLEAN MlmeValidateSSID(u8 *pSsid, u8 SsidLen) | ||
926 | { | ||
927 | int index; | ||
928 | |||
929 | if (SsidLen > MAX_LEN_OF_SSID) | ||
930 | return (FALSE); | ||
931 | |||
932 | /* Check each character value */ | ||
933 | for (index = 0; index < SsidLen; index++) { | ||
934 | if (pSsid[index] < 0x20) | ||
935 | return (FALSE); | ||
936 | } | ||
937 | |||
938 | /* All checked */ | ||
939 | return (TRUE); | ||
940 | } | ||
941 | |||
942 | void MlmeSelectTxRateTable(struct rt_rtmp_adapter *pAd, | ||
943 | struct rt_mac_table_entry *pEntry, | ||
944 | u8 ** ppTable, | ||
945 | u8 *pTableSize, u8 *pInitTxRateIdx) | ||
946 | { | ||
947 | do { | ||
948 | /* decide the rate table for tuning */ | ||
949 | if (pAd->CommonCfg.TxRateTableSize > 0) { | ||
950 | *ppTable = RateSwitchTable; | ||
951 | *pTableSize = RateSwitchTable[0]; | ||
952 | *pInitTxRateIdx = RateSwitchTable[1]; | ||
953 | |||
954 | break; | ||
955 | } | ||
956 | |||
957 | if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd)) { | ||
958 | if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) { /* 11N 1S Adhoc */ | ||
959 | *ppTable = RateSwitchTable11N1S; | ||
960 | *pTableSize = RateSwitchTable11N1S[0]; | ||
961 | *pInitTxRateIdx = RateSwitchTable11N1S[1]; | ||
962 | |||
963 | } else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) { /* 11N 2S Adhoc */ | ||
964 | if (pAd->LatchRfRegs.Channel <= 14) { | ||
965 | *ppTable = RateSwitchTable11N2S; | ||
966 | *pTableSize = RateSwitchTable11N2S[0]; | ||
967 | *pInitTxRateIdx = | ||
968 | RateSwitchTable11N2S[1]; | ||
969 | } else { | ||
970 | *ppTable = RateSwitchTable11N2SForABand; | ||
971 | *pTableSize = | ||
972 | RateSwitchTable11N2SForABand[0]; | ||
973 | *pInitTxRateIdx = | ||
974 | RateSwitchTable11N2SForABand[1]; | ||
975 | } | ||
976 | |||
977 | } else if ((pEntry->RateLen == 4) | ||
978 | && (pEntry->HTCapability.MCSSet[0] == 0) | ||
979 | && (pEntry->HTCapability.MCSSet[1] == 0) | ||
980 | ) { | ||
981 | *ppTable = RateSwitchTable11B; | ||
982 | *pTableSize = RateSwitchTable11B[0]; | ||
983 | *pInitTxRateIdx = RateSwitchTable11B[1]; | ||
984 | |||
985 | } else if (pAd->LatchRfRegs.Channel <= 14) { | ||
986 | *ppTable = RateSwitchTable11BG; | ||
987 | *pTableSize = RateSwitchTable11BG[0]; | ||
988 | *pInitTxRateIdx = RateSwitchTable11BG[1]; | ||
989 | |||
990 | } else { | ||
991 | *ppTable = RateSwitchTable11G; | ||
992 | *pTableSize = RateSwitchTable11G[0]; | ||
993 | *pInitTxRateIdx = RateSwitchTable11G[1]; | ||
994 | |||
995 | } | ||
996 | break; | ||
997 | } | ||
998 | /*if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && */ | ||
999 | /* ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) */ | ||
1000 | if (((pEntry->RateLen == 12) || (pAd->OpMode == OPMODE_STA)) && (pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1))) { /* 11BGN 1S AP */ | ||
1001 | *ppTable = RateSwitchTable11BGN1S; | ||
1002 | *pTableSize = RateSwitchTable11BGN1S[0]; | ||
1003 | *pInitTxRateIdx = RateSwitchTable11BGN1S[1]; | ||
1004 | |||
1005 | break; | ||
1006 | } | ||
1007 | /*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && */ | ||
1008 | /* (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) */ | ||
1009 | if (((pEntry->RateLen == 12) || (pAd->OpMode == OPMODE_STA)) && (pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2)) { /* 11BGN 2S AP */ | ||
1010 | if (pAd->LatchRfRegs.Channel <= 14) { | ||
1011 | *ppTable = RateSwitchTable11BGN2S; | ||
1012 | *pTableSize = RateSwitchTable11BGN2S[0]; | ||
1013 | *pInitTxRateIdx = RateSwitchTable11BGN2S[1]; | ||
1014 | |||
1015 | } else { | ||
1016 | *ppTable = RateSwitchTable11BGN2SForABand; | ||
1017 | *pTableSize = RateSwitchTable11BGN2SForABand[0]; | ||
1018 | *pInitTxRateIdx = | ||
1019 | RateSwitchTable11BGN2SForABand[1]; | ||
1020 | |||
1021 | } | ||
1022 | break; | ||
1023 | } | ||
1024 | /*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) */ | ||
1025 | if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1))) { /* 11N 1S AP */ | ||
1026 | *ppTable = RateSwitchTable11N1S; | ||
1027 | *pTableSize = RateSwitchTable11N1S[0]; | ||
1028 | *pInitTxRateIdx = RateSwitchTable11N1S[1]; | ||
1029 | |||
1030 | break; | ||
1031 | } | ||
1032 | /*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) */ | ||
1033 | if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2)) { /* 11N 2S AP */ | ||
1034 | if (pAd->LatchRfRegs.Channel <= 14) { | ||
1035 | *ppTable = RateSwitchTable11N2S; | ||
1036 | *pTableSize = RateSwitchTable11N2S[0]; | ||
1037 | *pInitTxRateIdx = RateSwitchTable11N2S[1]; | ||
1038 | } else { | ||
1039 | *ppTable = RateSwitchTable11N2SForABand; | ||
1040 | *pTableSize = RateSwitchTable11N2SForABand[0]; | ||
1041 | *pInitTxRateIdx = | ||
1042 | RateSwitchTable11N2SForABand[1]; | ||
1043 | } | ||
1044 | |||
1045 | break; | ||
1046 | } | ||
1047 | /*else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */ | ||
1048 | if ((pEntry->RateLen == 4 || pAd->CommonCfg.PhyMode == PHY_11B) | ||
1049 | /*Iverson mark for Adhoc b mode,sta will use rate 54 Mbps when connect with sta b/g/n mode */ | ||
1050 | /* && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) */ | ||
1051 | ) { /* B only AP */ | ||
1052 | *ppTable = RateSwitchTable11B; | ||
1053 | *pTableSize = RateSwitchTable11B[0]; | ||
1054 | *pInitTxRateIdx = RateSwitchTable11B[1]; | ||
1055 | |||
1056 | break; | ||
1057 | } | ||
1058 | /*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */ | ||
1059 | if ((pEntry->RateLen > 8) | ||
1060 | && (pEntry->HTCapability.MCSSet[0] == 0) | ||
1061 | && (pEntry->HTCapability.MCSSet[1] == 0) | ||
1062 | ) { /* B/G mixed AP */ | ||
1063 | *ppTable = RateSwitchTable11BG; | ||
1064 | *pTableSize = RateSwitchTable11BG[0]; | ||
1065 | *pInitTxRateIdx = RateSwitchTable11BG[1]; | ||
1066 | |||
1067 | break; | ||
1068 | } | ||
1069 | /*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */ | ||
1070 | if ((pEntry->RateLen == 8) | ||
1071 | && (pEntry->HTCapability.MCSSet[0] == 0) | ||
1072 | && (pEntry->HTCapability.MCSSet[1] == 0) | ||
1073 | ) { /* G only AP */ | ||
1074 | *ppTable = RateSwitchTable11G; | ||
1075 | *pTableSize = RateSwitchTable11G[0]; | ||
1076 | *pInitTxRateIdx = RateSwitchTable11G[1]; | ||
1077 | |||
1078 | break; | ||
1079 | } | ||
1080 | |||
1081 | { | ||
1082 | /*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */ | ||
1083 | if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)) { /* Legacy mode */ | ||
1084 | if (pAd->CommonCfg.MaxTxRate <= RATE_11) { | ||
1085 | *ppTable = RateSwitchTable11B; | ||
1086 | *pTableSize = RateSwitchTable11B[0]; | ||
1087 | *pInitTxRateIdx = RateSwitchTable11B[1]; | ||
1088 | } else if ((pAd->CommonCfg.MaxTxRate > RATE_11) | ||
1089 | && (pAd->CommonCfg.MinTxRate > | ||
1090 | RATE_11)) { | ||
1091 | *ppTable = RateSwitchTable11G; | ||
1092 | *pTableSize = RateSwitchTable11G[0]; | ||
1093 | *pInitTxRateIdx = RateSwitchTable11G[1]; | ||
1094 | |||
1095 | } else { | ||
1096 | *ppTable = RateSwitchTable11BG; | ||
1097 | *pTableSize = RateSwitchTable11BG[0]; | ||
1098 | *pInitTxRateIdx = | ||
1099 | RateSwitchTable11BG[1]; | ||
1100 | } | ||
1101 | break; | ||
1102 | } | ||
1103 | if (pAd->LatchRfRegs.Channel <= 14) { | ||
1104 | if (pAd->CommonCfg.TxStream == 1) { | ||
1105 | *ppTable = RateSwitchTable11N1S; | ||
1106 | *pTableSize = RateSwitchTable11N1S[0]; | ||
1107 | *pInitTxRateIdx = | ||
1108 | RateSwitchTable11N1S[1]; | ||
1109 | DBGPRINT_RAW(RT_DEBUG_ERROR, | ||
1110 | ("DRS: unknown mode,default use 11N 1S AP \n")); | ||
1111 | } else { | ||
1112 | *ppTable = RateSwitchTable11N2S; | ||
1113 | *pTableSize = RateSwitchTable11N2S[0]; | ||
1114 | *pInitTxRateIdx = | ||
1115 | RateSwitchTable11N2S[1]; | ||
1116 | DBGPRINT_RAW(RT_DEBUG_ERROR, | ||
1117 | ("DRS: unknown mode,default use 11N 2S AP \n")); | ||
1118 | } | ||
1119 | } else { | ||
1120 | if (pAd->CommonCfg.TxStream == 1) { | ||
1121 | *ppTable = RateSwitchTable11N1S; | ||
1122 | *pTableSize = RateSwitchTable11N1S[0]; | ||
1123 | *pInitTxRateIdx = | ||
1124 | RateSwitchTable11N1S[1]; | ||
1125 | DBGPRINT_RAW(RT_DEBUG_ERROR, | ||
1126 | ("DRS: unknown mode,default use 11N 1S AP \n")); | ||
1127 | } else { | ||
1128 | *ppTable = RateSwitchTable11N2SForABand; | ||
1129 | *pTableSize = | ||
1130 | RateSwitchTable11N2SForABand[0]; | ||
1131 | *pInitTxRateIdx = | ||
1132 | RateSwitchTable11N2SForABand[1]; | ||
1133 | DBGPRINT_RAW(RT_DEBUG_ERROR, | ||
1134 | ("DRS: unknown mode,default use 11N 2S AP \n")); | ||
1135 | } | ||
1136 | } | ||
1137 | DBGPRINT_RAW(RT_DEBUG_ERROR, | ||
1138 | ("DRS: unknown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n", | ||
1139 | pAd->StaActive.SupRateLen, | ||
1140 | pAd->StaActive.ExtRateLen, | ||
1141 | pAd->StaActive.SupportedPhyInfo.MCSSet[0], | ||
1142 | pAd->StaActive.SupportedPhyInfo. | ||
1143 | MCSSet[1])); | ||
1144 | } | ||
1145 | } while (FALSE); | ||
1146 | } | ||
1147 | |||
1148 | void STAMlmePeriodicExec(struct rt_rtmp_adapter *pAd) | ||
1149 | { | ||
1150 | unsigned long TxTotalCnt; | ||
1151 | int i; | ||
1152 | |||
1153 | /* | ||
1154 | We return here in ATE mode, because the statistics | ||
1155 | that ATE need are not collected via this routine. | ||
1156 | */ | ||
1157 | #if defined(RT305x)||defined(RT3070) | ||
1158 | /* request by Gary, if Rssi0 > -42, BBP 82 need to be changed from 0x62 to 0x42, , bbp 67 need to be changed from 0x20 to 0x18 */ | ||
1159 | if (!pAd->CommonCfg.HighPowerPatchDisabled) { | ||
1160 | #ifdef RT3070 | ||
1161 | if ((IS_RT3070(pAd) && ((pAd->MACVersion & 0xffff) < 0x0201))) | ||
1162 | #endif /* RT3070 // */ | ||
1163 | { | ||
1164 | if ((pAd->StaCfg.RssiSample.AvgRssi0 != 0) | ||
1165 | && (pAd->StaCfg.RssiSample.AvgRssi0 > | ||
1166 | (pAd->BbpRssiToDbmDelta - 35))) { | ||
1167 | RT30xxWriteRFRegister(pAd, RF_R27, 0x20); | ||
1168 | } else { | ||
1169 | RT30xxWriteRFRegister(pAd, RF_R27, 0x23); | ||
1170 | } | ||
1171 | } | ||
1172 | } | ||
1173 | #endif | ||
1174 | #ifdef PCIE_PS_SUPPORT | ||
1175 | /* don't perform idle-power-save mechanism within 3 min after driver initialization. */ | ||
1176 | /* This can make rebooter test more robust */ | ||
1177 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) { | ||
1178 | if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) | ||
1179 | && (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) | ||
1180 | && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) | ||
1181 | && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) { | ||
1182 | if (IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) { | ||
1183 | if (pAd->StaCfg.PSControl.field.EnableNewPS == | ||
1184 | TRUE) { | ||
1185 | DBGPRINT(RT_DEBUG_TRACE, | ||
1186 | ("%s\n", __func__)); | ||
1187 | RT28xxPciAsicRadioOff(pAd, | ||
1188 | GUI_IDLE_POWER_SAVE, | ||
1189 | 0); | ||
1190 | } else { | ||
1191 | AsicSendCommandToMcu(pAd, 0x30, | ||
1192 | PowerSafeCID, 0xff, | ||
1193 | 0x2); | ||
1194 | /* Wait command success */ | ||
1195 | AsicCheckCommanOk(pAd, PowerSafeCID); | ||
1196 | RTMP_SET_FLAG(pAd, | ||
1197 | fRTMP_ADAPTER_IDLE_RADIO_OFF); | ||
1198 | DBGPRINT(RT_DEBUG_TRACE, | ||
1199 | ("PSM - rt30xx Issue Sleep command)\n")); | ||
1200 | } | ||
1201 | } else if (pAd->Mlme.OneSecPeriodicRound > 180) { | ||
1202 | if (pAd->StaCfg.PSControl.field.EnableNewPS == | ||
1203 | TRUE) { | ||
1204 | DBGPRINT(RT_DEBUG_TRACE, | ||
1205 | ("%s\n", __func__)); | ||
1206 | RT28xxPciAsicRadioOff(pAd, | ||
1207 | GUI_IDLE_POWER_SAVE, | ||
1208 | 0); | ||
1209 | } else { | ||
1210 | AsicSendCommandToMcu(pAd, 0x30, | ||
1211 | PowerSafeCID, 0xff, | ||
1212 | 0x02); | ||
1213 | /* Wait command success */ | ||
1214 | AsicCheckCommanOk(pAd, PowerSafeCID); | ||
1215 | RTMP_SET_FLAG(pAd, | ||
1216 | fRTMP_ADAPTER_IDLE_RADIO_OFF); | ||
1217 | DBGPRINT(RT_DEBUG_TRACE, | ||
1218 | ("PSM - rt28xx Issue Sleep command)\n")); | ||
1219 | } | ||
1220 | } | ||
1221 | } else { | ||
1222 | DBGPRINT(RT_DEBUG_TRACE, | ||
1223 | ("STAMlmePeriodicExec MMCHK - CommonCfg.Ssid[%d]=%c%c%c%c... MlmeAux.Ssid[%d]=%c%c%c%c...\n", | ||
1224 | pAd->CommonCfg.SsidLen, | ||
1225 | pAd->CommonCfg.Ssid[0], | ||
1226 | pAd->CommonCfg.Ssid[1], | ||
1227 | pAd->CommonCfg.Ssid[2], | ||
1228 | pAd->CommonCfg.Ssid[3], pAd->MlmeAux.SsidLen, | ||
1229 | pAd->MlmeAux.Ssid[0], pAd->MlmeAux.Ssid[1], | ||
1230 | pAd->MlmeAux.Ssid[2], pAd->MlmeAux.Ssid[3])); | ||
1231 | } | ||
1232 | } | ||
1233 | #endif /* PCIE_PS_SUPPORT // */ | ||
1234 | |||
1235 | if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) { | ||
1236 | /* WPA MIC error should block association attempt for 60 seconds */ | ||
1237 | if (pAd->StaCfg.bBlockAssoc && | ||
1238 | RTMP_TIME_AFTER(pAd->Mlme.Now32, | ||
1239 | pAd->StaCfg.LastMicErrorTime + | ||
1240 | (60 * OS_HZ))) | ||
1241 | pAd->StaCfg.bBlockAssoc = FALSE; | ||
1242 | } | ||
1243 | |||
1244 | if ((pAd->PreMediaState != pAd->IndicateMediaState) | ||
1245 | && (pAd->CommonCfg.bWirelessEvent)) { | ||
1246 | if (pAd->IndicateMediaState == NdisMediaStateConnected) { | ||
1247 | RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, | ||
1248 | pAd->MacTab.Content[BSSID_WCID]. | ||
1249 | Addr, BSS0, 0); | ||
1250 | } | ||
1251 | pAd->PreMediaState = pAd->IndicateMediaState; | ||
1252 | } | ||
1253 | |||
1254 | if (pAd->CommonCfg.PSPXlink && ADHOC_ON(pAd)) { | ||
1255 | } else { | ||
1256 | AsicStaBbpTuning(pAd); | ||
1257 | } | ||
1258 | |||
1259 | TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + | ||
1260 | pAd->RalinkCounters.OneSecTxRetryOkCount + | ||
1261 | pAd->RalinkCounters.OneSecTxFailCount; | ||
1262 | |||
1263 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) { | ||
1264 | /* update channel quality for Roaming and UI LinkQuality display */ | ||
1265 | MlmeCalculateChannelQuality(pAd, NULL, pAd->Mlme.Now32); | ||
1266 | } | ||
1267 | /* must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if */ | ||
1268 | /* Radio is currently in noisy environment */ | ||
1269 | if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) | ||
1270 | AsicAdjustTxPower(pAd); | ||
1271 | |||
1272 | if (INFRA_ON(pAd)) { | ||
1273 | |||
1274 | /* Is PSM bit consistent with user power management policy? */ | ||
1275 | /* This is the only place that will set PSM bit ON. */ | ||
1276 | if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) | ||
1277 | MlmeCheckPsmChange(pAd, pAd->Mlme.Now32); | ||
1278 | |||
1279 | pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt; | ||
1280 | |||
1281 | if ((RTMP_TIME_AFTER | ||
1282 | (pAd->Mlme.Now32, | ||
1283 | pAd->StaCfg.LastBeaconRxTime + (1 * OS_HZ))) | ||
1284 | && | ||
1285 | (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) | ||
1286 | && | ||
1287 | (((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt) < | ||
1288 | 600))) { | ||
1289 | RTMPSetAGCInitValue(pAd, BW_20); | ||
1290 | DBGPRINT(RT_DEBUG_TRACE, | ||
1291 | ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", | ||
1292 | (0x2E + GET_LNA_GAIN(pAd)))); | ||
1293 | } | ||
1294 | /*if ((pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) && */ | ||
1295 | /* (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)) */ | ||
1296 | { | ||
1297 | if (pAd->CommonCfg.bAPSDCapable | ||
1298 | && pAd->CommonCfg.APEdcaParm.bAPSDCapable) { | ||
1299 | /* When APSD is enabled, the period changes as 20 sec */ | ||
1300 | if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8) | ||
1301 | RTMPSendNullFrame(pAd, | ||
1302 | pAd->CommonCfg.TxRate, | ||
1303 | TRUE); | ||
1304 | } else { | ||
1305 | /* Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out) */ | ||
1306 | if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8) { | ||
1307 | if (pAd->CommonCfg.bWmmCapable) | ||
1308 | RTMPSendNullFrame(pAd, | ||
1309 | pAd-> | ||
1310 | CommonCfg. | ||
1311 | TxRate, TRUE); | ||
1312 | else | ||
1313 | RTMPSendNullFrame(pAd, | ||
1314 | pAd-> | ||
1315 | CommonCfg. | ||
1316 | TxRate, | ||
1317 | FALSE); | ||
1318 | } | ||
1319 | } | ||
1320 | } | ||
1321 | |||
1322 | if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality)) { | ||
1323 | DBGPRINT(RT_DEBUG_TRACE, | ||
1324 | ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", | ||
1325 | pAd->RalinkCounters.BadCQIAutoRecoveryCount)); | ||
1326 | |||
1327 | /* Lost AP, send disconnect & link down event */ | ||
1328 | LinkDown(pAd, FALSE); | ||
1329 | |||
1330 | RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, NULL, NULL, | ||
1331 | 0); | ||
1332 | |||
1333 | /* RTMPPatchMacBbpBug(pAd); */ | ||
1334 | MlmeAutoReconnectLastSSID(pAd); | ||
1335 | } else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality)) { | ||
1336 | pAd->RalinkCounters.BadCQIAutoRecoveryCount++; | ||
1337 | DBGPRINT(RT_DEBUG_TRACE, | ||
1338 | ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", | ||
1339 | pAd->RalinkCounters.BadCQIAutoRecoveryCount)); | ||
1340 | MlmeAutoReconnectLastSSID(pAd); | ||
1341 | } | ||
1342 | |||
1343 | if (pAd->StaCfg.bAutoRoaming) { | ||
1344 | BOOLEAN rv = FALSE; | ||
1345 | char dBmToRoam = pAd->StaCfg.dBmToRoam; | ||
1346 | char MaxRssi = RTMPMaxRssi(pAd, | ||
1347 | pAd->StaCfg.RssiSample. | ||
1348 | LastRssi0, | ||
1349 | pAd->StaCfg.RssiSample. | ||
1350 | LastRssi1, | ||
1351 | pAd->StaCfg.RssiSample. | ||
1352 | LastRssi2); | ||
1353 | |||
1354 | /* Scanning, ignore Roaming */ | ||
1355 | if (!RTMP_TEST_FLAG | ||
1356 | (pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) | ||
1357 | && (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) | ||
1358 | && (MaxRssi <= dBmToRoam)) { | ||
1359 | DBGPRINT(RT_DEBUG_TRACE, | ||
1360 | ("Rssi=%d, dBmToRoam=%d\n", MaxRssi, | ||
1361 | (char)dBmToRoam)); | ||
1362 | |||
1363 | /* Add auto seamless roaming */ | ||
1364 | if (rv == FALSE) | ||
1365 | rv = MlmeCheckForFastRoaming(pAd); | ||
1366 | |||
1367 | if (rv == FALSE) { | ||
1368 | if ((pAd->StaCfg.LastScanTime + | ||
1369 | 10 * OS_HZ) < pAd->Mlme.Now32) { | ||
1370 | DBGPRINT(RT_DEBUG_TRACE, | ||
1371 | ("MMCHK - Roaming, No eligible entry, try new scan!\n")); | ||
1372 | pAd->StaCfg.ScanCnt = 2; | ||
1373 | pAd->StaCfg.LastScanTime = | ||
1374 | pAd->Mlme.Now32; | ||
1375 | MlmeAutoScan(pAd); | ||
1376 | } | ||
1377 | } | ||
1378 | } | ||
1379 | } | ||
1380 | } else if (ADHOC_ON(pAd)) { | ||
1381 | /* If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState */ | ||
1382 | /* to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can */ | ||
1383 | /* join later. */ | ||
1384 | if (RTMP_TIME_AFTER | ||
1385 | (pAd->Mlme.Now32, | ||
1386 | pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME) | ||
1387 | && OPSTATUS_TEST_FLAG(pAd, | ||
1388 | fOP_STATUS_MEDIA_STATE_CONNECTED)) { | ||
1389 | struct rt_mlme_start_req StartReq; | ||
1390 | |||
1391 | DBGPRINT(RT_DEBUG_TRACE, | ||
1392 | ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n")); | ||
1393 | LinkDown(pAd, FALSE); | ||
1394 | |||
1395 | StartParmFill(pAd, &StartReq, | ||
1396 | (char *) pAd->MlmeAux.Ssid, | ||
1397 | pAd->MlmeAux.SsidLen); | ||
1398 | MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, | ||
1399 | sizeof(struct rt_mlme_start_req), &StartReq); | ||
1400 | pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START; | ||
1401 | } | ||
1402 | |||
1403 | for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) { | ||
1404 | struct rt_mac_table_entry *pEntry = &pAd->MacTab.Content[i]; | ||
1405 | |||
1406 | if (pEntry->ValidAsCLI == FALSE) | ||
1407 | continue; | ||
1408 | |||
1409 | if (RTMP_TIME_AFTER | ||
1410 | (pAd->Mlme.Now32, | ||
1411 | pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME)) | ||
1412 | MacTableDeleteEntry(pAd, pEntry->Aid, | ||
1413 | pEntry->Addr); | ||
1414 | } | ||
1415 | } else /* no INFRA nor ADHOC connection */ | ||
1416 | { | ||
1417 | |||
1418 | if (pAd->StaCfg.bScanReqIsFromWebUI && | ||
1419 | RTMP_TIME_BEFORE(pAd->Mlme.Now32, | ||
1420 | pAd->StaCfg.LastScanTime + (30 * OS_HZ))) | ||
1421 | goto SKIP_AUTO_SCAN_CONN; | ||
1422 | else | ||
1423 | pAd->StaCfg.bScanReqIsFromWebUI = FALSE; | ||
1424 | |||
1425 | if ((pAd->StaCfg.bAutoReconnect == TRUE) | ||
1426 | && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP) | ||
1427 | && | ||
1428 | (MlmeValidateSSID | ||
1429 | (pAd->MlmeAux.AutoReconnectSsid, | ||
1430 | pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) { | ||
1431 | if ((pAd->ScanTab.BssNr == 0) | ||
1432 | && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)) { | ||
1433 | struct rt_mlme_scan_req ScanReq; | ||
1434 | |||
1435 | if (RTMP_TIME_AFTER | ||
1436 | (pAd->Mlme.Now32, | ||
1437 | pAd->StaCfg.LastScanTime + (10 * OS_HZ))) { | ||
1438 | DBGPRINT(RT_DEBUG_TRACE, | ||
1439 | ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", | ||
1440 | pAd->MlmeAux. | ||
1441 | AutoReconnectSsid)); | ||
1442 | ScanParmFill(pAd, &ScanReq, | ||
1443 | (char *)pAd->MlmeAux. | ||
1444 | AutoReconnectSsid, | ||
1445 | pAd->MlmeAux. | ||
1446 | AutoReconnectSsidLen, | ||
1447 | BSS_ANY, SCAN_ACTIVE); | ||
1448 | MlmeEnqueue(pAd, SYNC_STATE_MACHINE, | ||
1449 | MT2_MLME_SCAN_REQ, | ||
1450 | sizeof | ||
1451 | (struct rt_mlme_scan_req), | ||
1452 | &ScanReq); | ||
1453 | pAd->Mlme.CntlMachine.CurrState = | ||
1454 | CNTL_WAIT_OID_LIST_SCAN; | ||
1455 | /* Reset Missed scan number */ | ||
1456 | pAd->StaCfg.LastScanTime = | ||
1457 | pAd->Mlme.Now32; | ||
1458 | } else if (pAd->StaCfg.BssType == BSS_ADHOC) /* Quit the forever scan when in a very clean room */ | ||
1459 | MlmeAutoReconnectLastSSID(pAd); | ||
1460 | } else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) { | ||
1461 | if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0) { | ||
1462 | MlmeAutoScan(pAd); | ||
1463 | pAd->StaCfg.LastScanTime = | ||
1464 | pAd->Mlme.Now32; | ||
1465 | } else { | ||
1466 | MlmeAutoReconnectLastSSID(pAd); | ||
1467 | } | ||
1468 | } | ||
1469 | } | ||
1470 | } | ||
1471 | |||
1472 | SKIP_AUTO_SCAN_CONN: | ||
1473 | |||
1474 | if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap != 0) | ||
1475 | && (pAd->MacTab.fAnyBASession == FALSE)) { | ||
1476 | pAd->MacTab.fAnyBASession = TRUE; | ||
1477 | AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, | ||
1478 | FALSE); | ||
1479 | } else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap == 0) | ||
1480 | && (pAd->MacTab.fAnyBASession == TRUE)) { | ||
1481 | pAd->MacTab.fAnyBASession = FALSE; | ||
1482 | AsicUpdateProtect(pAd, | ||
1483 | pAd->MlmeAux.AddHtInfo.AddHtInfo2. | ||
1484 | OperaionMode, ALLN_SETPROTECT, FALSE, FALSE); | ||
1485 | } | ||
1486 | |||
1487 | return; | ||
1488 | } | ||
1489 | |||
1490 | /* Link down report */ | ||
1491 | void LinkDownExec(void *SystemSpecific1, | ||
1492 | void *FunctionContext, | ||
1493 | void *SystemSpecific2, void *SystemSpecific3) | ||
1494 | { | ||
1495 | struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; | ||
1496 | |||
1497 | if (pAd != NULL) { | ||
1498 | struct rt_mlme_disassoc_req DisassocReq; | ||
1499 | |||
1500 | if ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) && | ||
1501 | (INFRA_ON(pAd))) { | ||
1502 | DBGPRINT(RT_DEBUG_TRACE, | ||
1503 | ("LinkDownExec(): disassociate with current AP...\n")); | ||
1504 | DisassocParmFill(pAd, &DisassocReq, | ||
1505 | pAd->CommonCfg.Bssid, | ||
1506 | REASON_DISASSOC_STA_LEAVING); | ||
1507 | MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, | ||
1508 | MT2_MLME_DISASSOC_REQ, | ||
1509 | sizeof(struct rt_mlme_disassoc_req), | ||
1510 | &DisassocReq); | ||
1511 | pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; | ||
1512 | |||
1513 | pAd->IndicateMediaState = NdisMediaStateDisconnected; | ||
1514 | RTMP_IndicateMediaState(pAd); | ||
1515 | pAd->ExtraInfo = GENERAL_LINK_DOWN; | ||
1516 | } | ||
1517 | } | ||
1518 | } | ||
1519 | |||
1520 | /* IRQL = DISPATCH_LEVEL */ | ||
1521 | void MlmeAutoScan(struct rt_rtmp_adapter *pAd) | ||
1522 | { | ||
1523 | /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */ | ||
1524 | if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) { | ||
1525 | DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n")); | ||
1526 | MlmeEnqueue(pAd, | ||
1527 | MLME_CNTL_STATE_MACHINE, | ||
1528 | OID_802_11_BSSID_LIST_SCAN, | ||
1529 | pAd->MlmeAux.AutoReconnectSsidLen, | ||
1530 | pAd->MlmeAux.AutoReconnectSsid); | ||
1531 | RTMP_MLME_HANDLER(pAd); | ||
1532 | } | ||
1533 | } | ||
1534 | |||
1535 | /* IRQL = DISPATCH_LEVEL */ | ||
1536 | void MlmeAutoReconnectLastSSID(struct rt_rtmp_adapter *pAd) | ||
1537 | { | ||
1538 | if (pAd->StaCfg.bAutoConnectByBssid) { | ||
1539 | DBGPRINT(RT_DEBUG_TRACE, | ||
1540 | ("Driver auto reconnect to last OID_802_11_BSSID " | ||
1541 | "setting - %pM\n", pAd->MlmeAux.Bssid)); | ||
1542 | |||
1543 | pAd->MlmeAux.Channel = pAd->CommonCfg.Channel; | ||
1544 | MlmeEnqueue(pAd, | ||
1545 | MLME_CNTL_STATE_MACHINE, | ||
1546 | OID_802_11_BSSID, MAC_ADDR_LEN, pAd->MlmeAux.Bssid); | ||
1547 | |||
1548 | pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; | ||
1549 | |||
1550 | RTMP_MLME_HANDLER(pAd); | ||
1551 | } | ||
1552 | /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */ | ||
1553 | else if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) && | ||
1554 | (MlmeValidateSSID | ||
1555 | (pAd->MlmeAux.AutoReconnectSsid, | ||
1556 | pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) { | ||
1557 | struct rt_ndis_802_11_ssid OidSsid; | ||
1558 | OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen; | ||
1559 | NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, | ||
1560 | pAd->MlmeAux.AutoReconnectSsidLen); | ||
1561 | |||
1562 | DBGPRINT(RT_DEBUG_TRACE, | ||
1563 | ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", | ||
1564 | pAd->MlmeAux.AutoReconnectSsid, | ||
1565 | pAd->MlmeAux.AutoReconnectSsidLen)); | ||
1566 | MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, OID_802_11_SSID, | ||
1567 | sizeof(struct rt_ndis_802_11_ssid), &OidSsid); | ||
1568 | RTMP_MLME_HANDLER(pAd); | ||
1569 | } | ||
1570 | } | ||
1571 | |||
1572 | /* | ||
1573 | ========================================================================== | ||
1574 | Description: | ||
1575 | This routine checks if there're other APs out there capable for | ||
1576 | roaming. Caller should call this routine only when Link up in INFRA mode | ||
1577 | and channel quality is below CQI_GOOD_THRESHOLD. | ||
1578 | |||
1579 | IRQL = DISPATCH_LEVEL | ||
1580 | |||
1581 | Output: | ||
1582 | ========================================================================== | ||
1583 | */ | ||
1584 | void MlmeCheckForRoaming(struct rt_rtmp_adapter *pAd, unsigned long Now32) | ||
1585 | { | ||
1586 | u16 i; | ||
1587 | struct rt_bss_table *pRoamTab = &pAd->MlmeAux.RoamTab; | ||
1588 | struct rt_bss_entry *pBss; | ||
1589 | |||
1590 | DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n")); | ||
1591 | /* put all roaming candidates into RoamTab, and sort in RSSI order */ | ||
1592 | BssTableInit(pRoamTab); | ||
1593 | for (i = 0; i < pAd->ScanTab.BssNr; i++) { | ||
1594 | pBss = &pAd->ScanTab.BssEntry[i]; | ||
1595 | |||
1596 | if ((pBss->LastBeaconRxTime + pAd->StaCfg.BeaconLostTime) < | ||
1597 | Now32) | ||
1598 | continue; /* AP disappear */ | ||
1599 | if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING) | ||
1600 | continue; /* RSSI too weak. forget it. */ | ||
1601 | if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid)) | ||
1602 | continue; /* skip current AP */ | ||
1603 | if (pBss->Rssi < | ||
1604 | (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA)) | ||
1605 | continue; /* only AP with stronger RSSI is eligible for roaming */ | ||
1606 | |||
1607 | /* AP passing all above rules is put into roaming candidate table */ | ||
1608 | NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, | ||
1609 | sizeof(struct rt_bss_entry)); | ||
1610 | pRoamTab->BssNr += 1; | ||
1611 | } | ||
1612 | |||
1613 | if (pRoamTab->BssNr > 0) { | ||
1614 | /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */ | ||
1615 | if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) { | ||
1616 | pAd->RalinkCounters.PoorCQIRoamingCount++; | ||
1617 | DBGPRINT(RT_DEBUG_TRACE, | ||
1618 | ("MMCHK - Roaming attempt #%ld\n", | ||
1619 | pAd->RalinkCounters.PoorCQIRoamingCount)); | ||
1620 | MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, | ||
1621 | MT2_MLME_ROAMING_REQ, 0, NULL); | ||
1622 | RTMP_MLME_HANDLER(pAd); | ||
1623 | } | ||
1624 | } | ||
1625 | DBGPRINT(RT_DEBUG_TRACE, | ||
1626 | ("<== MlmeCheckForRoaming(# of candidate= %d)\n", | ||
1627 | pRoamTab->BssNr)); | ||
1628 | } | ||
1629 | |||
1630 | /* | ||
1631 | ========================================================================== | ||
1632 | Description: | ||
1633 | This routine checks if there're other APs out there capable for | ||
1634 | roaming. Caller should call this routine only when link up in INFRA mode | ||
1635 | and channel quality is below CQI_GOOD_THRESHOLD. | ||
1636 | |||
1637 | IRQL = DISPATCH_LEVEL | ||
1638 | |||
1639 | Output: | ||
1640 | ========================================================================== | ||
1641 | */ | ||
1642 | BOOLEAN MlmeCheckForFastRoaming(struct rt_rtmp_adapter *pAd) | ||
1643 | { | ||
1644 | u16 i; | ||
1645 | struct rt_bss_table *pRoamTab = &pAd->MlmeAux.RoamTab; | ||
1646 | struct rt_bss_entry *pBss; | ||
1647 | |||
1648 | DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n")); | ||
1649 | /* put all roaming candidates into RoamTab, and sort in RSSI order */ | ||
1650 | BssTableInit(pRoamTab); | ||
1651 | for (i = 0; i < pAd->ScanTab.BssNr; i++) { | ||
1652 | pBss = &pAd->ScanTab.BssEntry[i]; | ||
1653 | |||
1654 | if ((pBss->Rssi <= -50) | ||
1655 | && (pBss->Channel == pAd->CommonCfg.Channel)) | ||
1656 | continue; /* RSSI too weak. forget it. */ | ||
1657 | if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid)) | ||
1658 | continue; /* skip current AP */ | ||
1659 | if (!SSID_EQUAL | ||
1660 | (pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, | ||
1661 | pAd->CommonCfg.SsidLen)) | ||
1662 | continue; /* skip different SSID */ | ||
1663 | if (pBss->Rssi < | ||
1664 | (RTMPMaxRssi | ||
1665 | (pAd, pAd->StaCfg.RssiSample.LastRssi0, | ||
1666 | pAd->StaCfg.RssiSample.LastRssi1, | ||
1667 | pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA)) | ||
1668 | continue; /* skip AP without better RSSI */ | ||
1669 | |||
1670 | DBGPRINT(RT_DEBUG_TRACE, | ||
1671 | ("LastRssi0 = %d, pBss->Rssi = %d\n", | ||
1672 | RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, | ||
1673 | pAd->StaCfg.RssiSample.LastRssi1, | ||
1674 | pAd->StaCfg.RssiSample.LastRssi2), | ||
1675 | pBss->Rssi)); | ||
1676 | /* AP passing all above rules is put into roaming candidate table */ | ||
1677 | NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, | ||
1678 | sizeof(struct rt_bss_entry)); | ||
1679 | pRoamTab->BssNr += 1; | ||
1680 | } | ||
1681 | |||
1682 | DBGPRINT(RT_DEBUG_TRACE, | ||
1683 | ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr)); | ||
1684 | if (pRoamTab->BssNr > 0) { | ||
1685 | /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */ | ||
1686 | if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) { | ||
1687 | pAd->RalinkCounters.PoorCQIRoamingCount++; | ||
1688 | DBGPRINT(RT_DEBUG_TRACE, | ||
1689 | ("MMCHK - Roaming attempt #%ld\n", | ||
1690 | pAd->RalinkCounters.PoorCQIRoamingCount)); | ||
1691 | MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, | ||
1692 | MT2_MLME_ROAMING_REQ, 0, NULL); | ||
1693 | RTMP_MLME_HANDLER(pAd); | ||
1694 | return TRUE; | ||
1695 | } | ||
1696 | } | ||
1697 | |||
1698 | return FALSE; | ||
1699 | } | ||
1700 | |||
1701 | void MlmeSetTxRate(struct rt_rtmp_adapter *pAd, | ||
1702 | struct rt_mac_table_entry *pEntry, struct rt_rtmp_tx_rate_switch * pTxRate) | ||
1703 | { | ||
1704 | u8 MaxMode = MODE_OFDM; | ||
1705 | |||
1706 | MaxMode = MODE_HTGREENFIELD; | ||
1707 | |||
1708 | if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) | ||
1709 | && (pAd->Antenna.field.TxPath == 2)) | ||
1710 | pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE; | ||
1711 | else | ||
1712 | pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE; | ||
1713 | |||
1714 | if (pTxRate->CurrMCS < MCS_AUTO) | ||
1715 | pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS; | ||
1716 | |||
1717 | if (pAd->StaCfg.HTPhyMode.field.MCS > 7) | ||
1718 | pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE; | ||
1719 | |||
1720 | if (ADHOC_ON(pAd)) { | ||
1721 | /* If peer adhoc is b-only mode, we can't send 11g rate. */ | ||
1722 | pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; | ||
1723 | pEntry->HTPhyMode.field.STBC = STBC_NONE; | ||
1724 | |||
1725 | /* */ | ||
1726 | /* For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary */ | ||
1727 | /* */ | ||
1728 | pEntry->HTPhyMode.field.MODE = pTxRate->Mode; | ||
1729 | pEntry->HTPhyMode.field.ShortGI = | ||
1730 | pAd->StaCfg.HTPhyMode.field.ShortGI; | ||
1731 | pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; | ||
1732 | |||
1733 | /* Patch speed error in status page */ | ||
1734 | pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE; | ||
1735 | } else { | ||
1736 | if (pTxRate->Mode <= MaxMode) | ||
1737 | pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode; | ||
1738 | |||
1739 | if (pTxRate->ShortGI | ||
1740 | && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI)) | ||
1741 | pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400; | ||
1742 | else | ||
1743 | pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; | ||
1744 | |||
1745 | /* Reexam each bandwidth's SGI support. */ | ||
1746 | if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400) { | ||
1747 | if ((pEntry->HTPhyMode.field.BW == BW_20) | ||
1748 | && | ||
1749 | (!CLIENT_STATUS_TEST_FLAG | ||
1750 | (pEntry, fCLIENT_STATUS_SGI20_CAPABLE))) | ||
1751 | pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; | ||
1752 | if ((pEntry->HTPhyMode.field.BW == BW_40) | ||
1753 | && | ||
1754 | (!CLIENT_STATUS_TEST_FLAG | ||
1755 | (pEntry, fCLIENT_STATUS_SGI40_CAPABLE))) | ||
1756 | pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; | ||
1757 | } | ||
1758 | /* Turn RTS/CTS rate to 6Mbps. */ | ||
1759 | if ((pEntry->HTPhyMode.field.MCS == 0) | ||
1760 | && (pAd->StaCfg.HTPhyMode.field.MCS != 0)) { | ||
1761 | pEntry->HTPhyMode.field.MCS = | ||
1762 | pAd->StaCfg.HTPhyMode.field.MCS; | ||
1763 | if (pAd->MacTab.fAnyBASession) { | ||
1764 | AsicUpdateProtect(pAd, HT_FORCERTSCTS, | ||
1765 | ALLN_SETPROTECT, TRUE, | ||
1766 | (BOOLEAN) pAd->MlmeAux. | ||
1767 | AddHtInfo.AddHtInfo2. | ||
1768 | NonGfPresent); | ||
1769 | } else { | ||
1770 | AsicUpdateProtect(pAd, | ||
1771 | pAd->MlmeAux.AddHtInfo. | ||
1772 | AddHtInfo2.OperaionMode, | ||
1773 | ALLN_SETPROTECT, TRUE, | ||
1774 | (BOOLEAN) pAd->MlmeAux. | ||
1775 | AddHtInfo.AddHtInfo2. | ||
1776 | NonGfPresent); | ||
1777 | } | ||
1778 | } else if ((pEntry->HTPhyMode.field.MCS == 8) | ||
1779 | && (pAd->StaCfg.HTPhyMode.field.MCS != 8)) { | ||
1780 | pEntry->HTPhyMode.field.MCS = | ||
1781 | pAd->StaCfg.HTPhyMode.field.MCS; | ||
1782 | if (pAd->MacTab.fAnyBASession) { | ||
1783 | AsicUpdateProtect(pAd, HT_FORCERTSCTS, | ||
1784 | ALLN_SETPROTECT, TRUE, | ||
1785 | (BOOLEAN) pAd->MlmeAux. | ||
1786 | AddHtInfo.AddHtInfo2. | ||
1787 | NonGfPresent); | ||
1788 | } else { | ||
1789 | AsicUpdateProtect(pAd, | ||
1790 | pAd->MlmeAux.AddHtInfo. | ||
1791 | AddHtInfo2.OperaionMode, | ||
1792 | ALLN_SETPROTECT, TRUE, | ||
1793 | (BOOLEAN) pAd->MlmeAux. | ||
1794 | AddHtInfo.AddHtInfo2. | ||
1795 | NonGfPresent); | ||
1796 | } | ||
1797 | } else if ((pEntry->HTPhyMode.field.MCS != 0) | ||
1798 | && (pAd->StaCfg.HTPhyMode.field.MCS == 0)) { | ||
1799 | AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, | ||
1800 | TRUE, | ||
1801 | (BOOLEAN) pAd->MlmeAux.AddHtInfo. | ||
1802 | AddHtInfo2.NonGfPresent); | ||
1803 | |||
1804 | } else if ((pEntry->HTPhyMode.field.MCS != 8) | ||
1805 | && (pAd->StaCfg.HTPhyMode.field.MCS == 8)) { | ||
1806 | AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, | ||
1807 | TRUE, | ||
1808 | (BOOLEAN) pAd->MlmeAux.AddHtInfo. | ||
1809 | AddHtInfo2.NonGfPresent); | ||
1810 | } | ||
1811 | |||
1812 | pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC; | ||
1813 | pEntry->HTPhyMode.field.ShortGI = | ||
1814 | pAd->StaCfg.HTPhyMode.field.ShortGI; | ||
1815 | pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; | ||
1816 | pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE; | ||
1817 | if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) | ||
1818 | && pAd->WIFItestbed.bGreenField) | ||
1819 | pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD; | ||
1820 | } | ||
1821 | |||
1822 | pAd->LastTxRate = (u16)(pEntry->HTPhyMode.word); | ||
1823 | } | ||
1824 | |||
1825 | /* | ||
1826 | ========================================================================== | ||
1827 | Description: | ||
1828 | This routine calculates the acumulated TxPER of eaxh TxRate. And | ||
1829 | according to the calculation result, change CommonCfg.TxRate which | ||
1830 | is the stable TX Rate we expect the Radio situation could sustained. | ||
1831 | |||
1832 | CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate} | ||
1833 | Output: | ||
1834 | CommonCfg.TxRate - | ||
1835 | |||
1836 | IRQL = DISPATCH_LEVEL | ||
1837 | |||
1838 | NOTE: | ||
1839 | call this routine every second | ||
1840 | ========================================================================== | ||
1841 | */ | ||
1842 | void MlmeDynamicTxRateSwitching(struct rt_rtmp_adapter *pAd) | ||
1843 | { | ||
1844 | u8 UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx; | ||
1845 | unsigned long i, AccuTxTotalCnt = 0, TxTotalCnt; | ||
1846 | unsigned long TxErrorRatio = 0; | ||
1847 | BOOLEAN bTxRateChanged = FALSE, bUpgradeQuality = FALSE; | ||
1848 | struct rt_rtmp_tx_rate_switch *pCurrTxRate, *pNextTxRate = NULL; | ||
1849 | u8 *pTable; | ||
1850 | u8 TableSize = 0; | ||
1851 | u8 InitTxRateIdx = 0, TrainUp, TrainDown; | ||
1852 | char Rssi, RssiOffset = 0; | ||
1853 | TX_STA_CNT1_STRUC StaTx1; | ||
1854 | TX_STA_CNT0_STRUC TxStaCnt0; | ||
1855 | unsigned long TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0; | ||
1856 | struct rt_mac_table_entry *pEntry; | ||
1857 | struct rt_rssi_sample *pRssi = &pAd->StaCfg.RssiSample; | ||
1858 | |||
1859 | /* */ | ||
1860 | /* walk through MAC table, see if need to change AP's TX rate toward each entry */ | ||
1861 | /* */ | ||
1862 | for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) { | ||
1863 | pEntry = &pAd->MacTab.Content[i]; | ||
1864 | |||
1865 | /* check if this entry need to switch rate automatically */ | ||
1866 | if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE) | ||
1867 | continue; | ||
1868 | |||
1869 | if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls)) { | ||
1870 | Rssi = RTMPMaxRssi(pAd, | ||
1871 | pRssi->AvgRssi0, | ||
1872 | pRssi->AvgRssi1, pRssi->AvgRssi2); | ||
1873 | |||
1874 | /* Update statistic counter */ | ||
1875 | RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word); | ||
1876 | RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word); | ||
1877 | pAd->bUpdateBcnCntDone = TRUE; | ||
1878 | TxRetransmit = StaTx1.field.TxRetransmit; | ||
1879 | TxSuccess = StaTx1.field.TxSuccess; | ||
1880 | TxFailCount = TxStaCnt0.field.TxFailCount; | ||
1881 | TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; | ||
1882 | |||
1883 | pAd->RalinkCounters.OneSecTxRetryOkCount += | ||
1884 | StaTx1.field.TxRetransmit; | ||
1885 | pAd->RalinkCounters.OneSecTxNoRetryOkCount += | ||
1886 | StaTx1.field.TxSuccess; | ||
1887 | pAd->RalinkCounters.OneSecTxFailCount += | ||
1888 | TxStaCnt0.field.TxFailCount; | ||
1889 | pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += | ||
1890 | StaTx1.field.TxSuccess; | ||
1891 | pAd->WlanCounters.RetryCount.u.LowPart += | ||
1892 | StaTx1.field.TxRetransmit; | ||
1893 | pAd->WlanCounters.FailedCount.u.LowPart += | ||
1894 | TxStaCnt0.field.TxFailCount; | ||
1895 | |||
1896 | /* if no traffic in the past 1-sec period, don't change TX rate, */ | ||
1897 | /* but clear all bad history. because the bad history may affect the next */ | ||
1898 | /* Chariot throughput test */ | ||
1899 | AccuTxTotalCnt = | ||
1900 | pAd->RalinkCounters.OneSecTxNoRetryOkCount + | ||
1901 | pAd->RalinkCounters.OneSecTxRetryOkCount + | ||
1902 | pAd->RalinkCounters.OneSecTxFailCount; | ||
1903 | |||
1904 | if (TxTotalCnt) | ||
1905 | TxErrorRatio = | ||
1906 | ((TxRetransmit + | ||
1907 | TxFailCount) * 100) / TxTotalCnt; | ||
1908 | } else { | ||
1909 | if (INFRA_ON(pAd) && (i == 1)) | ||
1910 | Rssi = RTMPMaxRssi(pAd, | ||
1911 | pRssi->AvgRssi0, | ||
1912 | pRssi->AvgRssi1, | ||
1913 | pRssi->AvgRssi2); | ||
1914 | else | ||
1915 | Rssi = RTMPMaxRssi(pAd, | ||
1916 | pEntry->RssiSample.AvgRssi0, | ||
1917 | pEntry->RssiSample.AvgRssi1, | ||
1918 | pEntry->RssiSample.AvgRssi2); | ||
1919 | |||
1920 | TxTotalCnt = pEntry->OneSecTxNoRetryOkCount + | ||
1921 | pEntry->OneSecTxRetryOkCount + | ||
1922 | pEntry->OneSecTxFailCount; | ||
1923 | |||
1924 | if (TxTotalCnt) | ||
1925 | TxErrorRatio = | ||
1926 | ((pEntry->OneSecTxRetryOkCount + | ||
1927 | pEntry->OneSecTxFailCount) * 100) / | ||
1928 | TxTotalCnt; | ||
1929 | } | ||
1930 | |||
1931 | if (TxTotalCnt) { | ||
1932 | /* | ||
1933 | Three AdHoc connections can not work normally if one AdHoc connection is disappeared from a heavy traffic environment generated by ping tool | ||
1934 | We force to set LongRtyLimit and ShortRtyLimit to 0 to stop retransmitting packet, after a while, resoring original settings | ||
1935 | */ | ||
1936 | if (TxErrorRatio == 100) { | ||
1937 | TX_RTY_CFG_STRUC TxRtyCfg, TxRtyCfgtmp; | ||
1938 | unsigned long Index; | ||
1939 | unsigned long MACValue; | ||
1940 | |||
1941 | RTMP_IO_READ32(pAd, TX_RTY_CFG, &TxRtyCfg.word); | ||
1942 | TxRtyCfgtmp.word = TxRtyCfg.word; | ||
1943 | TxRtyCfg.field.LongRtyLimit = 0x0; | ||
1944 | TxRtyCfg.field.ShortRtyLimit = 0x0; | ||
1945 | RTMP_IO_WRITE32(pAd, TX_RTY_CFG, TxRtyCfg.word); | ||
1946 | |||
1947 | RTMPusecDelay(1); | ||
1948 | |||
1949 | Index = 0; | ||
1950 | MACValue = 0; | ||
1951 | do { | ||
1952 | RTMP_IO_READ32(pAd, TXRXQ_PCNT, | ||
1953 | &MACValue); | ||
1954 | if ((MACValue & 0xffffff) == 0) | ||
1955 | break; | ||
1956 | Index++; | ||
1957 | RTMPusecDelay(1000); | ||
1958 | } while ((Index < 330) | ||
1959 | && | ||
1960 | (!RTMP_TEST_FLAG | ||
1961 | (pAd, | ||
1962 | fRTMP_ADAPTER_HALT_IN_PROGRESS))); | ||
1963 | |||
1964 | RTMP_IO_READ32(pAd, TX_RTY_CFG, &TxRtyCfg.word); | ||
1965 | TxRtyCfg.field.LongRtyLimit = | ||
1966 | TxRtyCfgtmp.field.LongRtyLimit; | ||
1967 | TxRtyCfg.field.ShortRtyLimit = | ||
1968 | TxRtyCfgtmp.field.ShortRtyLimit; | ||
1969 | RTMP_IO_WRITE32(pAd, TX_RTY_CFG, TxRtyCfg.word); | ||
1970 | } | ||
1971 | } | ||
1972 | |||
1973 | CurrRateIdx = pEntry->CurrTxRateIndex; | ||
1974 | |||
1975 | MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, | ||
1976 | &InitTxRateIdx); | ||
1977 | |||
1978 | if (CurrRateIdx >= TableSize) { | ||
1979 | CurrRateIdx = TableSize - 1; | ||
1980 | } | ||
1981 | /* When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex. */ | ||
1982 | /* So need to sync here. */ | ||
1983 | pCurrTxRate = | ||
1984 | (struct rt_rtmp_tx_rate_switch *) & pTable[(CurrRateIdx + 1) * 5]; | ||
1985 | if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS) | ||
1986 | /*&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE) */ | ||
1987 | ) { | ||
1988 | |||
1989 | /* Need to sync Real Tx rate and our record. */ | ||
1990 | /* Then return for next DRS. */ | ||
1991 | pCurrTxRate = | ||
1992 | (struct rt_rtmp_tx_rate_switch *) & pTable[(InitTxRateIdx + 1) | ||
1993 | * 5]; | ||
1994 | pEntry->CurrTxRateIndex = InitTxRateIdx; | ||
1995 | MlmeSetTxRate(pAd, pEntry, pCurrTxRate); | ||
1996 | |||
1997 | /* reset all OneSecTx counters */ | ||
1998 | RESET_ONE_SEC_TX_CNT(pEntry); | ||
1999 | continue; | ||
2000 | } | ||
2001 | /* decide the next upgrade rate and downgrade rate, if any */ | ||
2002 | if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) { | ||
2003 | UpRateIdx = CurrRateIdx + 1; | ||
2004 | DownRateIdx = CurrRateIdx - 1; | ||
2005 | } else if (CurrRateIdx == 0) { | ||
2006 | UpRateIdx = CurrRateIdx + 1; | ||
2007 | DownRateIdx = CurrRateIdx; | ||
2008 | } else if (CurrRateIdx == (TableSize - 1)) { | ||
2009 | UpRateIdx = CurrRateIdx; | ||
2010 | DownRateIdx = CurrRateIdx - 1; | ||
2011 | } | ||
2012 | |||
2013 | pCurrTxRate = | ||
2014 | (struct rt_rtmp_tx_rate_switch *) & pTable[(CurrRateIdx + 1) * 5]; | ||
2015 | |||
2016 | if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) { | ||
2017 | TrainUp = | ||
2018 | (pCurrTxRate->TrainUp + | ||
2019 | (pCurrTxRate->TrainUp >> 1)); | ||
2020 | TrainDown = | ||
2021 | (pCurrTxRate->TrainDown + | ||
2022 | (pCurrTxRate->TrainDown >> 1)); | ||
2023 | } else { | ||
2024 | TrainUp = pCurrTxRate->TrainUp; | ||
2025 | TrainDown = pCurrTxRate->TrainDown; | ||
2026 | } | ||
2027 | |||
2028 | /*pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction; */ | ||
2029 | |||
2030 | /* */ | ||
2031 | /* Keep the last time TxRateChangeAction status. */ | ||
2032 | /* */ | ||
2033 | pEntry->LastTimeTxRateChangeAction = | ||
2034 | pEntry->LastSecTxRateChangeAction; | ||
2035 | |||
2036 | /* */ | ||
2037 | /* CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI */ | ||
2038 | /* (criteria copied from RT2500 for Netopia case) */ | ||
2039 | /* */ | ||
2040 | if (TxTotalCnt <= 15) { | ||
2041 | char idx = 0; | ||
2042 | u8 TxRateIdx; | ||
2043 | u8 MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = | ||
2044 | 0, MCS5 = 0, MCS6 = 0, MCS7 = 0; | ||
2045 | u8 MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0; | ||
2046 | u8 MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; /* 3*3 */ | ||
2047 | |||
2048 | /* check the existence and index of each needed MCS */ | ||
2049 | while (idx < pTable[0]) { | ||
2050 | pCurrTxRate = | ||
2051 | (struct rt_rtmp_tx_rate_switch *) & pTable[(idx + 1) * | ||
2052 | 5]; | ||
2053 | |||
2054 | if (pCurrTxRate->CurrMCS == MCS_0) { | ||
2055 | MCS0 = idx; | ||
2056 | } else if (pCurrTxRate->CurrMCS == MCS_1) { | ||
2057 | MCS1 = idx; | ||
2058 | } else if (pCurrTxRate->CurrMCS == MCS_2) { | ||
2059 | MCS2 = idx; | ||
2060 | } else if (pCurrTxRate->CurrMCS == MCS_3) { | ||
2061 | MCS3 = idx; | ||
2062 | } else if (pCurrTxRate->CurrMCS == MCS_4) { | ||
2063 | MCS4 = idx; | ||
2064 | } else if (pCurrTxRate->CurrMCS == MCS_5) { | ||
2065 | MCS5 = idx; | ||
2066 | } else if (pCurrTxRate->CurrMCS == MCS_6) { | ||
2067 | MCS6 = idx; | ||
2068 | } | ||
2069 | /*else if (pCurrTxRate->CurrMCS == MCS_7) */ | ||
2070 | else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) /* prevent the highest MCS using short GI when 1T and low throughput */ | ||
2071 | { | ||
2072 | MCS7 = idx; | ||
2073 | } else if (pCurrTxRate->CurrMCS == MCS_12) { | ||
2074 | MCS12 = idx; | ||
2075 | } else if (pCurrTxRate->CurrMCS == MCS_13) { | ||
2076 | MCS13 = idx; | ||
2077 | } else if (pCurrTxRate->CurrMCS == MCS_14) { | ||
2078 | MCS14 = idx; | ||
2079 | } | ||
2080 | else if ((pCurrTxRate->CurrMCS == MCS_15) && (pCurrTxRate->ShortGI == GI_800)) /*we hope to use ShortGI as initial rate, however Atheros's chip has bugs when short GI */ | ||
2081 | { | ||
2082 | MCS15 = idx; | ||
2083 | } else if (pCurrTxRate->CurrMCS == MCS_20) /* 3*3 */ | ||
2084 | { | ||
2085 | MCS20 = idx; | ||
2086 | } else if (pCurrTxRate->CurrMCS == MCS_21) { | ||
2087 | MCS21 = idx; | ||
2088 | } else if (pCurrTxRate->CurrMCS == MCS_22) { | ||
2089 | MCS22 = idx; | ||
2090 | } else if (pCurrTxRate->CurrMCS == MCS_23) { | ||
2091 | MCS23 = idx; | ||
2092 | } | ||
2093 | idx++; | ||
2094 | } | ||
2095 | |||
2096 | if (pAd->LatchRfRegs.Channel <= 14) { | ||
2097 | if (pAd->NicConfig2.field.ExternalLNAForG) { | ||
2098 | RssiOffset = 2; | ||
2099 | } else { | ||
2100 | RssiOffset = 5; | ||
2101 | } | ||
2102 | } else { | ||
2103 | if (pAd->NicConfig2.field.ExternalLNAForA) { | ||
2104 | RssiOffset = 5; | ||
2105 | } else { | ||
2106 | RssiOffset = 8; | ||
2107 | } | ||
2108 | } | ||
2109 | |||
2110 | /*if (MCS15) */ | ||
2111 | if ((pTable == RateSwitchTable11BGN3S) || (pTable == RateSwitchTable11N3S) || (pTable == RateSwitchTable)) { /* N mode with 3 stream // 3*3 */ | ||
2112 | if (MCS23 && (Rssi >= -70)) | ||
2113 | TxRateIdx = MCS23; | ||
2114 | else if (MCS22 && (Rssi >= -72)) | ||
2115 | TxRateIdx = MCS22; | ||
2116 | else if (MCS21 && (Rssi >= -76)) | ||
2117 | TxRateIdx = MCS21; | ||
2118 | else if (MCS20 && (Rssi >= -78)) | ||
2119 | TxRateIdx = MCS20; | ||
2120 | else if (MCS4 && (Rssi >= -82)) | ||
2121 | TxRateIdx = MCS4; | ||
2122 | else if (MCS3 && (Rssi >= -84)) | ||
2123 | TxRateIdx = MCS3; | ||
2124 | else if (MCS2 && (Rssi >= -86)) | ||
2125 | TxRateIdx = MCS2; | ||
2126 | else if (MCS1 && (Rssi >= -88)) | ||
2127 | TxRateIdx = MCS1; | ||
2128 | else | ||
2129 | TxRateIdx = MCS0; | ||
2130 | } | ||
2131 | /* else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand) || (pTable == RateSwitchTable)) */ | ||
2132 | else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) || (pTable == RateSwitchTable11N2S) || (pTable == RateSwitchTable11N2SForABand)) /* 3*3 */ | ||
2133 | { /* N mode with 2 stream */ | ||
2134 | if (MCS15 && (Rssi >= (-70 + RssiOffset))) | ||
2135 | TxRateIdx = MCS15; | ||
2136 | else if (MCS14 && (Rssi >= (-72 + RssiOffset))) | ||
2137 | TxRateIdx = MCS14; | ||
2138 | else if (MCS13 && (Rssi >= (-76 + RssiOffset))) | ||
2139 | TxRateIdx = MCS13; | ||
2140 | else if (MCS12 && (Rssi >= (-78 + RssiOffset))) | ||
2141 | TxRateIdx = MCS12; | ||
2142 | else if (MCS4 && (Rssi >= (-82 + RssiOffset))) | ||
2143 | TxRateIdx = MCS4; | ||
2144 | else if (MCS3 && (Rssi >= (-84 + RssiOffset))) | ||
2145 | TxRateIdx = MCS3; | ||
2146 | else if (MCS2 && (Rssi >= (-86 + RssiOffset))) | ||
2147 | TxRateIdx = MCS2; | ||
2148 | else if (MCS1 && (Rssi >= (-88 + RssiOffset))) | ||
2149 | TxRateIdx = MCS1; | ||
2150 | else | ||
2151 | TxRateIdx = MCS0; | ||
2152 | } else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S)) { /* N mode with 1 stream */ | ||
2153 | if (MCS7 && (Rssi > (-72 + RssiOffset))) | ||
2154 | TxRateIdx = MCS7; | ||
2155 | else if (MCS6 && (Rssi > (-74 + RssiOffset))) | ||
2156 | TxRateIdx = MCS6; | ||
2157 | else if (MCS5 && (Rssi > (-77 + RssiOffset))) | ||
2158 | TxRateIdx = MCS5; | ||
2159 | else if (MCS4 && (Rssi > (-79 + RssiOffset))) | ||
2160 | TxRateIdx = MCS4; | ||
2161 | else if (MCS3 && (Rssi > (-81 + RssiOffset))) | ||
2162 | TxRateIdx = MCS3; | ||
2163 | else if (MCS2 && (Rssi > (-83 + RssiOffset))) | ||
2164 | TxRateIdx = MCS2; | ||
2165 | else if (MCS1 && (Rssi > (-86 + RssiOffset))) | ||
2166 | TxRateIdx = MCS1; | ||
2167 | else | ||
2168 | TxRateIdx = MCS0; | ||
2169 | } else { /* Legacy mode */ | ||
2170 | if (MCS7 && (Rssi > -70)) | ||
2171 | TxRateIdx = MCS7; | ||
2172 | else if (MCS6 && (Rssi > -74)) | ||
2173 | TxRateIdx = MCS6; | ||
2174 | else if (MCS5 && (Rssi > -78)) | ||
2175 | TxRateIdx = MCS5; | ||
2176 | else if (MCS4 && (Rssi > -82)) | ||
2177 | TxRateIdx = MCS4; | ||
2178 | else if (MCS4 == 0) /* for B-only mode */ | ||
2179 | TxRateIdx = MCS3; | ||
2180 | else if (MCS3 && (Rssi > -85)) | ||
2181 | TxRateIdx = MCS3; | ||
2182 | else if (MCS2 && (Rssi > -87)) | ||
2183 | TxRateIdx = MCS2; | ||
2184 | else if (MCS1 && (Rssi > -90)) | ||
2185 | TxRateIdx = MCS1; | ||
2186 | else | ||
2187 | TxRateIdx = MCS0; | ||
2188 | } | ||
2189 | |||
2190 | /* if (TxRateIdx != pAd->CommonCfg.TxRateIndex) */ | ||
2191 | { | ||
2192 | pEntry->CurrTxRateIndex = TxRateIdx; | ||
2193 | pNextTxRate = | ||
2194 | (struct rt_rtmp_tx_rate_switch *) & | ||
2195 | pTable[(pEntry->CurrTxRateIndex + 1) * 5]; | ||
2196 | MlmeSetTxRate(pAd, pEntry, pNextTxRate); | ||
2197 | } | ||
2198 | |||
2199 | NdisZeroMemory(pEntry->TxQuality, | ||
2200 | sizeof(u16)* | ||
2201 | MAX_STEP_OF_TX_RATE_SWITCH); | ||
2202 | NdisZeroMemory(pEntry->PER, | ||
2203 | sizeof(u8)* | ||
2204 | MAX_STEP_OF_TX_RATE_SWITCH); | ||
2205 | pEntry->fLastSecAccordingRSSI = TRUE; | ||
2206 | /* reset all OneSecTx counters */ | ||
2207 | RESET_ONE_SEC_TX_CNT(pEntry); | ||
2208 | |||
2209 | continue; | ||
2210 | } | ||
2211 | |||
2212 | if (pEntry->fLastSecAccordingRSSI == TRUE) { | ||
2213 | pEntry->fLastSecAccordingRSSI = FALSE; | ||
2214 | pEntry->LastSecTxRateChangeAction = 0; | ||
2215 | /* reset all OneSecTx counters */ | ||
2216 | RESET_ONE_SEC_TX_CNT(pEntry); | ||
2217 | |||
2218 | continue; | ||
2219 | } | ||
2220 | |||
2221 | do { | ||
2222 | BOOLEAN bTrainUpDown = FALSE; | ||
2223 | |||
2224 | pEntry->CurrTxRateStableTime++; | ||
2225 | |||
2226 | /* downgrade TX quality if PER >= Rate-Down threshold */ | ||
2227 | if (TxErrorRatio >= TrainDown) { | ||
2228 | bTrainUpDown = TRUE; | ||
2229 | pEntry->TxQuality[CurrRateIdx] = | ||
2230 | DRS_TX_QUALITY_WORST_BOUND; | ||
2231 | } | ||
2232 | /* upgrade TX quality if PER <= Rate-Up threshold */ | ||
2233 | else if (TxErrorRatio <= TrainUp) { | ||
2234 | bTrainUpDown = TRUE; | ||
2235 | bUpgradeQuality = TRUE; | ||
2236 | if (pEntry->TxQuality[CurrRateIdx]) | ||
2237 | pEntry->TxQuality[CurrRateIdx]--; /* quality very good in CurrRate */ | ||
2238 | |||
2239 | if (pEntry->TxRateUpPenalty) | ||
2240 | pEntry->TxRateUpPenalty--; | ||
2241 | else if (pEntry->TxQuality[UpRateIdx]) | ||
2242 | pEntry->TxQuality[UpRateIdx]--; /* may improve next UP rate's quality */ | ||
2243 | } | ||
2244 | |||
2245 | pEntry->PER[CurrRateIdx] = (u8)TxErrorRatio; | ||
2246 | |||
2247 | if (bTrainUpDown) { | ||
2248 | /* perform DRS - consider TxRate Down first, then rate up. */ | ||
2249 | if ((CurrRateIdx != DownRateIdx) | ||
2250 | && (pEntry->TxQuality[CurrRateIdx] >= | ||
2251 | DRS_TX_QUALITY_WORST_BOUND)) { | ||
2252 | pEntry->CurrTxRateIndex = DownRateIdx; | ||
2253 | } else if ((CurrRateIdx != UpRateIdx) | ||
2254 | && (pEntry->TxQuality[UpRateIdx] <= | ||
2255 | 0)) { | ||
2256 | pEntry->CurrTxRateIndex = UpRateIdx; | ||
2257 | } | ||
2258 | } | ||
2259 | } while (FALSE); | ||
2260 | |||
2261 | /* if rate-up happen, clear all bad history of all TX rates */ | ||
2262 | if (pEntry->CurrTxRateIndex > CurrRateIdx) { | ||
2263 | pEntry->CurrTxRateStableTime = 0; | ||
2264 | pEntry->TxRateUpPenalty = 0; | ||
2265 | pEntry->LastSecTxRateChangeAction = 1; /* rate UP */ | ||
2266 | NdisZeroMemory(pEntry->TxQuality, | ||
2267 | sizeof(u16)* | ||
2268 | MAX_STEP_OF_TX_RATE_SWITCH); | ||
2269 | NdisZeroMemory(pEntry->PER, | ||
2270 | sizeof(u8)* | ||
2271 | MAX_STEP_OF_TX_RATE_SWITCH); | ||
2272 | |||
2273 | /* */ | ||
2274 | /* For TxRate fast train up */ | ||
2275 | /* */ | ||
2276 | if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) { | ||
2277 | RTMPSetTimer(&pAd->StaCfg. | ||
2278 | StaQuickResponeForRateUpTimer, | ||
2279 | 100); | ||
2280 | |||
2281 | pAd->StaCfg. | ||
2282 | StaQuickResponeForRateUpTimerRunning = TRUE; | ||
2283 | } | ||
2284 | bTxRateChanged = TRUE; | ||
2285 | } | ||
2286 | /* if rate-down happen, only clear DownRate's bad history */ | ||
2287 | else if (pEntry->CurrTxRateIndex < CurrRateIdx) { | ||
2288 | pEntry->CurrTxRateStableTime = 0; | ||
2289 | pEntry->TxRateUpPenalty = 0; /* no penalty */ | ||
2290 | pEntry->LastSecTxRateChangeAction = 2; /* rate DOWN */ | ||
2291 | pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0; | ||
2292 | pEntry->PER[pEntry->CurrTxRateIndex] = 0; | ||
2293 | |||
2294 | /* */ | ||
2295 | /* For TxRate fast train down */ | ||
2296 | /* */ | ||
2297 | if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) { | ||
2298 | RTMPSetTimer(&pAd->StaCfg. | ||
2299 | StaQuickResponeForRateUpTimer, | ||
2300 | 100); | ||
2301 | |||
2302 | pAd->StaCfg. | ||
2303 | StaQuickResponeForRateUpTimerRunning = TRUE; | ||
2304 | } | ||
2305 | bTxRateChanged = TRUE; | ||
2306 | } else { | ||
2307 | pEntry->LastSecTxRateChangeAction = 0; /* rate no change */ | ||
2308 | bTxRateChanged = FALSE; | ||
2309 | } | ||
2310 | |||
2311 | pEntry->LastTxOkCount = TxSuccess; | ||
2312 | { | ||
2313 | u8 tmpTxRate; | ||
2314 | |||
2315 | /* to fix tcp ack issue */ | ||
2316 | if (!bTxRateChanged | ||
2317 | && (pAd->RalinkCounters.OneSecReceivedByteCount > | ||
2318 | (pAd->RalinkCounters. | ||
2319 | OneSecTransmittedByteCount * 5))) { | ||
2320 | tmpTxRate = DownRateIdx; | ||
2321 | DBGPRINT_RAW(RT_DEBUG_TRACE, | ||
2322 | ("DRS: Rx(%d) is 5 times larger than Tx(%d), use low rate (curr=%d, tmp=%d)\n", | ||
2323 | pAd->RalinkCounters. | ||
2324 | OneSecReceivedByteCount, | ||
2325 | pAd->RalinkCounters. | ||
2326 | OneSecTransmittedByteCount, | ||
2327 | pEntry->CurrTxRateIndex, | ||
2328 | tmpTxRate)); | ||
2329 | } else { | ||
2330 | tmpTxRate = pEntry->CurrTxRateIndex; | ||
2331 | } | ||
2332 | |||
2333 | pNextTxRate = | ||
2334 | (struct rt_rtmp_tx_rate_switch *) & pTable[(tmpTxRate + 1) * | ||
2335 | 5]; | ||
2336 | } | ||
2337 | if (bTxRateChanged && pNextTxRate) { | ||
2338 | MlmeSetTxRate(pAd, pEntry, pNextTxRate); | ||
2339 | } | ||
2340 | /* reset all OneSecTx counters */ | ||
2341 | RESET_ONE_SEC_TX_CNT(pEntry); | ||
2342 | } | ||
2343 | } | ||
2344 | |||
2345 | /* | ||
2346 | ======================================================================== | ||
2347 | Routine Description: | ||
2348 | Station side, Auto TxRate faster train up timer call back function. | ||
2349 | |||
2350 | Arguments: | ||
2351 | SystemSpecific1 - Not used. | ||
2352 | FunctionContext - Pointer to our Adapter context. | ||
2353 | SystemSpecific2 - Not used. | ||
2354 | SystemSpecific3 - Not used. | ||
2355 | |||
2356 | Return Value: | ||
2357 | None | ||
2358 | |||
2359 | ======================================================================== | ||
2360 | */ | ||
2361 | void StaQuickResponeForRateUpExec(void *SystemSpecific1, | ||
2362 | void *FunctionContext, | ||
2363 | void *SystemSpecific2, | ||
2364 | void *SystemSpecific3) | ||
2365 | { | ||
2366 | struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; | ||
2367 | u8 UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0; | ||
2368 | unsigned long TxTotalCnt; | ||
2369 | unsigned long TxErrorRatio = 0; | ||
2370 | BOOLEAN bTxRateChanged; /*, bUpgradeQuality = FALSE; */ | ||
2371 | struct rt_rtmp_tx_rate_switch *pCurrTxRate, *pNextTxRate = NULL; | ||
2372 | u8 *pTable; | ||
2373 | u8 TableSize = 0; | ||
2374 | u8 InitTxRateIdx = 0, TrainUp, TrainDown; | ||
2375 | TX_STA_CNT1_STRUC StaTx1; | ||
2376 | TX_STA_CNT0_STRUC TxStaCnt0; | ||
2377 | char Rssi, ratio; | ||
2378 | unsigned long TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0; | ||
2379 | struct rt_mac_table_entry *pEntry; | ||
2380 | unsigned long i; | ||
2381 | |||
2382 | pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE; | ||
2383 | |||
2384 | /* */ | ||
2385 | /* walk through MAC table, see if need to change AP's TX rate toward each entry */ | ||
2386 | /* */ | ||
2387 | for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) { | ||
2388 | pEntry = &pAd->MacTab.Content[i]; | ||
2389 | |||
2390 | /* check if this entry need to switch rate automatically */ | ||
2391 | if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE) | ||
2392 | continue; | ||
2393 | |||
2394 | if (INFRA_ON(pAd) && (i == 1)) | ||
2395 | Rssi = RTMPMaxRssi(pAd, | ||
2396 | pAd->StaCfg.RssiSample.AvgRssi0, | ||
2397 | pAd->StaCfg.RssiSample.AvgRssi1, | ||
2398 | pAd->StaCfg.RssiSample.AvgRssi2); | ||
2399 | else | ||
2400 | Rssi = RTMPMaxRssi(pAd, | ||
2401 | pEntry->RssiSample.AvgRssi0, | ||
2402 | pEntry->RssiSample.AvgRssi1, | ||
2403 | pEntry->RssiSample.AvgRssi2); | ||
2404 | |||
2405 | CurrRateIdx = pAd->CommonCfg.TxRateIndex; | ||
2406 | |||
2407 | MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, | ||
2408 | &InitTxRateIdx); | ||
2409 | |||
2410 | /* decide the next upgrade rate and downgrade rate, if any */ | ||
2411 | if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) { | ||
2412 | UpRateIdx = CurrRateIdx + 1; | ||
2413 | DownRateIdx = CurrRateIdx - 1; | ||
2414 | } else if (CurrRateIdx == 0) { | ||
2415 | UpRateIdx = CurrRateIdx + 1; | ||
2416 | DownRateIdx = CurrRateIdx; | ||
2417 | } else if (CurrRateIdx == (TableSize - 1)) { | ||
2418 | UpRateIdx = CurrRateIdx; | ||
2419 | DownRateIdx = CurrRateIdx - 1; | ||
2420 | } | ||
2421 | |||
2422 | pCurrTxRate = | ||
2423 | (struct rt_rtmp_tx_rate_switch *) & pTable[(CurrRateIdx + 1) * 5]; | ||
2424 | |||
2425 | if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) { | ||
2426 | TrainUp = | ||
2427 | (pCurrTxRate->TrainUp + | ||
2428 | (pCurrTxRate->TrainUp >> 1)); | ||
2429 | TrainDown = | ||
2430 | (pCurrTxRate->TrainDown + | ||
2431 | (pCurrTxRate->TrainDown >> 1)); | ||
2432 | } else { | ||
2433 | TrainUp = pCurrTxRate->TrainUp; | ||
2434 | TrainDown = pCurrTxRate->TrainDown; | ||
2435 | } | ||
2436 | |||
2437 | if (pAd->MacTab.Size == 1) { | ||
2438 | /* Update statistic counter */ | ||
2439 | RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word); | ||
2440 | RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word); | ||
2441 | |||
2442 | TxRetransmit = StaTx1.field.TxRetransmit; | ||
2443 | TxSuccess = StaTx1.field.TxSuccess; | ||
2444 | TxFailCount = TxStaCnt0.field.TxFailCount; | ||
2445 | TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; | ||
2446 | |||
2447 | pAd->RalinkCounters.OneSecTxRetryOkCount += | ||
2448 | StaTx1.field.TxRetransmit; | ||
2449 | pAd->RalinkCounters.OneSecTxNoRetryOkCount += | ||
2450 | StaTx1.field.TxSuccess; | ||
2451 | pAd->RalinkCounters.OneSecTxFailCount += | ||
2452 | TxStaCnt0.field.TxFailCount; | ||
2453 | pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += | ||
2454 | StaTx1.field.TxSuccess; | ||
2455 | pAd->WlanCounters.RetryCount.u.LowPart += | ||
2456 | StaTx1.field.TxRetransmit; | ||
2457 | pAd->WlanCounters.FailedCount.u.LowPart += | ||
2458 | TxStaCnt0.field.TxFailCount; | ||
2459 | |||
2460 | if (TxTotalCnt) | ||
2461 | TxErrorRatio = | ||
2462 | ((TxRetransmit + | ||
2463 | TxFailCount) * 100) / TxTotalCnt; | ||
2464 | } else { | ||
2465 | TxTotalCnt = pEntry->OneSecTxNoRetryOkCount + | ||
2466 | pEntry->OneSecTxRetryOkCount + | ||
2467 | pEntry->OneSecTxFailCount; | ||
2468 | |||
2469 | if (TxTotalCnt) | ||
2470 | TxErrorRatio = | ||
2471 | ((pEntry->OneSecTxRetryOkCount + | ||
2472 | pEntry->OneSecTxFailCount) * 100) / | ||
2473 | TxTotalCnt; | ||
2474 | } | ||
2475 | |||
2476 | /* */ | ||
2477 | /* CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI */ | ||
2478 | /* (criteria copied from RT2500 for Netopia case) */ | ||
2479 | /* */ | ||
2480 | if (TxTotalCnt <= 12) { | ||
2481 | NdisZeroMemory(pAd->DrsCounters.TxQuality, | ||
2482 | sizeof(u16)* | ||
2483 | MAX_STEP_OF_TX_RATE_SWITCH); | ||
2484 | NdisZeroMemory(pAd->DrsCounters.PER, | ||
2485 | sizeof(u8)* | ||
2486 | MAX_STEP_OF_TX_RATE_SWITCH); | ||
2487 | |||
2488 | if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) | ||
2489 | && (CurrRateIdx != DownRateIdx)) { | ||
2490 | pAd->CommonCfg.TxRateIndex = DownRateIdx; | ||
2491 | pAd->DrsCounters.TxQuality[CurrRateIdx] = | ||
2492 | DRS_TX_QUALITY_WORST_BOUND; | ||
2493 | } else | ||
2494 | if ((pAd->DrsCounters.LastSecTxRateChangeAction == | ||
2495 | 2) && (CurrRateIdx != UpRateIdx)) { | ||
2496 | pAd->CommonCfg.TxRateIndex = UpRateIdx; | ||
2497 | } | ||
2498 | |||
2499 | DBGPRINT_RAW(RT_DEBUG_TRACE, | ||
2500 | ("QuickDRS: TxTotalCnt <= 15, train back to original rate \n")); | ||
2501 | return; | ||
2502 | } | ||
2503 | |||
2504 | do { | ||
2505 | unsigned long OneSecTxNoRetryOKRationCount; | ||
2506 | |||
2507 | if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0) | ||
2508 | ratio = 5; | ||
2509 | else | ||
2510 | ratio = 4; | ||
2511 | |||
2512 | /* downgrade TX quality if PER >= Rate-Down threshold */ | ||
2513 | if (TxErrorRatio >= TrainDown) { | ||
2514 | pAd->DrsCounters.TxQuality[CurrRateIdx] = | ||
2515 | DRS_TX_QUALITY_WORST_BOUND; | ||
2516 | } | ||
2517 | |||
2518 | pAd->DrsCounters.PER[CurrRateIdx] = | ||
2519 | (u8)TxErrorRatio; | ||
2520 | |||
2521 | OneSecTxNoRetryOKRationCount = (TxSuccess * ratio); | ||
2522 | |||
2523 | /* perform DRS - consider TxRate Down first, then rate up. */ | ||
2524 | if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) | ||
2525 | && (CurrRateIdx != DownRateIdx)) { | ||
2526 | if ((pAd->DrsCounters.LastTxOkCount + 2) >= | ||
2527 | OneSecTxNoRetryOKRationCount) { | ||
2528 | pAd->CommonCfg.TxRateIndex = | ||
2529 | DownRateIdx; | ||
2530 | pAd->DrsCounters. | ||
2531 | TxQuality[CurrRateIdx] = | ||
2532 | DRS_TX_QUALITY_WORST_BOUND; | ||
2533 | |||
2534 | } | ||
2535 | |||
2536 | } else | ||
2537 | if ((pAd->DrsCounters.LastSecTxRateChangeAction == | ||
2538 | 2) && (CurrRateIdx != UpRateIdx)) { | ||
2539 | if ((TxErrorRatio >= 50) | ||
2540 | || (TxErrorRatio >= TrainDown)) { | ||
2541 | |||
2542 | } else if ((pAd->DrsCounters.LastTxOkCount + 2) | ||
2543 | >= OneSecTxNoRetryOKRationCount) { | ||
2544 | pAd->CommonCfg.TxRateIndex = UpRateIdx; | ||
2545 | } | ||
2546 | } | ||
2547 | } while (FALSE); | ||
2548 | |||
2549 | /* if rate-up happen, clear all bad history of all TX rates */ | ||
2550 | if (pAd->CommonCfg.TxRateIndex > CurrRateIdx) { | ||
2551 | pAd->DrsCounters.TxRateUpPenalty = 0; | ||
2552 | NdisZeroMemory(pAd->DrsCounters.TxQuality, | ||
2553 | sizeof(u16)* | ||
2554 | MAX_STEP_OF_TX_RATE_SWITCH); | ||
2555 | NdisZeroMemory(pAd->DrsCounters.PER, | ||
2556 | sizeof(u8)* | ||
2557 | MAX_STEP_OF_TX_RATE_SWITCH); | ||
2558 | bTxRateChanged = TRUE; | ||
2559 | } | ||
2560 | /* if rate-down happen, only clear DownRate's bad history */ | ||
2561 | else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx) { | ||
2562 | DBGPRINT_RAW(RT_DEBUG_TRACE, | ||
2563 | ("QuickDRS: --TX rate from %d to %d \n", | ||
2564 | CurrRateIdx, pAd->CommonCfg.TxRateIndex)); | ||
2565 | |||
2566 | pAd->DrsCounters.TxRateUpPenalty = 0; /* no penalty */ | ||
2567 | pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = | ||
2568 | 0; | ||
2569 | pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0; | ||
2570 | bTxRateChanged = TRUE; | ||
2571 | } else { | ||
2572 | bTxRateChanged = FALSE; | ||
2573 | } | ||
2574 | |||
2575 | pNextTxRate = | ||
2576 | (struct rt_rtmp_tx_rate_switch *) & | ||
2577 | pTable[(pAd->CommonCfg.TxRateIndex + 1) * 5]; | ||
2578 | if (bTxRateChanged && pNextTxRate) { | ||
2579 | MlmeSetTxRate(pAd, pEntry, pNextTxRate); | ||
2580 | } | ||
2581 | } | ||
2582 | } | ||
2583 | |||
2584 | /* | ||
2585 | ========================================================================== | ||
2586 | Description: | ||
2587 | This routine is executed periodically inside MlmePeriodicExec() after | ||
2588 | association with an AP. | ||
2589 | It checks if StaCfg.Psm is consistent with user policy (recorded in | ||
2590 | StaCfg.WindowsPowerMode). If not, enforce user policy. However, | ||
2591 | there're some conditions to consider: | ||
2592 | 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all | ||
2593 | the time when Mibss==TRUE | ||
2594 | 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE | ||
2595 | if outgoing traffic available in TxRing or MgmtRing. | ||
2596 | Output: | ||
2597 | 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched | ||
2598 | |||
2599 | IRQL = DISPATCH_LEVEL | ||
2600 | |||
2601 | ========================================================================== | ||
2602 | */ | ||
2603 | void MlmeCheckPsmChange(struct rt_rtmp_adapter *pAd, unsigned long Now32) | ||
2604 | { | ||
2605 | unsigned long PowerMode; | ||
2606 | |||
2607 | /* condition - */ | ||
2608 | /* 1. Psm maybe ON only happen in INFRASTRUCTURE mode */ | ||
2609 | /* 2. user wants either MAX_PSP or FAST_PSP */ | ||
2610 | /* 3. but current psm is not in PWR_SAVE */ | ||
2611 | /* 4. CNTL state machine is not doing SCANning */ | ||
2612 | /* 5. no TX SUCCESS event for the past 1-sec period */ | ||
2613 | PowerMode = pAd->StaCfg.WindowsPowerMode; | ||
2614 | |||
2615 | if (INFRA_ON(pAd) && | ||
2616 | (PowerMode != Ndis802_11PowerModeCAM) && | ||
2617 | (pAd->StaCfg.Psm == PWR_ACTIVE) && | ||
2618 | /* (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) */ | ||
2619 | (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) && | ||
2620 | RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP) | ||
2621 | /*&& | ||
2622 | (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) && | ||
2623 | (pAd->RalinkCounters.OneSecTxRetryOkCount == 0) */ | ||
2624 | ) { | ||
2625 | NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime); | ||
2626 | pAd->RalinkCounters.RxCountSinceLastNULL = 0; | ||
2627 | RTMP_SET_PSM_BIT(pAd, PWR_SAVE); | ||
2628 | if (! | ||
2629 | (pAd->CommonCfg.bAPSDCapable | ||
2630 | && pAd->CommonCfg.APEdcaParm.bAPSDCapable)) { | ||
2631 | RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE); | ||
2632 | } else { | ||
2633 | RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE); | ||
2634 | } | ||
2635 | } | ||
2636 | } | ||
2637 | |||
2638 | /* IRQL = PASSIVE_LEVEL */ | ||
2639 | /* IRQL = DISPATCH_LEVEL */ | ||
2640 | void MlmeSetPsmBit(struct rt_rtmp_adapter *pAd, u16 psm) | ||
2641 | { | ||
2642 | AUTO_RSP_CFG_STRUC csr4; | ||
2643 | |||
2644 | pAd->StaCfg.Psm = psm; | ||
2645 | RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word); | ||
2646 | csr4.field.AckCtsPsmBit = (psm == PWR_SAVE) ? 1 : 0; | ||
2647 | RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word); | ||
2648 | |||
2649 | DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm)); | ||
2650 | } | ||
2651 | |||
2652 | /* | ||
2653 | ========================================================================== | ||
2654 | Description: | ||
2655 | This routine calculates TxPER, RxPER of the past N-sec period. And | ||
2656 | according to the calculation result, ChannelQuality is calculated here | ||
2657 | to decide if current AP is still doing the job. | ||
2658 | |||
2659 | If ChannelQuality is not good, a ROAMing attempt may be tried later. | ||
2660 | Output: | ||
2661 | StaCfg.ChannelQuality - 0..100 | ||
2662 | |||
2663 | IRQL = DISPATCH_LEVEL | ||
2664 | |||
2665 | NOTE: This routine decide channle quality based on RX CRC error ratio. | ||
2666 | Caller should make sure a function call to NICUpdateRawCounters(pAd) | ||
2667 | is performed right before this routine, so that this routine can decide | ||
2668 | channel quality based on the most up-to-date information | ||
2669 | ========================================================================== | ||
2670 | */ | ||
2671 | void MlmeCalculateChannelQuality(struct rt_rtmp_adapter *pAd, | ||
2672 | struct rt_mac_table_entry *pMacEntry, unsigned long Now32) | ||
2673 | { | ||
2674 | unsigned long TxOkCnt, TxCnt, TxPER, TxPRR; | ||
2675 | unsigned long RxCnt, RxPER; | ||
2676 | u8 NorRssi; | ||
2677 | char MaxRssi; | ||
2678 | struct rt_rssi_sample *pRssiSample = NULL; | ||
2679 | u32 OneSecTxNoRetryOkCount = 0; | ||
2680 | u32 OneSecTxRetryOkCount = 0; | ||
2681 | u32 OneSecTxFailCount = 0; | ||
2682 | u32 OneSecRxOkCnt = 0; | ||
2683 | u32 OneSecRxFcsErrCnt = 0; | ||
2684 | unsigned long ChannelQuality = 0; /* 0..100, Channel Quality Indication for Roaming */ | ||
2685 | unsigned long BeaconLostTime = pAd->StaCfg.BeaconLostTime; | ||
2686 | |||
2687 | if (pAd->OpMode == OPMODE_STA) { | ||
2688 | pRssiSample = &pAd->StaCfg.RssiSample; | ||
2689 | OneSecTxNoRetryOkCount = | ||
2690 | pAd->RalinkCounters.OneSecTxNoRetryOkCount; | ||
2691 | OneSecTxRetryOkCount = pAd->RalinkCounters.OneSecTxRetryOkCount; | ||
2692 | OneSecTxFailCount = pAd->RalinkCounters.OneSecTxFailCount; | ||
2693 | OneSecRxOkCnt = pAd->RalinkCounters.OneSecRxOkCnt; | ||
2694 | OneSecRxFcsErrCnt = pAd->RalinkCounters.OneSecRxFcsErrCnt; | ||
2695 | } | ||
2696 | |||
2697 | MaxRssi = RTMPMaxRssi(pAd, pRssiSample->LastRssi0, | ||
2698 | pRssiSample->LastRssi1, pRssiSample->LastRssi2); | ||
2699 | |||
2700 | /* */ | ||
2701 | /* calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics */ | ||
2702 | /* */ | ||
2703 | TxOkCnt = OneSecTxNoRetryOkCount + OneSecTxRetryOkCount; | ||
2704 | TxCnt = TxOkCnt + OneSecTxFailCount; | ||
2705 | if (TxCnt < 5) { | ||
2706 | TxPER = 0; | ||
2707 | TxPRR = 0; | ||
2708 | } else { | ||
2709 | TxPER = (OneSecTxFailCount * 100) / TxCnt; | ||
2710 | TxPRR = ((TxCnt - OneSecTxNoRetryOkCount) * 100) / TxCnt; | ||
2711 | } | ||
2712 | |||
2713 | /* */ | ||
2714 | /* calculate RX PER - don't take RxPER into consideration if too few sample */ | ||
2715 | /* */ | ||
2716 | RxCnt = OneSecRxOkCnt + OneSecRxFcsErrCnt; | ||
2717 | if (RxCnt < 5) | ||
2718 | RxPER = 0; | ||
2719 | else | ||
2720 | RxPER = (OneSecRxFcsErrCnt * 100) / RxCnt; | ||
2721 | |||
2722 | /* */ | ||
2723 | /* decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER */ | ||
2724 | /* */ | ||
2725 | if ((pAd->OpMode == OPMODE_STA) && INFRA_ON(pAd) && (OneSecTxNoRetryOkCount < 2) && /* no heavy traffic */ | ||
2726 | ((pAd->StaCfg.LastBeaconRxTime + BeaconLostTime) < Now32)) { | ||
2727 | DBGPRINT(RT_DEBUG_TRACE, | ||
2728 | ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", | ||
2729 | BeaconLostTime, TxOkCnt)); | ||
2730 | ChannelQuality = 0; | ||
2731 | } else { | ||
2732 | /* Normalize Rssi */ | ||
2733 | if (MaxRssi > -40) | ||
2734 | NorRssi = 100; | ||
2735 | else if (MaxRssi < -90) | ||
2736 | NorRssi = 0; | ||
2737 | else | ||
2738 | NorRssi = (MaxRssi + 90) * 2; | ||
2739 | |||
2740 | /* ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0) */ | ||
2741 | ChannelQuality = (RSSI_WEIGHTING * NorRssi + | ||
2742 | TX_WEIGHTING * (100 - TxPRR) + | ||
2743 | RX_WEIGHTING * (100 - RxPER)) / 100; | ||
2744 | } | ||
2745 | |||
2746 | if (pAd->OpMode == OPMODE_STA) | ||
2747 | pAd->Mlme.ChannelQuality = | ||
2748 | (ChannelQuality > 100) ? 100 : ChannelQuality; | ||
2749 | |||
2750 | } | ||
2751 | |||
2752 | /* IRQL = DISPATCH_LEVEL */ | ||
2753 | void MlmeSetTxPreamble(struct rt_rtmp_adapter *pAd, u16 TxPreamble) | ||
2754 | { | ||
2755 | AUTO_RSP_CFG_STRUC csr4; | ||
2756 | |||
2757 | /* */ | ||
2758 | /* Always use Long preamble before verifiation short preamble functionality works well. */ | ||
2759 | /* Todo: remove the following line if short preamble functionality works */ | ||
2760 | /* */ | ||
2761 | /*TxPreamble = Rt802_11PreambleLong; */ | ||
2762 | |||
2763 | RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word); | ||
2764 | if (TxPreamble == Rt802_11PreambleLong) { | ||
2765 | DBGPRINT(RT_DEBUG_TRACE, | ||
2766 | ("MlmeSetTxPreamble (= long PREAMBLE)\n")); | ||
2767 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); | ||
2768 | csr4.field.AutoResponderPreamble = 0; | ||
2769 | } else { | ||
2770 | /* NOTE: 1Mbps should always use long preamble */ | ||
2771 | DBGPRINT(RT_DEBUG_TRACE, | ||
2772 | ("MlmeSetTxPreamble (= short PREAMBLE)\n")); | ||
2773 | OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); | ||
2774 | csr4.field.AutoResponderPreamble = 1; | ||
2775 | } | ||
2776 | |||
2777 | RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word); | ||
2778 | } | ||
2779 | |||
2780 | /* | ||
2781 | ========================================================================== | ||
2782 | Description: | ||
2783 | Update basic rate bitmap | ||
2784 | ========================================================================== | ||
2785 | */ | ||
2786 | |||
2787 | void UpdateBasicRateBitmap(struct rt_rtmp_adapter *pAdapter) | ||
2788 | { | ||
2789 | int i, j; | ||
2790 | /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */ | ||
2791 | u8 rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 }; | ||
2792 | u8 *sup_p = pAdapter->CommonCfg.SupRate; | ||
2793 | u8 *ext_p = pAdapter->CommonCfg.ExtRate; | ||
2794 | unsigned long bitmap = pAdapter->CommonCfg.BasicRateBitmap; | ||
2795 | |||
2796 | /* if A mode, always use fix BasicRateBitMap */ | ||
2797 | /*if (pAdapter->CommonCfg.Channel == PHY_11A) */ | ||
2798 | if (pAdapter->CommonCfg.Channel > 14) | ||
2799 | pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */ | ||
2800 | /* End of if */ | ||
2801 | |||
2802 | if (pAdapter->CommonCfg.BasicRateBitmap > 4095) { | ||
2803 | /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */ | ||
2804 | return; | ||
2805 | } | ||
2806 | /* End of if */ | ||
2807 | for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) { | ||
2808 | sup_p[i] &= 0x7f; | ||
2809 | ext_p[i] &= 0x7f; | ||
2810 | } /* End of for */ | ||
2811 | |||
2812 | for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) { | ||
2813 | if (bitmap & (1 << i)) { | ||
2814 | for (j = 0; j < MAX_LEN_OF_SUPPORTED_RATES; j++) { | ||
2815 | if (sup_p[j] == rate[i]) | ||
2816 | sup_p[j] |= 0x80; | ||
2817 | /* End of if */ | ||
2818 | } /* End of for */ | ||
2819 | |||
2820 | for (j = 0; j < MAX_LEN_OF_SUPPORTED_RATES; j++) { | ||
2821 | if (ext_p[j] == rate[i]) | ||
2822 | ext_p[j] |= 0x80; | ||
2823 | /* End of if */ | ||
2824 | } /* End of for */ | ||
2825 | } /* End of if */ | ||
2826 | } /* End of for */ | ||
2827 | } /* End of UpdateBasicRateBitmap */ | ||
2828 | |||
2829 | /* IRQL = PASSIVE_LEVEL */ | ||
2830 | /* IRQL = DISPATCH_LEVEL */ | ||
2831 | /* bLinkUp is to identify the initial link speed. */ | ||
2832 | /* TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps. */ | ||
2833 | void MlmeUpdateTxRates(struct rt_rtmp_adapter *pAd, IN BOOLEAN bLinkUp, u8 apidx) | ||
2834 | { | ||
2835 | int i, num; | ||
2836 | u8 Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1; | ||
2837 | u8 MinSupport = RATE_54; | ||
2838 | unsigned long BasicRateBitmap = 0; | ||
2839 | u8 CurrBasicRate = RATE_1; | ||
2840 | u8 *pSupRate, SupRateLen, *pExtRate, ExtRateLen; | ||
2841 | PHTTRANSMIT_SETTING pHtPhy = NULL; | ||
2842 | PHTTRANSMIT_SETTING pMaxHtPhy = NULL; | ||
2843 | PHTTRANSMIT_SETTING pMinHtPhy = NULL; | ||
2844 | BOOLEAN *auto_rate_cur_p; | ||
2845 | u8 HtMcs = MCS_AUTO; | ||
2846 | |||
2847 | /* find max desired rate */ | ||
2848 | UpdateBasicRateBitmap(pAd); | ||
2849 | |||
2850 | num = 0; | ||
2851 | auto_rate_cur_p = NULL; | ||
2852 | for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) { | ||
2853 | switch (pAd->CommonCfg.DesireRate[i] & 0x7f) { | ||
2854 | case 2: | ||
2855 | Rate = RATE_1; | ||
2856 | num++; | ||
2857 | break; | ||
2858 | case 4: | ||
2859 | Rate = RATE_2; | ||
2860 | num++; | ||
2861 | break; | ||
2862 | case 11: | ||
2863 | Rate = RATE_5_5; | ||
2864 | num++; | ||
2865 | break; | ||
2866 | case 22: | ||
2867 | Rate = RATE_11; | ||
2868 | num++; | ||
2869 | break; | ||
2870 | case 12: | ||
2871 | Rate = RATE_6; | ||
2872 | num++; | ||
2873 | break; | ||
2874 | case 18: | ||
2875 | Rate = RATE_9; | ||
2876 | num++; | ||
2877 | break; | ||
2878 | case 24: | ||
2879 | Rate = RATE_12; | ||
2880 | num++; | ||
2881 | break; | ||
2882 | case 36: | ||
2883 | Rate = RATE_18; | ||
2884 | num++; | ||
2885 | break; | ||
2886 | case 48: | ||
2887 | Rate = RATE_24; | ||
2888 | num++; | ||
2889 | break; | ||
2890 | case 72: | ||
2891 | Rate = RATE_36; | ||
2892 | num++; | ||
2893 | break; | ||
2894 | case 96: | ||
2895 | Rate = RATE_48; | ||
2896 | num++; | ||
2897 | break; | ||
2898 | case 108: | ||
2899 | Rate = RATE_54; | ||
2900 | num++; | ||
2901 | break; | ||
2902 | /*default: Rate = RATE_1; break; */ | ||
2903 | } | ||
2904 | if (MaxDesire < Rate) | ||
2905 | MaxDesire = Rate; | ||
2906 | } | ||
2907 | |||
2908 | /*=========================================================================== */ | ||
2909 | /*=========================================================================== */ | ||
2910 | { | ||
2911 | pHtPhy = &pAd->StaCfg.HTPhyMode; | ||
2912 | pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode; | ||
2913 | pMinHtPhy = &pAd->StaCfg.MinHTPhyMode; | ||
2914 | |||
2915 | auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch; | ||
2916 | HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS; | ||
2917 | |||
2918 | if ((pAd->StaCfg.BssType == BSS_ADHOC) && | ||
2919 | (pAd->CommonCfg.PhyMode == PHY_11B) && | ||
2920 | (MaxDesire > RATE_11)) { | ||
2921 | MaxDesire = RATE_11; | ||
2922 | } | ||
2923 | } | ||
2924 | |||
2925 | pAd->CommonCfg.MaxDesiredRate = MaxDesire; | ||
2926 | pMinHtPhy->word = 0; | ||
2927 | pMaxHtPhy->word = 0; | ||
2928 | pHtPhy->word = 0; | ||
2929 | |||
2930 | /* Auto rate switching is enabled only if more than one DESIRED RATES are */ | ||
2931 | /* specified; otherwise disabled */ | ||
2932 | if (num <= 1) { | ||
2933 | /*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */ | ||
2934 | /*pAd->CommonCfg.bAutoTxRateSwitch = FALSE; */ | ||
2935 | *auto_rate_cur_p = FALSE; | ||
2936 | } else { | ||
2937 | /*OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */ | ||
2938 | /*pAd->CommonCfg.bAutoTxRateSwitch = TRUE; */ | ||
2939 | *auto_rate_cur_p = TRUE; | ||
2940 | } | ||
2941 | |||
2942 | if (HtMcs != MCS_AUTO) { | ||
2943 | /*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */ | ||
2944 | /*pAd->CommonCfg.bAutoTxRateSwitch = FALSE; */ | ||
2945 | *auto_rate_cur_p = FALSE; | ||
2946 | } else { | ||
2947 | /*OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */ | ||
2948 | /*pAd->CommonCfg.bAutoTxRateSwitch = TRUE; */ | ||
2949 | *auto_rate_cur_p = TRUE; | ||
2950 | } | ||
2951 | |||
2952 | if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) { | ||
2953 | pSupRate = &pAd->StaActive.SupRate[0]; | ||
2954 | pExtRate = &pAd->StaActive.ExtRate[0]; | ||
2955 | SupRateLen = pAd->StaActive.SupRateLen; | ||
2956 | ExtRateLen = pAd->StaActive.ExtRateLen; | ||
2957 | } else { | ||
2958 | pSupRate = &pAd->CommonCfg.SupRate[0]; | ||
2959 | pExtRate = &pAd->CommonCfg.ExtRate[0]; | ||
2960 | SupRateLen = pAd->CommonCfg.SupRateLen; | ||
2961 | ExtRateLen = pAd->CommonCfg.ExtRateLen; | ||
2962 | } | ||
2963 | |||
2964 | /* find max supported rate */ | ||
2965 | for (i = 0; i < SupRateLen; i++) { | ||
2966 | switch (pSupRate[i] & 0x7f) { | ||
2967 | case 2: | ||
2968 | Rate = RATE_1; | ||
2969 | if (pSupRate[i] & 0x80) | ||
2970 | BasicRateBitmap |= 0x0001; | ||
2971 | break; | ||
2972 | case 4: | ||
2973 | Rate = RATE_2; | ||
2974 | if (pSupRate[i] & 0x80) | ||
2975 | BasicRateBitmap |= 0x0002; | ||
2976 | break; | ||
2977 | case 11: | ||
2978 | Rate = RATE_5_5; | ||
2979 | if (pSupRate[i] & 0x80) | ||
2980 | BasicRateBitmap |= 0x0004; | ||
2981 | break; | ||
2982 | case 22: | ||
2983 | Rate = RATE_11; | ||
2984 | if (pSupRate[i] & 0x80) | ||
2985 | BasicRateBitmap |= 0x0008; | ||
2986 | break; | ||
2987 | case 12: | ||
2988 | Rate = RATE_6; /*if (pSupRate[i] & 0x80) */ | ||
2989 | BasicRateBitmap |= 0x0010; | ||
2990 | break; | ||
2991 | case 18: | ||
2992 | Rate = RATE_9; | ||
2993 | if (pSupRate[i] & 0x80) | ||
2994 | BasicRateBitmap |= 0x0020; | ||
2995 | break; | ||
2996 | case 24: | ||
2997 | Rate = RATE_12; /*if (pSupRate[i] & 0x80) */ | ||
2998 | BasicRateBitmap |= 0x0040; | ||
2999 | break; | ||
3000 | case 36: | ||
3001 | Rate = RATE_18; | ||
3002 | if (pSupRate[i] & 0x80) | ||
3003 | BasicRateBitmap |= 0x0080; | ||
3004 | break; | ||
3005 | case 48: | ||
3006 | Rate = RATE_24; /*if (pSupRate[i] & 0x80) */ | ||
3007 | BasicRateBitmap |= 0x0100; | ||
3008 | break; | ||
3009 | case 72: | ||
3010 | Rate = RATE_36; | ||
3011 | if (pSupRate[i] & 0x80) | ||
3012 | BasicRateBitmap |= 0x0200; | ||
3013 | break; | ||
3014 | case 96: | ||
3015 | Rate = RATE_48; | ||
3016 | if (pSupRate[i] & 0x80) | ||
3017 | BasicRateBitmap |= 0x0400; | ||
3018 | break; | ||
3019 | case 108: | ||
3020 | Rate = RATE_54; | ||
3021 | if (pSupRate[i] & 0x80) | ||
3022 | BasicRateBitmap |= 0x0800; | ||
3023 | break; | ||
3024 | default: | ||
3025 | Rate = RATE_1; | ||
3026 | break; | ||
3027 | } | ||
3028 | if (MaxSupport < Rate) | ||
3029 | MaxSupport = Rate; | ||
3030 | |||
3031 | if (MinSupport > Rate) | ||
3032 | MinSupport = Rate; | ||
3033 | } | ||
3034 | |||
3035 | for (i = 0; i < ExtRateLen; i++) { | ||
3036 | switch (pExtRate[i] & 0x7f) { | ||
3037 | case 2: | ||
3038 | Rate = RATE_1; | ||
3039 | if (pExtRate[i] & 0x80) | ||
3040 | BasicRateBitmap |= 0x0001; | ||
3041 | break; | ||
3042 | case 4: | ||
3043 | Rate = RATE_2; | ||
3044 | if (pExtRate[i] & 0x80) | ||
3045 | BasicRateBitmap |= 0x0002; | ||
3046 | break; | ||
3047 | case 11: | ||
3048 | Rate = RATE_5_5; | ||
3049 | if (pExtRate[i] & 0x80) | ||
3050 | BasicRateBitmap |= 0x0004; | ||
3051 | break; | ||
3052 | case 22: | ||
3053 | Rate = RATE_11; | ||
3054 | if (pExtRate[i] & 0x80) | ||
3055 | BasicRateBitmap |= 0x0008; | ||
3056 | break; | ||
3057 | case 12: | ||
3058 | Rate = RATE_6; /*if (pExtRate[i] & 0x80) */ | ||
3059 | BasicRateBitmap |= 0x0010; | ||
3060 | break; | ||
3061 | case 18: | ||
3062 | Rate = RATE_9; | ||
3063 | if (pExtRate[i] & 0x80) | ||
3064 | BasicRateBitmap |= 0x0020; | ||
3065 | break; | ||
3066 | case 24: | ||
3067 | Rate = RATE_12; /*if (pExtRate[i] & 0x80) */ | ||
3068 | BasicRateBitmap |= 0x0040; | ||
3069 | break; | ||
3070 | case 36: | ||
3071 | Rate = RATE_18; | ||
3072 | if (pExtRate[i] & 0x80) | ||
3073 | BasicRateBitmap |= 0x0080; | ||
3074 | break; | ||
3075 | case 48: | ||
3076 | Rate = RATE_24; /*if (pExtRate[i] & 0x80) */ | ||
3077 | BasicRateBitmap |= 0x0100; | ||
3078 | break; | ||
3079 | case 72: | ||
3080 | Rate = RATE_36; | ||
3081 | if (pExtRate[i] & 0x80) | ||
3082 | BasicRateBitmap |= 0x0200; | ||
3083 | break; | ||
3084 | case 96: | ||
3085 | Rate = RATE_48; | ||
3086 | if (pExtRate[i] & 0x80) | ||
3087 | BasicRateBitmap |= 0x0400; | ||
3088 | break; | ||
3089 | case 108: | ||
3090 | Rate = RATE_54; | ||
3091 | if (pExtRate[i] & 0x80) | ||
3092 | BasicRateBitmap |= 0x0800; | ||
3093 | break; | ||
3094 | default: | ||
3095 | Rate = RATE_1; | ||
3096 | break; | ||
3097 | } | ||
3098 | if (MaxSupport < Rate) | ||
3099 | MaxSupport = Rate; | ||
3100 | |||
3101 | if (MinSupport > Rate) | ||
3102 | MinSupport = Rate; | ||
3103 | } | ||
3104 | |||
3105 | RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap); | ||
3106 | |||
3107 | /* bug fix */ | ||
3108 | /* pAd->CommonCfg.BasicRateBitmap = BasicRateBitmap; */ | ||
3109 | |||
3110 | /* calculate the exptected ACK rate for each TX rate. This info is used to caculate */ | ||
3111 | /* the DURATION field of outgoing uniicast DATA/MGMT frame */ | ||
3112 | for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) { | ||
3113 | if (BasicRateBitmap & (0x01 << i)) | ||
3114 | CurrBasicRate = (u8)i; | ||
3115 | pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate; | ||
3116 | } | ||
3117 | |||
3118 | DBGPRINT(RT_DEBUG_TRACE, | ||
3119 | ("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", | ||
3120 | RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire])); | ||
3121 | /* max tx rate = min {max desire rate, max supported rate} */ | ||
3122 | if (MaxSupport < MaxDesire) | ||
3123 | pAd->CommonCfg.MaxTxRate = MaxSupport; | ||
3124 | else | ||
3125 | pAd->CommonCfg.MaxTxRate = MaxDesire; | ||
3126 | |||
3127 | pAd->CommonCfg.MinTxRate = MinSupport; | ||
3128 | /* 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success */ | ||
3129 | /* ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending */ | ||
3130 | /* on average RSSI */ | ||
3131 | /* 1. RSSI >= -70db, start at 54 Mbps (short distance) */ | ||
3132 | /* 2. -70 > RSSI >= -75, start at 24 Mbps (mid distance) */ | ||
3133 | /* 3. -75 > RSSI, start at 11 Mbps (long distance) */ | ||
3134 | if (*auto_rate_cur_p) { | ||
3135 | short dbm = 0; | ||
3136 | |||
3137 | dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta; | ||
3138 | |||
3139 | if (bLinkUp == TRUE) | ||
3140 | pAd->CommonCfg.TxRate = RATE_24; | ||
3141 | else | ||
3142 | pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; | ||
3143 | |||
3144 | if (dbm < -75) | ||
3145 | pAd->CommonCfg.TxRate = RATE_11; | ||
3146 | else if (dbm < -70) | ||
3147 | pAd->CommonCfg.TxRate = RATE_24; | ||
3148 | |||
3149 | /* should never exceed MaxTxRate (consider 11B-only mode) */ | ||
3150 | if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate) | ||
3151 | pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; | ||
3152 | |||
3153 | pAd->CommonCfg.TxRateIndex = 0; | ||
3154 | } else { | ||
3155 | pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; | ||
3156 | pHtPhy->field.MCS = | ||
3157 | (pAd->CommonCfg.MaxTxRate > | ||
3158 | 3) ? (pAd->CommonCfg.MaxTxRate - | ||
3159 | 4) : pAd->CommonCfg.MaxTxRate; | ||
3160 | pHtPhy->field.MODE = | ||
3161 | (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK; | ||
3162 | |||
3163 | pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = | ||
3164 | pHtPhy->field.STBC; | ||
3165 | pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = | ||
3166 | pHtPhy->field.ShortGI; | ||
3167 | pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = | ||
3168 | pHtPhy->field.MCS; | ||
3169 | pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = | ||
3170 | pHtPhy->field.MODE; | ||
3171 | } | ||
3172 | |||
3173 | if (pAd->CommonCfg.TxRate <= RATE_11) { | ||
3174 | pMaxHtPhy->field.MODE = MODE_CCK; | ||
3175 | pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate; | ||
3176 | pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate; | ||
3177 | } else { | ||
3178 | pMaxHtPhy->field.MODE = MODE_OFDM; | ||
3179 | pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate]; | ||
3180 | if (pAd->CommonCfg.MinTxRate >= RATE_6 | ||
3181 | && (pAd->CommonCfg.MinTxRate <= RATE_54)) { | ||
3182 | pMinHtPhy->field.MCS = | ||
3183 | OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate]; | ||
3184 | } else { | ||
3185 | pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate; | ||
3186 | } | ||
3187 | } | ||
3188 | |||
3189 | pHtPhy->word = (pMaxHtPhy->word); | ||
3190 | if (bLinkUp && (pAd->OpMode == OPMODE_STA)) { | ||
3191 | pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word; | ||
3192 | pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = | ||
3193 | pMaxHtPhy->word; | ||
3194 | pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = | ||
3195 | pMinHtPhy->word; | ||
3196 | } else { | ||
3197 | switch (pAd->CommonCfg.PhyMode) { | ||
3198 | case PHY_11BG_MIXED: | ||
3199 | case PHY_11B: | ||
3200 | case PHY_11BGN_MIXED: | ||
3201 | pAd->CommonCfg.MlmeRate = RATE_1; | ||
3202 | pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; | ||
3203 | pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1; | ||
3204 | |||
3205 | /*#ifdef WIFI_TEST */ | ||
3206 | pAd->CommonCfg.RtsRate = RATE_11; | ||
3207 | /*#else */ | ||
3208 | /* pAd->CommonCfg.RtsRate = RATE_1; */ | ||
3209 | /*#endif */ | ||
3210 | break; | ||
3211 | case PHY_11G: | ||
3212 | case PHY_11A: | ||
3213 | case PHY_11AGN_MIXED: | ||
3214 | case PHY_11GN_MIXED: | ||
3215 | case PHY_11N_2_4G: | ||
3216 | case PHY_11AN_MIXED: | ||
3217 | case PHY_11N_5G: | ||
3218 | pAd->CommonCfg.MlmeRate = RATE_6; | ||
3219 | pAd->CommonCfg.RtsRate = RATE_6; | ||
3220 | pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; | ||
3221 | pAd->CommonCfg.MlmeTransmit.field.MCS = | ||
3222 | OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; | ||
3223 | break; | ||
3224 | case PHY_11ABG_MIXED: | ||
3225 | case PHY_11ABGN_MIXED: | ||
3226 | if (pAd->CommonCfg.Channel <= 14) { | ||
3227 | pAd->CommonCfg.MlmeRate = RATE_1; | ||
3228 | pAd->CommonCfg.RtsRate = RATE_1; | ||
3229 | pAd->CommonCfg.MlmeTransmit.field.MODE = | ||
3230 | MODE_CCK; | ||
3231 | pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1; | ||
3232 | } else { | ||
3233 | pAd->CommonCfg.MlmeRate = RATE_6; | ||
3234 | pAd->CommonCfg.RtsRate = RATE_6; | ||
3235 | pAd->CommonCfg.MlmeTransmit.field.MODE = | ||
3236 | MODE_OFDM; | ||
3237 | pAd->CommonCfg.MlmeTransmit.field.MCS = | ||
3238 | OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; | ||
3239 | } | ||
3240 | break; | ||
3241 | default: /* error */ | ||
3242 | pAd->CommonCfg.MlmeRate = RATE_6; | ||
3243 | pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; | ||
3244 | pAd->CommonCfg.MlmeTransmit.field.MCS = | ||
3245 | OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; | ||
3246 | pAd->CommonCfg.RtsRate = RATE_1; | ||
3247 | break; | ||
3248 | } | ||
3249 | /* */ | ||
3250 | /* Keep Basic Mlme Rate. */ | ||
3251 | /* */ | ||
3252 | pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = | ||
3253 | pAd->CommonCfg.MlmeTransmit.word; | ||
3254 | if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM) | ||
3255 | pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = | ||
3256 | OfdmRateToRxwiMCS[RATE_24]; | ||
3257 | else | ||
3258 | pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = | ||
3259 | RATE_1; | ||
3260 | pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate; | ||
3261 | } | ||
3262 | |||
3263 | DBGPRINT(RT_DEBUG_TRACE, | ||
3264 | (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n", | ||
3265 | RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], | ||
3266 | RateIdToMbps[pAd->CommonCfg.MaxTxRate], | ||
3267 | RateIdToMbps[pAd->CommonCfg.MinTxRate], | ||
3268 | /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED) */ | ||
3269 | *auto_rate_cur_p)); | ||
3270 | DBGPRINT(RT_DEBUG_TRACE, | ||
3271 | (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n", | ||
3272 | RateIdToMbps[pAd->CommonCfg.TxRate], | ||
3273 | RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap)); | ||
3274 | DBGPRINT(RT_DEBUG_TRACE, | ||
3275 | ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n", | ||
3276 | pAd->CommonCfg.MlmeTransmit.word, | ||
3277 | pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word, | ||
3278 | pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word, | ||
3279 | pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word)); | ||
3280 | } | ||
3281 | |||
3282 | /* | ||
3283 | ========================================================================== | ||
3284 | Description: | ||
3285 | This function update HT Rate setting. | ||
3286 | Input Wcid value is valid for 2 case : | ||
3287 | 1. it's used for Station in infra mode that copy AP rate to Mactable. | ||
3288 | 2. OR Station in adhoc mode to copy peer's HT rate to Mactable. | ||
3289 | |||
3290 | IRQL = DISPATCH_LEVEL | ||
3291 | |||
3292 | ========================================================================== | ||
3293 | */ | ||
3294 | void MlmeUpdateHtTxRates(struct rt_rtmp_adapter *pAd, u8 apidx) | ||
3295 | { | ||
3296 | u8 StbcMcs; /*j, StbcMcs, bitmask; */ | ||
3297 | char i; /* 3*3 */ | ||
3298 | struct rt_ht_capability *pRtHtCap = NULL; | ||
3299 | struct rt_ht_phy_info *pActiveHtPhy = NULL; | ||
3300 | unsigned long BasicMCS; | ||
3301 | u8 j, bitmask; | ||
3302 | struct rt_ht_phy_info *pDesireHtPhy = NULL; | ||
3303 | PHTTRANSMIT_SETTING pHtPhy = NULL; | ||
3304 | PHTTRANSMIT_SETTING pMaxHtPhy = NULL; | ||
3305 | PHTTRANSMIT_SETTING pMinHtPhy = NULL; | ||
3306 | BOOLEAN *auto_rate_cur_p; | ||
3307 | |||
3308 | DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateHtTxRates===> \n")); | ||
3309 | |||
3310 | auto_rate_cur_p = NULL; | ||
3311 | |||
3312 | { | ||
3313 | pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo; | ||
3314 | pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo; | ||
3315 | pHtPhy = &pAd->StaCfg.HTPhyMode; | ||
3316 | pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode; | ||
3317 | pMinHtPhy = &pAd->StaCfg.MinHTPhyMode; | ||
3318 | |||
3319 | auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch; | ||
3320 | } | ||
3321 | |||
3322 | if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) { | ||
3323 | if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) | ||
3324 | return; | ||
3325 | |||
3326 | pRtHtCap = &pAd->StaActive.SupportedHtPhy; | ||
3327 | pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo; | ||
3328 | StbcMcs = (u8)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs; | ||
3329 | BasicMCS = | ||
3330 | pAd->MlmeAux.AddHtInfo.MCSSet[0] + | ||
3331 | (pAd->MlmeAux.AddHtInfo.MCSSet[1] << 8) + (StbcMcs << 16); | ||
3332 | if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) | ||
3333 | && (pAd->Antenna.field.TxPath == 2)) | ||
3334 | pMaxHtPhy->field.STBC = STBC_USE; | ||
3335 | else | ||
3336 | pMaxHtPhy->field.STBC = STBC_NONE; | ||
3337 | } else { | ||
3338 | if (pDesireHtPhy->bHtEnable == FALSE) | ||
3339 | return; | ||
3340 | |||
3341 | pRtHtCap = &pAd->CommonCfg.DesiredHtPhy; | ||
3342 | StbcMcs = (u8)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs; | ||
3343 | BasicMCS = | ||
3344 | pAd->CommonCfg.AddHTInfo.MCSSet[0] + | ||
3345 | (pAd->CommonCfg.AddHTInfo.MCSSet[1] << 8) + (StbcMcs << 16); | ||
3346 | if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) | ||
3347 | && (pAd->Antenna.field.TxPath == 2)) | ||
3348 | pMaxHtPhy->field.STBC = STBC_USE; | ||
3349 | else | ||
3350 | pMaxHtPhy->field.STBC = STBC_NONE; | ||
3351 | } | ||
3352 | |||
3353 | /* Decide MAX ht rate. */ | ||
3354 | if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF)) | ||
3355 | pMaxHtPhy->field.MODE = MODE_HTGREENFIELD; | ||
3356 | else | ||
3357 | pMaxHtPhy->field.MODE = MODE_HTMIX; | ||
3358 | |||
3359 | if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) | ||
3360 | && (pRtHtCap->ChannelWidth)) | ||
3361 | pMaxHtPhy->field.BW = BW_40; | ||
3362 | else | ||
3363 | pMaxHtPhy->field.BW = BW_20; | ||
3364 | |||
3365 | if (pMaxHtPhy->field.BW == BW_20) | ||
3366 | pMaxHtPhy->field.ShortGI = | ||
3367 | (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap-> | ||
3368 | ShortGIfor20); | ||
3369 | else | ||
3370 | pMaxHtPhy->field.ShortGI = | ||
3371 | (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap-> | ||
3372 | ShortGIfor40); | ||
3373 | |||
3374 | if (pDesireHtPhy->MCSSet[4] != 0) { | ||
3375 | pMaxHtPhy->field.MCS = 32; | ||
3376 | } | ||
3377 | |||
3378 | for (i = 23; i >= 0; i--) /* 3*3 */ | ||
3379 | { | ||
3380 | j = i / 8; | ||
3381 | bitmask = (1 << (i - (j * 8))); | ||
3382 | |||
3383 | if ((pActiveHtPhy->MCSSet[j] & bitmask) | ||
3384 | && (pDesireHtPhy->MCSSet[j] & bitmask)) { | ||
3385 | pMaxHtPhy->field.MCS = i; | ||
3386 | break; | ||
3387 | } | ||
3388 | |||
3389 | if (i == 0) | ||
3390 | break; | ||
3391 | } | ||
3392 | |||
3393 | /* Copy MIN ht rate. rt2860??? */ | ||
3394 | pMinHtPhy->field.BW = BW_20; | ||
3395 | pMinHtPhy->field.MCS = 0; | ||
3396 | pMinHtPhy->field.STBC = 0; | ||
3397 | pMinHtPhy->field.ShortGI = 0; | ||
3398 | /*If STA assigns fixed rate. update to fixed here. */ | ||
3399 | if ((pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff)) { | ||
3400 | if (pDesireHtPhy->MCSSet[4] != 0) { | ||
3401 | pMaxHtPhy->field.MCS = 32; | ||
3402 | pMinHtPhy->field.MCS = 32; | ||
3403 | DBGPRINT(RT_DEBUG_TRACE, | ||
3404 | ("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n", | ||
3405 | pMinHtPhy->field.MCS)); | ||
3406 | } | ||
3407 | |||
3408 | for (i = 23; (char)i >= 0; i--) /* 3*3 */ | ||
3409 | { | ||
3410 | j = i / 8; | ||
3411 | bitmask = (1 << (i - (j * 8))); | ||
3412 | if ((pDesireHtPhy->MCSSet[j] & bitmask) | ||
3413 | && (pActiveHtPhy->MCSSet[j] & bitmask)) { | ||
3414 | pMaxHtPhy->field.MCS = i; | ||
3415 | pMinHtPhy->field.MCS = i; | ||
3416 | break; | ||
3417 | } | ||
3418 | if (i == 0) | ||
3419 | break; | ||
3420 | } | ||
3421 | } | ||
3422 | |||
3423 | /* Decide ht rate */ | ||
3424 | pHtPhy->field.STBC = pMaxHtPhy->field.STBC; | ||
3425 | pHtPhy->field.BW = pMaxHtPhy->field.BW; | ||
3426 | pHtPhy->field.MODE = pMaxHtPhy->field.MODE; | ||
3427 | pHtPhy->field.MCS = pMaxHtPhy->field.MCS; | ||
3428 | pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI; | ||
3429 | |||
3430 | /* use default now. rt2860 */ | ||
3431 | if (pDesireHtPhy->MCSSet[0] != 0xff) | ||
3432 | *auto_rate_cur_p = FALSE; | ||
3433 | else | ||
3434 | *auto_rate_cur_p = TRUE; | ||
3435 | |||
3436 | DBGPRINT(RT_DEBUG_TRACE, | ||
3437 | (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", | ||
3438 | pAd->CommonCfg.DesiredHtPhy.AmsduSize)); | ||
3439 | DBGPRINT(RT_DEBUG_TRACE, | ||
3440 | ("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", | ||
3441 | pActiveHtPhy->MCSSet[0], pHtPhy->field.MCS, pHtPhy->field.BW, | ||
3442 | pHtPhy->field.ShortGI, pHtPhy->field.MODE)); | ||
3443 | DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateHtTxRates<=== \n")); | ||
3444 | } | ||
3445 | |||
3446 | void BATableInit(struct rt_rtmp_adapter *pAd, struct rt_ba_table *Tab) | ||
3447 | { | ||
3448 | int i; | ||
3449 | |||
3450 | Tab->numAsOriginator = 0; | ||
3451 | Tab->numAsRecipient = 0; | ||
3452 | Tab->numDoneOriginator = 0; | ||
3453 | NdisAllocateSpinLock(&pAd->BATabLock); | ||
3454 | for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) { | ||
3455 | Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE; | ||
3456 | NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock)); | ||
3457 | } | ||
3458 | for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++) { | ||
3459 | Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE; | ||
3460 | } | ||
3461 | } | ||
3462 | |||
3463 | /* IRQL = DISPATCH_LEVEL */ | ||
3464 | void MlmeRadioOff(struct rt_rtmp_adapter *pAd) | ||
3465 | { | ||
3466 | RTMP_MLME_RADIO_OFF(pAd); | ||
3467 | } | ||
3468 | |||
3469 | /* IRQL = DISPATCH_LEVEL */ | ||
3470 | void MlmeRadioOn(struct rt_rtmp_adapter *pAd) | ||
3471 | { | ||
3472 | RTMP_MLME_RADIO_ON(pAd); | ||
3473 | } | ||
3474 | |||
3475 | /* =========================================================================================== */ | ||
3476 | /* bss_table.c */ | ||
3477 | /* =========================================================================================== */ | ||
3478 | |||
3479 | /*! \brief initialize BSS table | ||
3480 | * \param p_tab pointer to the table | ||
3481 | * \return none | ||
3482 | * \pre | ||
3483 | * \post | ||
3484 | |||
3485 | IRQL = PASSIVE_LEVEL | ||
3486 | IRQL = DISPATCH_LEVEL | ||
3487 | |||
3488 | */ | ||
3489 | void BssTableInit(struct rt_bss_table *Tab) | ||
3490 | { | ||
3491 | int i; | ||
3492 | |||
3493 | Tab->BssNr = 0; | ||
3494 | Tab->BssOverlapNr = 0; | ||
3495 | for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++) { | ||
3496 | NdisZeroMemory(&Tab->BssEntry[i], sizeof(struct rt_bss_entry)); | ||
3497 | Tab->BssEntry[i].Rssi = -127; /* initial the rssi as a minimum value */ | ||
3498 | } | ||
3499 | } | ||
3500 | |||
3501 | /*! \brief search the BSS table by SSID | ||
3502 | * \param p_tab pointer to the bss table | ||
3503 | * \param ssid SSID string | ||
3504 | * \return index of the table, BSS_NOT_FOUND if not in the table | ||
3505 | * \pre | ||
3506 | * \post | ||
3507 | * \note search by sequential search | ||
3508 | |||
3509 | IRQL = DISPATCH_LEVEL | ||
3510 | |||
3511 | */ | ||
3512 | unsigned long BssTableSearch(struct rt_bss_table *Tab, u8 *pBssid, u8 Channel) | ||
3513 | { | ||
3514 | u8 i; | ||
3515 | |||
3516 | for (i = 0; i < Tab->BssNr; i++) { | ||
3517 | /* */ | ||
3518 | /* Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. */ | ||
3519 | /* We should distinguish this case. */ | ||
3520 | /* */ | ||
3521 | if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || | ||
3522 | ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && | ||
3523 | MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)) { | ||
3524 | return i; | ||
3525 | } | ||
3526 | } | ||
3527 | return (unsigned long)BSS_NOT_FOUND; | ||
3528 | } | ||
3529 | |||
3530 | unsigned long BssSsidTableSearch(struct rt_bss_table *Tab, | ||
3531 | u8 *pBssid, | ||
3532 | u8 *pSsid, u8 SsidLen, u8 Channel) | ||
3533 | { | ||
3534 | u8 i; | ||
3535 | |||
3536 | for (i = 0; i < Tab->BssNr; i++) { | ||
3537 | /* */ | ||
3538 | /* Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. */ | ||
3539 | /* We should distinguish this case. */ | ||
3540 | /* */ | ||
3541 | if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || | ||
3542 | ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && | ||
3543 | MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) && | ||
3544 | SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, | ||
3545 | Tab->BssEntry[i].SsidLen)) { | ||
3546 | return i; | ||
3547 | } | ||
3548 | } | ||
3549 | return (unsigned long)BSS_NOT_FOUND; | ||
3550 | } | ||
3551 | |||
3552 | unsigned long BssTableSearchWithSSID(struct rt_bss_table *Tab, | ||
3553 | u8 *Bssid, | ||
3554 | u8 *pSsid, | ||
3555 | u8 SsidLen, u8 Channel) | ||
3556 | { | ||
3557 | u8 i; | ||
3558 | |||
3559 | for (i = 0; i < Tab->BssNr; i++) { | ||
3560 | if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || | ||
3561 | ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && | ||
3562 | MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) && | ||
3563 | (SSID_EQUAL | ||
3564 | (pSsid, SsidLen, Tab->BssEntry[i].Ssid, | ||
3565 | Tab->BssEntry[i].SsidLen) | ||
3566 | || (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) | ||
3567 | || | ||
3568 | (NdisEqualMemory | ||
3569 | (Tab->BssEntry[i].Ssid, ZeroSsid, | ||
3570 | Tab->BssEntry[i].SsidLen)))) { | ||
3571 | return i; | ||
3572 | } | ||
3573 | } | ||
3574 | return (unsigned long)BSS_NOT_FOUND; | ||
3575 | } | ||
3576 | |||
3577 | unsigned long BssSsidTableSearchBySSID(struct rt_bss_table *Tab, | ||
3578 | u8 *pSsid, u8 SsidLen) | ||
3579 | { | ||
3580 | u8 i; | ||
3581 | |||
3582 | for (i = 0; i < Tab->BssNr; i++) { | ||
3583 | if (SSID_EQUAL | ||
3584 | (pSsid, SsidLen, Tab->BssEntry[i].Ssid, | ||
3585 | Tab->BssEntry[i].SsidLen)) { | ||
3586 | return i; | ||
3587 | } | ||
3588 | } | ||
3589 | return (unsigned long)BSS_NOT_FOUND; | ||
3590 | } | ||
3591 | |||
3592 | /* IRQL = DISPATCH_LEVEL */ | ||
3593 | void BssTableDeleteEntry(struct rt_bss_table *Tab, | ||
3594 | u8 *pBssid, u8 Channel) | ||
3595 | { | ||
3596 | u8 i, j; | ||
3597 | |||
3598 | for (i = 0; i < Tab->BssNr; i++) { | ||
3599 | if ((Tab->BssEntry[i].Channel == Channel) && | ||
3600 | (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))) { | ||
3601 | for (j = i; j < Tab->BssNr - 1; j++) { | ||
3602 | NdisMoveMemory(&(Tab->BssEntry[j]), | ||
3603 | &(Tab->BssEntry[j + 1]), | ||
3604 | sizeof(struct rt_bss_entry)); | ||
3605 | } | ||
3606 | NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), | ||
3607 | sizeof(struct rt_bss_entry)); | ||
3608 | Tab->BssNr -= 1; | ||
3609 | return; | ||
3610 | } | ||
3611 | } | ||
3612 | } | ||
3613 | |||
3614 | /* | ||
3615 | ======================================================================== | ||
3616 | Routine Description: | ||
3617 | Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed. | ||
3618 | |||
3619 | Arguments: | ||
3620 | // IRQL = DISPATCH_LEVEL | ||
3621 | ======================================================================== | ||
3622 | */ | ||
3623 | void BATableDeleteORIEntry(struct rt_rtmp_adapter *pAd, | ||
3624 | struct rt_ba_ori_entry *pBAORIEntry) | ||
3625 | { | ||
3626 | |||
3627 | if (pBAORIEntry->ORI_BA_Status != Originator_NONE) { | ||
3628 | NdisAcquireSpinLock(&pAd->BATabLock); | ||
3629 | if (pBAORIEntry->ORI_BA_Status == Originator_Done) { | ||
3630 | pAd->BATable.numAsOriginator -= 1; | ||
3631 | DBGPRINT(RT_DEBUG_TRACE, | ||
3632 | ("BATableDeleteORIEntry numAsOriginator= %ld\n", | ||
3633 | pAd->BATable.numAsRecipient)); | ||
3634 | /* Erase Bitmap flag. */ | ||
3635 | } | ||
3636 | pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1 << (pBAORIEntry->TID))); /* If STA mode, erase flag here */ | ||
3637 | pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; /* If STA mode, erase flag here */ | ||
3638 | pBAORIEntry->ORI_BA_Status = Originator_NONE; | ||
3639 | pBAORIEntry->Token = 1; | ||
3640 | /* Not clear Sequence here. */ | ||
3641 | NdisReleaseSpinLock(&pAd->BATabLock); | ||
3642 | } | ||
3643 | } | ||
3644 | |||
3645 | /*! \brief | ||
3646 | * \param | ||
3647 | * \return | ||
3648 | * \pre | ||
3649 | * \post | ||
3650 | |||
3651 | IRQL = DISPATCH_LEVEL | ||
3652 | |||
3653 | */ | ||
3654 | void BssEntrySet(struct rt_rtmp_adapter *pAd, struct rt_bss_entry *pBss, u8 *pBssid, char Ssid[], u8 SsidLen, u8 BssType, u16 BeaconPeriod, struct rt_cf_parm * pCfParm, u16 AtimWin, u16 CapabilityInfo, u8 SupRate[], u8 SupRateLen, u8 ExtRate[], u8 ExtRateLen, struct rt_ht_capability_ie * pHtCapability, struct rt_add_ht_info_ie * pAddHtInfo, /* AP might use this additional ht info IE */ | ||
3655 | u8 HtCapabilityLen, | ||
3656 | u8 AddHtInfoLen, | ||
3657 | u8 NewExtChanOffset, | ||
3658 | u8 Channel, | ||
3659 | char Rssi, | ||
3660 | IN LARGE_INTEGER TimeStamp, | ||
3661 | u8 CkipFlag, | ||
3662 | struct rt_edca_parm *pEdcaParm, | ||
3663 | struct rt_qos_capability_parm *pQosCapability, | ||
3664 | struct rt_qbss_load_parm *pQbssLoad, | ||
3665 | u16 LengthVIE, struct rt_ndis_802_11_variable_ies *pVIE) | ||
3666 | { | ||
3667 | COPY_MAC_ADDR(pBss->Bssid, pBssid); | ||
3668 | /* Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID */ | ||
3669 | pBss->Hidden = 1; | ||
3670 | if (SsidLen > 0) { | ||
3671 | /* For hidden SSID AP, it might send beacon with SSID len equal to 0 */ | ||
3672 | /* Or send beacon /probe response with SSID len matching real SSID length, */ | ||
3673 | /* but SSID is all zero. such as "00-00-00-00" with length 4. */ | ||
3674 | /* We have to prevent this case overwrite correct table */ | ||
3675 | if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0) { | ||
3676 | NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID); | ||
3677 | NdisMoveMemory(pBss->Ssid, Ssid, SsidLen); | ||
3678 | pBss->SsidLen = SsidLen; | ||
3679 | pBss->Hidden = 0; | ||
3680 | } | ||
3681 | } else | ||
3682 | pBss->SsidLen = 0; | ||
3683 | pBss->BssType = BssType; | ||
3684 | pBss->BeaconPeriod = BeaconPeriod; | ||
3685 | if (BssType == BSS_INFRA) { | ||
3686 | if (pCfParm->bValid) { | ||
3687 | pBss->CfpCount = pCfParm->CfpCount; | ||
3688 | pBss->CfpPeriod = pCfParm->CfpPeriod; | ||
3689 | pBss->CfpMaxDuration = pCfParm->CfpMaxDuration; | ||
3690 | pBss->CfpDurRemaining = pCfParm->CfpDurRemaining; | ||
3691 | } | ||
3692 | } else { | ||
3693 | pBss->AtimWin = AtimWin; | ||
3694 | } | ||
3695 | |||
3696 | pBss->CapabilityInfo = CapabilityInfo; | ||
3697 | /* The privacy bit indicate security is ON, it maight be WEP, TKIP or AES */ | ||
3698 | /* Combine with AuthMode, they will decide the connection methods. */ | ||
3699 | pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo); | ||
3700 | ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES); | ||
3701 | if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES) | ||
3702 | NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen); | ||
3703 | else | ||
3704 | NdisMoveMemory(pBss->SupRate, SupRate, | ||
3705 | MAX_LEN_OF_SUPPORTED_RATES); | ||
3706 | pBss->SupRateLen = SupRateLen; | ||
3707 | ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES); | ||
3708 | NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen); | ||
3709 | pBss->NewExtChanOffset = NewExtChanOffset; | ||
3710 | pBss->ExtRateLen = ExtRateLen; | ||
3711 | pBss->Channel = Channel; | ||
3712 | pBss->CentralChannel = Channel; | ||
3713 | pBss->Rssi = Rssi; | ||
3714 | /* Update CkipFlag. if not exists, the value is 0x0 */ | ||
3715 | pBss->CkipFlag = CkipFlag; | ||
3716 | |||
3717 | /* New for microsoft Fixed IEs */ | ||
3718 | NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8); | ||
3719 | pBss->FixIEs.BeaconInterval = BeaconPeriod; | ||
3720 | pBss->FixIEs.Capabilities = CapabilityInfo; | ||
3721 | |||
3722 | /* New for microsoft Variable IEs */ | ||
3723 | if (LengthVIE != 0) { | ||
3724 | pBss->VarIELen = LengthVIE; | ||
3725 | NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen); | ||
3726 | } else { | ||
3727 | pBss->VarIELen = 0; | ||
3728 | } | ||
3729 | |||
3730 | pBss->AddHtInfoLen = 0; | ||
3731 | pBss->HtCapabilityLen = 0; | ||
3732 | if (HtCapabilityLen > 0) { | ||
3733 | pBss->HtCapabilityLen = HtCapabilityLen; | ||
3734 | NdisMoveMemory(&pBss->HtCapability, pHtCapability, | ||
3735 | HtCapabilityLen); | ||
3736 | if (AddHtInfoLen > 0) { | ||
3737 | pBss->AddHtInfoLen = AddHtInfoLen; | ||
3738 | NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, | ||
3739 | AddHtInfoLen); | ||
3740 | |||
3741 | if ((pAddHtInfo->ControlChan > 2) | ||
3742 | && (pAddHtInfo->AddHtInfo.ExtChanOffset == | ||
3743 | EXTCHA_BELOW) | ||
3744 | && (pHtCapability->HtCapInfo.ChannelWidth == | ||
3745 | BW_40)) { | ||
3746 | pBss->CentralChannel = | ||
3747 | pAddHtInfo->ControlChan - 2; | ||
3748 | } else | ||
3749 | if ((pAddHtInfo->AddHtInfo.ExtChanOffset == | ||
3750 | EXTCHA_ABOVE) | ||
3751 | && (pHtCapability->HtCapInfo.ChannelWidth == | ||
3752 | BW_40)) { | ||
3753 | pBss->CentralChannel = | ||
3754 | pAddHtInfo->ControlChan + 2; | ||
3755 | } | ||
3756 | } | ||
3757 | } | ||
3758 | |||
3759 | BssCipherParse(pBss); | ||
3760 | |||
3761 | /* new for QOS */ | ||
3762 | if (pEdcaParm) | ||
3763 | NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(struct rt_edca_parm)); | ||
3764 | else | ||
3765 | pBss->EdcaParm.bValid = FALSE; | ||
3766 | if (pQosCapability) | ||
3767 | NdisMoveMemory(&pBss->QosCapability, pQosCapability, | ||
3768 | sizeof(struct rt_qos_capability_parm)); | ||
3769 | else | ||
3770 | pBss->QosCapability.bValid = FALSE; | ||
3771 | if (pQbssLoad) | ||
3772 | NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, | ||
3773 | sizeof(struct rt_qbss_load_parm)); | ||
3774 | else | ||
3775 | pBss->QbssLoad.bValid = FALSE; | ||
3776 | |||
3777 | { | ||
3778 | struct rt_eid * pEid; | ||
3779 | u16 Length = 0; | ||
3780 | |||
3781 | NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN); | ||
3782 | NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN); | ||
3783 | pEid = (struct rt_eid *) pVIE; | ||
3784 | while ((Length + 2 + (u16)pEid->Len) <= LengthVIE) { | ||
3785 | switch (pEid->Eid) { | ||
3786 | case IE_WPA: | ||
3787 | if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) { | ||
3788 | if ((pEid->Len + 2) > MAX_CUSTOM_LEN) { | ||
3789 | pBss->WpaIE.IELen = 0; | ||
3790 | break; | ||
3791 | } | ||
3792 | pBss->WpaIE.IELen = pEid->Len + 2; | ||
3793 | NdisMoveMemory(pBss->WpaIE.IE, pEid, | ||
3794 | pBss->WpaIE.IELen); | ||
3795 | } | ||
3796 | break; | ||
3797 | case IE_RSN: | ||
3798 | if (NdisEqualMemory | ||
3799 | (pEid->Octet + 2, RSN_OUI, 3)) { | ||
3800 | if ((pEid->Len + 2) > MAX_CUSTOM_LEN) { | ||
3801 | pBss->RsnIE.IELen = 0; | ||
3802 | break; | ||
3803 | } | ||
3804 | pBss->RsnIE.IELen = pEid->Len + 2; | ||
3805 | NdisMoveMemory(pBss->RsnIE.IE, pEid, | ||
3806 | pBss->RsnIE.IELen); | ||
3807 | } | ||
3808 | break; | ||
3809 | } | ||
3810 | Length = Length + 2 + (u16)pEid->Len; /* Eid[1] + Len[1]+ content[Len] */ | ||
3811 | pEid = (struct rt_eid *) ((u8 *) pEid + 2 + pEid->Len); | ||
3812 | } | ||
3813 | } | ||
3814 | } | ||
3815 | |||
3816 | /*! | ||
3817 | * \brief insert an entry into the bss table | ||
3818 | * \param p_tab The BSS table | ||
3819 | * \param Bssid BSSID | ||
3820 | * \param ssid SSID | ||
3821 | * \param ssid_len Length of SSID | ||
3822 | * \param bss_type | ||
3823 | * \param beacon_period | ||
3824 | * \param timestamp | ||
3825 | * \param p_cf | ||
3826 | * \param atim_win | ||
3827 | * \param cap | ||
3828 | * \param rates | ||
3829 | * \param rates_len | ||
3830 | * \param channel_idx | ||
3831 | * \return none | ||
3832 | * \pre | ||
3833 | * \post | ||
3834 | * \note If SSID is identical, the old entry will be replaced by the new one | ||
3835 | |||
3836 | IRQL = DISPATCH_LEVEL | ||
3837 | |||
3838 | */ | ||
3839 | unsigned long BssTableSetEntry(struct rt_rtmp_adapter *pAd, struct rt_bss_table *Tab, u8 *pBssid, char Ssid[], u8 SsidLen, u8 BssType, u16 BeaconPeriod, struct rt_cf_parm * CfParm, u16 AtimWin, u16 CapabilityInfo, u8 SupRate[], u8 SupRateLen, u8 ExtRate[], u8 ExtRateLen, struct rt_ht_capability_ie * pHtCapability, struct rt_add_ht_info_ie * pAddHtInfo, /* AP might use this additional ht info IE */ | ||
3840 | u8 HtCapabilityLen, | ||
3841 | u8 AddHtInfoLen, | ||
3842 | u8 NewExtChanOffset, | ||
3843 | u8 ChannelNo, | ||
3844 | char Rssi, | ||
3845 | IN LARGE_INTEGER TimeStamp, | ||
3846 | u8 CkipFlag, | ||
3847 | struct rt_edca_parm *pEdcaParm, | ||
3848 | struct rt_qos_capability_parm *pQosCapability, | ||
3849 | struct rt_qbss_load_parm *pQbssLoad, | ||
3850 | u16 LengthVIE, struct rt_ndis_802_11_variable_ies *pVIE) | ||
3851 | { | ||
3852 | unsigned long Idx; | ||
3853 | |||
3854 | Idx = | ||
3855 | BssTableSearchWithSSID(Tab, pBssid, (u8 *) Ssid, SsidLen, | ||
3856 | ChannelNo); | ||
3857 | if (Idx == BSS_NOT_FOUND) { | ||
3858 | if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE) { | ||
3859 | /* */ | ||
3860 | /* It may happen when BSS Table was full. */ | ||
3861 | /* The desired AP will not be added into BSS Table */ | ||
3862 | /* In this case, if we found the desired AP then overwrite BSS Table. */ | ||
3863 | /* */ | ||
3864 | if (!OPSTATUS_TEST_FLAG | ||
3865 | (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) { | ||
3866 | if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) | ||
3867 | || SSID_EQUAL(pAd->MlmeAux.Ssid, | ||
3868 | pAd->MlmeAux.SsidLen, Ssid, | ||
3869 | SsidLen)) { | ||
3870 | Idx = Tab->BssOverlapNr; | ||
3871 | BssEntrySet(pAd, &Tab->BssEntry[Idx], | ||
3872 | pBssid, Ssid, SsidLen, | ||
3873 | BssType, BeaconPeriod, | ||
3874 | CfParm, AtimWin, | ||
3875 | CapabilityInfo, SupRate, | ||
3876 | SupRateLen, ExtRate, | ||
3877 | ExtRateLen, pHtCapability, | ||
3878 | pAddHtInfo, HtCapabilityLen, | ||
3879 | AddHtInfoLen, | ||
3880 | NewExtChanOffset, ChannelNo, | ||
3881 | Rssi, TimeStamp, CkipFlag, | ||
3882 | pEdcaParm, pQosCapability, | ||
3883 | pQbssLoad, LengthVIE, pVIE); | ||
3884 | Tab->BssOverlapNr = | ||
3885 | (Tab->BssOverlapNr++) % | ||
3886 | MAX_LEN_OF_BSS_TABLE; | ||
3887 | } | ||
3888 | return Idx; | ||
3889 | } else { | ||
3890 | return BSS_NOT_FOUND; | ||
3891 | } | ||
3892 | } | ||
3893 | Idx = Tab->BssNr; | ||
3894 | BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, | ||
3895 | BssType, BeaconPeriod, CfParm, AtimWin, | ||
3896 | CapabilityInfo, SupRate, SupRateLen, ExtRate, | ||
3897 | ExtRateLen, pHtCapability, pAddHtInfo, | ||
3898 | HtCapabilityLen, AddHtInfoLen, NewExtChanOffset, | ||
3899 | ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, | ||
3900 | pQosCapability, pQbssLoad, LengthVIE, pVIE); | ||
3901 | Tab->BssNr++; | ||
3902 | } else { | ||
3903 | /* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */ | ||
3904 | if ((SSID_EQUAL | ||
3905 | (Ssid, SsidLen, Tab->BssEntry[Idx].Ssid, | ||
3906 | Tab->BssEntry[Idx].SsidLen)) | ||
3907 | || | ||
3908 | (NdisEqualMemory | ||
3909 | (Tab->BssEntry[Idx].Ssid, ZeroSsid, | ||
3910 | Tab->BssEntry[Idx].SsidLen))) { | ||
3911 | BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, | ||
3912 | SsidLen, BssType, BeaconPeriod, CfParm, | ||
3913 | AtimWin, CapabilityInfo, SupRate, | ||
3914 | SupRateLen, ExtRate, ExtRateLen, | ||
3915 | pHtCapability, pAddHtInfo, HtCapabilityLen, | ||
3916 | AddHtInfoLen, NewExtChanOffset, ChannelNo, | ||
3917 | Rssi, TimeStamp, CkipFlag, pEdcaParm, | ||
3918 | pQosCapability, pQbssLoad, LengthVIE, pVIE); | ||
3919 | } | ||
3920 | } | ||
3921 | |||
3922 | return Idx; | ||
3923 | } | ||
3924 | |||
3925 | /* IRQL = DISPATCH_LEVEL */ | ||
3926 | void BssTableSsidSort(struct rt_rtmp_adapter *pAd, | ||
3927 | struct rt_bss_table *OutTab, char Ssid[], u8 SsidLen) | ||
3928 | { | ||
3929 | int i; | ||
3930 | BssTableInit(OutTab); | ||
3931 | |||
3932 | for (i = 0; i < pAd->ScanTab.BssNr; i++) { | ||
3933 | struct rt_bss_entry *pInBss = &pAd->ScanTab.BssEntry[i]; | ||
3934 | BOOLEAN bIsHiddenApIncluded = FALSE; | ||
3935 | |||
3936 | if (((pAd->CommonCfg.bIEEE80211H == 1) && | ||
3937 | (pAd->MlmeAux.Channel > 14) && | ||
3938 | RadarChannelCheck(pAd, pInBss->Channel)) | ||
3939 | ) { | ||
3940 | if (pInBss->Hidden) | ||
3941 | bIsHiddenApIncluded = TRUE; | ||
3942 | } | ||
3943 | |||
3944 | if ((pInBss->BssType == pAd->StaCfg.BssType) && | ||
3945 | (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) | ||
3946 | || bIsHiddenApIncluded)) { | ||
3947 | struct rt_bss_entry *pOutBss = &OutTab->BssEntry[OutTab->BssNr]; | ||
3948 | |||
3949 | /* 2.4G/5G N only mode */ | ||
3950 | if ((pInBss->HtCapabilityLen == 0) && | ||
3951 | ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) | ||
3952 | || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) { | ||
3953 | DBGPRINT(RT_DEBUG_TRACE, | ||
3954 | ("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n")); | ||
3955 | continue; | ||
3956 | } | ||
3957 | /* New for WPA2 */ | ||
3958 | /* Check the Authmode first */ | ||
3959 | if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) { | ||
3960 | /* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode */ | ||
3961 | if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) | ||
3962 | && (pAd->StaCfg.AuthMode != | ||
3963 | pInBss->AuthModeAux)) | ||
3964 | /* None matched */ | ||
3965 | continue; | ||
3966 | |||
3967 | /* Check cipher suite, AP must have more secured cipher than station setting */ | ||
3968 | if ((pAd->StaCfg.AuthMode == | ||
3969 | Ndis802_11AuthModeWPA) | ||
3970 | || (pAd->StaCfg.AuthMode == | ||
3971 | Ndis802_11AuthModeWPAPSK)) { | ||
3972 | /* If it's not mixed mode, we should only let BSS pass with the same encryption */ | ||
3973 | if (pInBss->WPA.bMixMode == FALSE) | ||
3974 | if (pAd->StaCfg.WepStatus != | ||
3975 | pInBss->WPA.GroupCipher) | ||
3976 | continue; | ||
3977 | |||
3978 | /* check group cipher */ | ||
3979 | if ((pAd->StaCfg.WepStatus < | ||
3980 | pInBss->WPA.GroupCipher) | ||
3981 | && (pInBss->WPA.GroupCipher != | ||
3982 | Ndis802_11GroupWEP40Enabled) | ||
3983 | && (pInBss->WPA.GroupCipher != | ||
3984 | Ndis802_11GroupWEP104Enabled)) | ||
3985 | continue; | ||
3986 | |||
3987 | /* check pairwise cipher, skip if none matched */ | ||
3988 | /* If profile set to AES, let it pass without question. */ | ||
3989 | /* If profile set to TKIP, we must find one mateched */ | ||
3990 | if ((pAd->StaCfg.WepStatus == | ||
3991 | Ndis802_11Encryption2Enabled) | ||
3992 | && (pAd->StaCfg.WepStatus != | ||
3993 | pInBss->WPA.PairCipher) | ||
3994 | && (pAd->StaCfg.WepStatus != | ||
3995 | pInBss->WPA.PairCipherAux)) | ||
3996 | continue; | ||
3997 | } else | ||
3998 | if ((pAd->StaCfg.AuthMode == | ||
3999 | Ndis802_11AuthModeWPA2) | ||
4000 | || (pAd->StaCfg.AuthMode == | ||
4001 | Ndis802_11AuthModeWPA2PSK)) { | ||
4002 | /* If it's not mixed mode, we should only let BSS pass with the same encryption */ | ||
4003 | if (pInBss->WPA2.bMixMode == FALSE) | ||
4004 | if (pAd->StaCfg.WepStatus != | ||
4005 | pInBss->WPA2.GroupCipher) | ||
4006 | continue; | ||
4007 | |||
4008 | /* check group cipher */ | ||
4009 | if ((pAd->StaCfg.WepStatus < | ||
4010 | pInBss->WPA.GroupCipher) | ||
4011 | && (pInBss->WPA2.GroupCipher != | ||
4012 | Ndis802_11GroupWEP40Enabled) | ||
4013 | && (pInBss->WPA2.GroupCipher != | ||
4014 | Ndis802_11GroupWEP104Enabled)) | ||
4015 | continue; | ||
4016 | |||
4017 | /* check pairwise cipher, skip if none matched */ | ||
4018 | /* If profile set to AES, let it pass without question. */ | ||
4019 | /* If profile set to TKIP, we must find one mateched */ | ||
4020 | if ((pAd->StaCfg.WepStatus == | ||
4021 | Ndis802_11Encryption2Enabled) | ||
4022 | && (pAd->StaCfg.WepStatus != | ||
4023 | pInBss->WPA2.PairCipher) | ||
4024 | && (pAd->StaCfg.WepStatus != | ||
4025 | pInBss->WPA2.PairCipherAux)) | ||
4026 | continue; | ||
4027 | } | ||
4028 | } | ||
4029 | /* Bss Type matched, SSID matched. */ | ||
4030 | /* We will check wepstatus for qualification Bss */ | ||
4031 | else if (pAd->StaCfg.WepStatus != pInBss->WepStatus) { | ||
4032 | DBGPRINT(RT_DEBUG_TRACE, | ||
4033 | ("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", | ||
4034 | pAd->StaCfg.WepStatus, | ||
4035 | pInBss->WepStatus)); | ||
4036 | /* */ | ||
4037 | /* For the SESv2 case, we will not qualify WepStatus. */ | ||
4038 | /* */ | ||
4039 | if (!pInBss->bSES) | ||
4040 | continue; | ||
4041 | } | ||
4042 | /* Since the AP is using hidden SSID, and we are trying to connect to ANY */ | ||
4043 | /* It definitely will fail. So, skip it. */ | ||
4044 | /* CCX also require not even try to connect it! */ | ||
4045 | if (SsidLen == 0) | ||
4046 | continue; | ||
4047 | |||
4048 | /* If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region */ | ||
4049 | /* If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, */ | ||
4050 | if ((pInBss->CentralChannel != pInBss->Channel) && | ||
4051 | (pAd->CommonCfg.RegTransmitSetting.field.BW == | ||
4052 | BW_40)) { | ||
4053 | if (RTMPCheckChannel | ||
4054 | (pAd, pInBss->CentralChannel, | ||
4055 | pInBss->Channel) == FALSE) { | ||
4056 | pAd->CommonCfg.RegTransmitSetting.field. | ||
4057 | BW = BW_20; | ||
4058 | SetCommonHT(pAd); | ||
4059 | pAd->CommonCfg.RegTransmitSetting.field. | ||
4060 | BW = BW_40; | ||
4061 | } else { | ||
4062 | if (pAd->CommonCfg.DesiredHtPhy. | ||
4063 | ChannelWidth == BAND_WIDTH_20) { | ||
4064 | SetCommonHT(pAd); | ||
4065 | } | ||
4066 | } | ||
4067 | } | ||
4068 | /* copy matching BSS from InTab to OutTab */ | ||
4069 | NdisMoveMemory(pOutBss, pInBss, sizeof(struct rt_bss_entry)); | ||
4070 | |||
4071 | OutTab->BssNr++; | ||
4072 | } else if ((pInBss->BssType == pAd->StaCfg.BssType) | ||
4073 | && (SsidLen == 0)) { | ||
4074 | struct rt_bss_entry *pOutBss = &OutTab->BssEntry[OutTab->BssNr]; | ||
4075 | |||
4076 | /* 2.4G/5G N only mode */ | ||
4077 | if ((pInBss->HtCapabilityLen == 0) && | ||
4078 | ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) | ||
4079 | || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) { | ||
4080 | DBGPRINT(RT_DEBUG_TRACE, | ||
4081 | ("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n")); | ||
4082 | continue; | ||
4083 | } | ||
4084 | /* New for WPA2 */ | ||
4085 | /* Check the Authmode first */ | ||
4086 | if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) { | ||
4087 | /* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode */ | ||
4088 | if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) | ||
4089 | && (pAd->StaCfg.AuthMode != | ||
4090 | pInBss->AuthModeAux)) | ||
4091 | /* None matched */ | ||
4092 | continue; | ||
4093 | |||
4094 | /* Check cipher suite, AP must have more secured cipher than station setting */ | ||
4095 | if ((pAd->StaCfg.AuthMode == | ||
4096 | Ndis802_11AuthModeWPA) | ||
4097 | || (pAd->StaCfg.AuthMode == | ||
4098 | Ndis802_11AuthModeWPAPSK)) { | ||
4099 | /* If it's not mixed mode, we should only let BSS pass with the same encryption */ | ||
4100 | if (pInBss->WPA.bMixMode == FALSE) | ||
4101 | if (pAd->StaCfg.WepStatus != | ||
4102 | pInBss->WPA.GroupCipher) | ||
4103 | continue; | ||
4104 | |||
4105 | /* check group cipher */ | ||
4106 | if (pAd->StaCfg.WepStatus < | ||
4107 | pInBss->WPA.GroupCipher) | ||
4108 | continue; | ||
4109 | |||
4110 | /* check pairwise cipher, skip if none matched */ | ||
4111 | /* If profile set to AES, let it pass without question. */ | ||
4112 | /* If profile set to TKIP, we must find one mateched */ | ||
4113 | if ((pAd->StaCfg.WepStatus == | ||
4114 | Ndis802_11Encryption2Enabled) | ||
4115 | && (pAd->StaCfg.WepStatus != | ||
4116 | pInBss->WPA.PairCipher) | ||
4117 | && (pAd->StaCfg.WepStatus != | ||
4118 | pInBss->WPA.PairCipherAux)) | ||
4119 | continue; | ||
4120 | } else | ||
4121 | if ((pAd->StaCfg.AuthMode == | ||
4122 | Ndis802_11AuthModeWPA2) | ||
4123 | || (pAd->StaCfg.AuthMode == | ||
4124 | Ndis802_11AuthModeWPA2PSK)) { | ||
4125 | /* If it's not mixed mode, we should only let BSS pass with the same encryption */ | ||
4126 | if (pInBss->WPA2.bMixMode == FALSE) | ||
4127 | if (pAd->StaCfg.WepStatus != | ||
4128 | pInBss->WPA2.GroupCipher) | ||
4129 | continue; | ||
4130 | |||
4131 | /* check group cipher */ | ||
4132 | if (pAd->StaCfg.WepStatus < | ||
4133 | pInBss->WPA2.GroupCipher) | ||
4134 | continue; | ||
4135 | |||
4136 | /* check pairwise cipher, skip if none matched */ | ||
4137 | /* If profile set to AES, let it pass without question. */ | ||
4138 | /* If profile set to TKIP, we must find one mateched */ | ||
4139 | if ((pAd->StaCfg.WepStatus == | ||
4140 | Ndis802_11Encryption2Enabled) | ||
4141 | && (pAd->StaCfg.WepStatus != | ||
4142 | pInBss->WPA2.PairCipher) | ||
4143 | && (pAd->StaCfg.WepStatus != | ||
4144 | pInBss->WPA2.PairCipherAux)) | ||
4145 | continue; | ||
4146 | } | ||
4147 | } | ||
4148 | /* Bss Type matched, SSID matched. */ | ||
4149 | /* We will check wepstatus for qualification Bss */ | ||
4150 | else if (pAd->StaCfg.WepStatus != pInBss->WepStatus) | ||
4151 | continue; | ||
4152 | |||
4153 | /* If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region */ | ||
4154 | /* If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, */ | ||
4155 | if ((pInBss->CentralChannel != pInBss->Channel) && | ||
4156 | (pAd->CommonCfg.RegTransmitSetting.field.BW == | ||
4157 | BW_40)) { | ||
4158 | if (RTMPCheckChannel | ||
4159 | (pAd, pInBss->CentralChannel, | ||
4160 | pInBss->Channel) == FALSE) { | ||
4161 | pAd->CommonCfg.RegTransmitSetting.field. | ||
4162 | BW = BW_20; | ||
4163 | SetCommonHT(pAd); | ||
4164 | pAd->CommonCfg.RegTransmitSetting.field. | ||
4165 | BW = BW_40; | ||
4166 | } | ||
4167 | } | ||
4168 | /* copy matching BSS from InTab to OutTab */ | ||
4169 | NdisMoveMemory(pOutBss, pInBss, sizeof(struct rt_bss_entry)); | ||
4170 | |||
4171 | OutTab->BssNr++; | ||
4172 | } | ||
4173 | |||
4174 | if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE) | ||
4175 | break; | ||
4176 | } | ||
4177 | |||
4178 | BssTableSortByRssi(OutTab); | ||
4179 | } | ||
4180 | |||
4181 | /* IRQL = DISPATCH_LEVEL */ | ||
4182 | void BssTableSortByRssi(struct rt_bss_table *OutTab) | ||
4183 | { | ||
4184 | int i, j; | ||
4185 | struct rt_bss_entry TmpBss; | ||
4186 | |||
4187 | for (i = 0; i < OutTab->BssNr - 1; i++) { | ||
4188 | for (j = i + 1; j < OutTab->BssNr; j++) { | ||
4189 | if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi) { | ||
4190 | NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], | ||
4191 | sizeof(struct rt_bss_entry)); | ||
4192 | NdisMoveMemory(&OutTab->BssEntry[j], | ||
4193 | &OutTab->BssEntry[i], | ||
4194 | sizeof(struct rt_bss_entry)); | ||
4195 | NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, | ||
4196 | sizeof(struct rt_bss_entry)); | ||
4197 | } | ||
4198 | } | ||
4199 | } | ||
4200 | } | ||
4201 | |||
4202 | void BssCipherParse(struct rt_bss_entry *pBss) | ||
4203 | { | ||
4204 | struct rt_eid * pEid; | ||
4205 | u8 *pTmp; | ||
4206 | struct rt_rsn_ie_header * pRsnHeader; | ||
4207 | struct rt_cipher_suite_struct * pCipher; | ||
4208 | struct rt_akm_suite * pAKM; | ||
4209 | u16 Count; | ||
4210 | int Length; | ||
4211 | NDIS_802_11_ENCRYPTION_STATUS TmpCipher; | ||
4212 | |||
4213 | /* */ | ||
4214 | /* WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame. */ | ||
4215 | /* */ | ||
4216 | if (pBss->Privacy) { | ||
4217 | pBss->WepStatus = Ndis802_11WEPEnabled; | ||
4218 | } else { | ||
4219 | pBss->WepStatus = Ndis802_11WEPDisabled; | ||
4220 | } | ||
4221 | /* Set default to disable & open authentication before parsing variable IE */ | ||
4222 | pBss->AuthMode = Ndis802_11AuthModeOpen; | ||
4223 | pBss->AuthModeAux = Ndis802_11AuthModeOpen; | ||
4224 | |||
4225 | /* Init WPA setting */ | ||
4226 | pBss->WPA.PairCipher = Ndis802_11WEPDisabled; | ||
4227 | pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled; | ||
4228 | pBss->WPA.GroupCipher = Ndis802_11WEPDisabled; | ||
4229 | pBss->WPA.RsnCapability = 0; | ||
4230 | pBss->WPA.bMixMode = FALSE; | ||
4231 | |||
4232 | /* Init WPA2 setting */ | ||
4233 | pBss->WPA2.PairCipher = Ndis802_11WEPDisabled; | ||
4234 | pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled; | ||
4235 | pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled; | ||
4236 | pBss->WPA2.RsnCapability = 0; | ||
4237 | pBss->WPA2.bMixMode = FALSE; | ||
4238 | |||
4239 | Length = (int)pBss->VarIELen; | ||
4240 | |||
4241 | while (Length > 0) { | ||
4242 | /* Parse cipher suite base on WPA1 & WPA2, they should be parsed differently */ | ||
4243 | pTmp = ((u8 *)pBss->VarIEs) + pBss->VarIELen - Length; | ||
4244 | pEid = (struct rt_eid *) pTmp; | ||
4245 | switch (pEid->Eid) { | ||
4246 | case IE_WPA: | ||
4247 | if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) | ||
4248 | && (pEid->Len == 7)) { | ||
4249 | pBss->bSES = TRUE; | ||
4250 | break; | ||
4251 | } else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != | ||
4252 | 1) { | ||
4253 | /* if unsupported vendor specific IE */ | ||
4254 | break; | ||
4255 | } | ||
4256 | /* Skip OUI, version, and multicast suite */ | ||
4257 | /* This part should be improved in the future when AP supported multiple cipher suite. */ | ||
4258 | /* For now, it's OK since almost all APs have fixed cipher suite supported. */ | ||
4259 | /* pTmp = (u8 *)pEid->Octet; */ | ||
4260 | pTmp += 11; | ||
4261 | |||
4262 | /* Cipher Suite Selectors from Spec P802.11i/D3.2 P26. */ | ||
4263 | /* Value Meaning */ | ||
4264 | /* 0 None */ | ||
4265 | /* 1 WEP-40 */ | ||
4266 | /* 2 Tkip */ | ||
4267 | /* 3 WRAP */ | ||
4268 | /* 4 AES */ | ||
4269 | /* 5 WEP-104 */ | ||
4270 | /* Parse group cipher */ | ||
4271 | switch (*pTmp) { | ||
4272 | case 1: | ||
4273 | pBss->WPA.GroupCipher = | ||
4274 | Ndis802_11GroupWEP40Enabled; | ||
4275 | break; | ||
4276 | case 5: | ||
4277 | pBss->WPA.GroupCipher = | ||
4278 | Ndis802_11GroupWEP104Enabled; | ||
4279 | break; | ||
4280 | case 2: | ||
4281 | pBss->WPA.GroupCipher = | ||
4282 | Ndis802_11Encryption2Enabled; | ||
4283 | break; | ||
4284 | case 4: | ||
4285 | pBss->WPA.GroupCipher = | ||
4286 | Ndis802_11Encryption3Enabled; | ||
4287 | break; | ||
4288 | default: | ||
4289 | break; | ||
4290 | } | ||
4291 | /* number of unicast suite */ | ||
4292 | pTmp += 1; | ||
4293 | |||
4294 | /* skip all unicast cipher suites */ | ||
4295 | /*Count = *(u16 *)pTmp; */ | ||
4296 | Count = (pTmp[1] << 8) + pTmp[0]; | ||
4297 | pTmp += sizeof(u16); | ||
4298 | |||
4299 | /* Parsing all unicast cipher suite */ | ||
4300 | while (Count > 0) { | ||
4301 | /* Skip OUI */ | ||
4302 | pTmp += 3; | ||
4303 | TmpCipher = Ndis802_11WEPDisabled; | ||
4304 | switch (*pTmp) { | ||
4305 | case 1: | ||
4306 | case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */ | ||
4307 | TmpCipher = | ||
4308 | Ndis802_11Encryption1Enabled; | ||
4309 | break; | ||
4310 | case 2: | ||
4311 | TmpCipher = | ||
4312 | Ndis802_11Encryption2Enabled; | ||
4313 | break; | ||
4314 | case 4: | ||
4315 | TmpCipher = | ||
4316 | Ndis802_11Encryption3Enabled; | ||
4317 | break; | ||
4318 | default: | ||
4319 | break; | ||
4320 | } | ||
4321 | if (TmpCipher > pBss->WPA.PairCipher) { | ||
4322 | /* Move the lower cipher suite to PairCipherAux */ | ||
4323 | pBss->WPA.PairCipherAux = | ||
4324 | pBss->WPA.PairCipher; | ||
4325 | pBss->WPA.PairCipher = TmpCipher; | ||
4326 | } else { | ||
4327 | pBss->WPA.PairCipherAux = TmpCipher; | ||
4328 | } | ||
4329 | pTmp++; | ||
4330 | Count--; | ||
4331 | } | ||
4332 | |||
4333 | /* 4. get AKM suite counts */ | ||
4334 | /*Count = *(u16 *)pTmp; */ | ||
4335 | Count = (pTmp[1] << 8) + pTmp[0]; | ||
4336 | pTmp += sizeof(u16); | ||
4337 | pTmp += 3; | ||
4338 | |||
4339 | switch (*pTmp) { | ||
4340 | case 1: | ||
4341 | /* Set AP support WPA-enterprise mode */ | ||
4342 | if (pBss->AuthMode == Ndis802_11AuthModeOpen) | ||
4343 | pBss->AuthMode = Ndis802_11AuthModeWPA; | ||
4344 | else | ||
4345 | pBss->AuthModeAux = | ||
4346 | Ndis802_11AuthModeWPA; | ||
4347 | break; | ||
4348 | case 2: | ||
4349 | /* Set AP support WPA-PSK mode */ | ||
4350 | if (pBss->AuthMode == Ndis802_11AuthModeOpen) | ||
4351 | pBss->AuthMode = | ||
4352 | Ndis802_11AuthModeWPAPSK; | ||
4353 | else | ||
4354 | pBss->AuthModeAux = | ||
4355 | Ndis802_11AuthModeWPAPSK; | ||
4356 | break; | ||
4357 | default: | ||
4358 | break; | ||
4359 | } | ||
4360 | pTmp += 1; | ||
4361 | |||
4362 | /* Fixed for WPA-None */ | ||
4363 | if (pBss->BssType == BSS_ADHOC) { | ||
4364 | pBss->AuthMode = Ndis802_11AuthModeWPANone; | ||
4365 | pBss->AuthModeAux = Ndis802_11AuthModeWPANone; | ||
4366 | pBss->WepStatus = pBss->WPA.GroupCipher; | ||
4367 | /* Patched bugs for old driver */ | ||
4368 | if (pBss->WPA.PairCipherAux == | ||
4369 | Ndis802_11WEPDisabled) | ||
4370 | pBss->WPA.PairCipherAux = | ||
4371 | pBss->WPA.GroupCipher; | ||
4372 | } else | ||
4373 | pBss->WepStatus = pBss->WPA.PairCipher; | ||
4374 | |||
4375 | /* Check the Pair & Group, if different, turn on mixed mode flag */ | ||
4376 | if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher) | ||
4377 | pBss->WPA.bMixMode = TRUE; | ||
4378 | |||
4379 | break; | ||
4380 | |||
4381 | case IE_RSN: | ||
4382 | pRsnHeader = (struct rt_rsn_ie_header *) pTmp; | ||
4383 | |||
4384 | /* 0. Version must be 1 */ | ||
4385 | if (le2cpu16(pRsnHeader->Version) != 1) | ||
4386 | break; | ||
4387 | pTmp += sizeof(struct rt_rsn_ie_header); | ||
4388 | |||
4389 | /* 1. Check group cipher */ | ||
4390 | pCipher = (struct rt_cipher_suite_struct *) pTmp; | ||
4391 | if (!RTMPEqualMemory(pTmp, RSN_OUI, 3)) | ||
4392 | break; | ||
4393 | |||
4394 | /* Parse group cipher */ | ||
4395 | switch (pCipher->Type) { | ||
4396 | case 1: | ||
4397 | pBss->WPA2.GroupCipher = | ||
4398 | Ndis802_11GroupWEP40Enabled; | ||
4399 | break; | ||
4400 | case 5: | ||
4401 | pBss->WPA2.GroupCipher = | ||
4402 | Ndis802_11GroupWEP104Enabled; | ||
4403 | break; | ||
4404 | case 2: | ||
4405 | pBss->WPA2.GroupCipher = | ||
4406 | Ndis802_11Encryption2Enabled; | ||
4407 | break; | ||
4408 | case 4: | ||
4409 | pBss->WPA2.GroupCipher = | ||
4410 | Ndis802_11Encryption3Enabled; | ||
4411 | break; | ||
4412 | default: | ||
4413 | break; | ||
4414 | } | ||
4415 | /* set to correct offset for next parsing */ | ||
4416 | pTmp += sizeof(struct rt_cipher_suite_struct); | ||
4417 | |||
4418 | /* 2. Get pairwise cipher counts */ | ||
4419 | /*Count = *(u16 *)pTmp; */ | ||
4420 | Count = (pTmp[1] << 8) + pTmp[0]; | ||
4421 | pTmp += sizeof(u16); | ||
4422 | |||
4423 | /* 3. Get pairwise cipher */ | ||
4424 | /* Parsing all unicast cipher suite */ | ||
4425 | while (Count > 0) { | ||
4426 | /* Skip OUI */ | ||
4427 | pCipher = (struct rt_cipher_suite_struct *) pTmp; | ||
4428 | TmpCipher = Ndis802_11WEPDisabled; | ||
4429 | switch (pCipher->Type) { | ||
4430 | case 1: | ||
4431 | case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */ | ||
4432 | TmpCipher = | ||
4433 | Ndis802_11Encryption1Enabled; | ||
4434 | break; | ||
4435 | case 2: | ||
4436 | TmpCipher = | ||
4437 | Ndis802_11Encryption2Enabled; | ||
4438 | break; | ||
4439 | case 4: | ||
4440 | TmpCipher = | ||
4441 | Ndis802_11Encryption3Enabled; | ||
4442 | break; | ||
4443 | default: | ||
4444 | break; | ||
4445 | } | ||
4446 | if (TmpCipher > pBss->WPA2.PairCipher) { | ||
4447 | /* Move the lower cipher suite to PairCipherAux */ | ||
4448 | pBss->WPA2.PairCipherAux = | ||
4449 | pBss->WPA2.PairCipher; | ||
4450 | pBss->WPA2.PairCipher = TmpCipher; | ||
4451 | } else { | ||
4452 | pBss->WPA2.PairCipherAux = TmpCipher; | ||
4453 | } | ||
4454 | pTmp += sizeof(struct rt_cipher_suite_struct); | ||
4455 | Count--; | ||
4456 | } | ||
4457 | |||
4458 | /* 4. get AKM suite counts */ | ||
4459 | /*Count = *(u16 *)pTmp; */ | ||
4460 | Count = (pTmp[1] << 8) + pTmp[0]; | ||
4461 | pTmp += sizeof(u16); | ||
4462 | |||
4463 | /* 5. Get AKM ciphers */ | ||
4464 | /* Parsing all AKM ciphers */ | ||
4465 | while (Count > 0) { | ||
4466 | pAKM = (struct rt_akm_suite *) pTmp; | ||
4467 | if (!RTMPEqualMemory(pTmp, RSN_OUI, 3)) | ||
4468 | break; | ||
4469 | |||
4470 | switch (pAKM->Type) { | ||
4471 | case 1: | ||
4472 | /* Set AP support WPA-enterprise mode */ | ||
4473 | if (pBss->AuthMode == | ||
4474 | Ndis802_11AuthModeOpen) | ||
4475 | pBss->AuthMode = | ||
4476 | Ndis802_11AuthModeWPA2; | ||
4477 | else | ||
4478 | pBss->AuthModeAux = | ||
4479 | Ndis802_11AuthModeWPA2; | ||
4480 | break; | ||
4481 | case 2: | ||
4482 | /* Set AP support WPA-PSK mode */ | ||
4483 | if (pBss->AuthMode == | ||
4484 | Ndis802_11AuthModeOpen) | ||
4485 | pBss->AuthMode = | ||
4486 | Ndis802_11AuthModeWPA2PSK; | ||
4487 | else | ||
4488 | pBss->AuthModeAux = | ||
4489 | Ndis802_11AuthModeWPA2PSK; | ||
4490 | break; | ||
4491 | default: | ||
4492 | if (pBss->AuthMode == | ||
4493 | Ndis802_11AuthModeOpen) | ||
4494 | pBss->AuthMode = | ||
4495 | Ndis802_11AuthModeMax; | ||
4496 | else | ||
4497 | pBss->AuthModeAux = | ||
4498 | Ndis802_11AuthModeMax; | ||
4499 | break; | ||
4500 | } | ||
4501 | pTmp += (Count * sizeof(struct rt_akm_suite)); | ||
4502 | Count--; | ||
4503 | } | ||
4504 | |||
4505 | /* Fixed for WPA-None */ | ||
4506 | if (pBss->BssType == BSS_ADHOC) { | ||
4507 | pBss->AuthMode = Ndis802_11AuthModeWPANone; | ||
4508 | pBss->AuthModeAux = Ndis802_11AuthModeWPANone; | ||
4509 | pBss->WPA.PairCipherAux = | ||
4510 | pBss->WPA2.PairCipherAux; | ||
4511 | pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher; | ||
4512 | pBss->WepStatus = pBss->WPA.GroupCipher; | ||
4513 | /* Patched bugs for old driver */ | ||
4514 | if (pBss->WPA.PairCipherAux == | ||
4515 | Ndis802_11WEPDisabled) | ||
4516 | pBss->WPA.PairCipherAux = | ||
4517 | pBss->WPA.GroupCipher; | ||
4518 | } | ||
4519 | pBss->WepStatus = pBss->WPA2.PairCipher; | ||
4520 | |||
4521 | /* 6. Get RSN capability */ | ||
4522 | /*pBss->WPA2.RsnCapability = *(u16 *)pTmp; */ | ||
4523 | pBss->WPA2.RsnCapability = (pTmp[1] << 8) + pTmp[0]; | ||
4524 | pTmp += sizeof(u16); | ||
4525 | |||
4526 | /* Check the Pair & Group, if different, turn on mixed mode flag */ | ||
4527 | if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher) | ||
4528 | pBss->WPA2.bMixMode = TRUE; | ||
4529 | |||
4530 | break; | ||
4531 | default: | ||
4532 | break; | ||
4533 | } | ||
4534 | Length -= (pEid->Len + 2); | ||
4535 | } | ||
4536 | } | ||
4537 | |||
4538 | /* =========================================================================================== */ | ||
4539 | /* mac_table.c */ | ||
4540 | /* =========================================================================================== */ | ||
4541 | |||
4542 | /*! \brief generates a random mac address value for IBSS BSSID | ||
4543 | * \param Addr the bssid location | ||
4544 | * \return none | ||
4545 | * \pre | ||
4546 | * \post | ||
4547 | */ | ||
4548 | void MacAddrRandomBssid(struct rt_rtmp_adapter *pAd, u8 *pAddr) | ||
4549 | { | ||
4550 | int i; | ||
4551 | |||
4552 | for (i = 0; i < MAC_ADDR_LEN; i++) { | ||
4553 | pAddr[i] = RandomByte(pAd); | ||
4554 | } | ||
4555 | |||
4556 | pAddr[0] = (pAddr[0] & 0xfe) | 0x02; /* the first 2 bits must be 01xxxxxxxx */ | ||
4557 | } | ||
4558 | |||
4559 | /*! \brief init the management mac frame header | ||
4560 | * \param p_hdr mac header | ||
4561 | * \param subtype subtype of the frame | ||
4562 | * \param p_ds destination address, don't care if it is a broadcast address | ||
4563 | * \return none | ||
4564 | * \pre the station has the following information in the pAd->StaCfg | ||
4565 | * - bssid | ||
4566 | * - station address | ||
4567 | * \post | ||
4568 | * \note this function initializes the following field | ||
4569 | |||
4570 | IRQL = PASSIVE_LEVEL | ||
4571 | IRQL = DISPATCH_LEVEL | ||
4572 | |||
4573 | */ | ||
4574 | void MgtMacHeaderInit(struct rt_rtmp_adapter *pAd, | ||
4575 | struct rt_header_802_11 * pHdr80211, | ||
4576 | u8 SubType, | ||
4577 | u8 ToDs, u8 *pDA, u8 *pBssid) | ||
4578 | { | ||
4579 | NdisZeroMemory(pHdr80211, sizeof(struct rt_header_802_11)); | ||
4580 | |||
4581 | pHdr80211->FC.Type = BTYPE_MGMT; | ||
4582 | pHdr80211->FC.SubType = SubType; | ||
4583 | /* if (SubType == SUBTYPE_ACK) // sample, no use, it will conflict with ACTION frame sub type */ | ||
4584 | /* pHdr80211->FC.Type = BTYPE_CNTL; */ | ||
4585 | pHdr80211->FC.ToDs = ToDs; | ||
4586 | COPY_MAC_ADDR(pHdr80211->Addr1, pDA); | ||
4587 | COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress); | ||
4588 | COPY_MAC_ADDR(pHdr80211->Addr3, pBssid); | ||
4589 | } | ||
4590 | |||
4591 | /* =========================================================================================== */ | ||
4592 | /* mem_mgmt.c */ | ||
4593 | /* =========================================================================================== */ | ||
4594 | |||
4595 | /*!*************************************************************************** | ||
4596 | * This routine build an outgoing frame, and fill all information specified | ||
4597 | * in argument list to the frame body. The actual frame size is the summation | ||
4598 | * of all arguments. | ||
4599 | * input params: | ||
4600 | * Buffer - pointer to a pre-allocated memory segment | ||
4601 | * args - a list of <int arg_size, arg> pairs. | ||
4602 | * NOTE NOTE NOTE! the last argument must be NULL, otherwise this | ||
4603 | * function will FAIL! | ||
4604 | * return: | ||
4605 | * Size of the buffer | ||
4606 | * usage: | ||
4607 | * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS); | ||
4608 | |||
4609 | IRQL = PASSIVE_LEVEL | ||
4610 | IRQL = DISPATCH_LEVEL | ||
4611 | |||
4612 | ****************************************************************************/ | ||
4613 | unsigned long MakeOutgoingFrame(u8 * Buffer, unsigned long * FrameLen, ...) | ||
4614 | { | ||
4615 | u8 *p; | ||
4616 | int leng; | ||
4617 | unsigned long TotLeng; | ||
4618 | va_list Args; | ||
4619 | |||
4620 | /* calculates the total length */ | ||
4621 | TotLeng = 0; | ||
4622 | va_start(Args, FrameLen); | ||
4623 | do { | ||
4624 | leng = va_arg(Args, int); | ||
4625 | if (leng == END_OF_ARGS) { | ||
4626 | break; | ||
4627 | } | ||
4628 | p = va_arg(Args, void *); | ||
4629 | NdisMoveMemory(&Buffer[TotLeng], p, leng); | ||
4630 | TotLeng = TotLeng + leng; | ||
4631 | } while (TRUE); | ||
4632 | |||
4633 | va_end(Args); /* clean up */ | ||
4634 | *FrameLen = TotLeng; | ||
4635 | return TotLeng; | ||
4636 | } | ||
4637 | |||
4638 | /* =========================================================================================== */ | ||
4639 | /* mlme_queue.c */ | ||
4640 | /* =========================================================================================== */ | ||
4641 | |||
4642 | /*! \brief Initialize The MLME Queue, used by MLME Functions | ||
4643 | * \param *Queue The MLME Queue | ||
4644 | * \return Always Return NDIS_STATE_SUCCESS in this implementation | ||
4645 | * \pre | ||
4646 | * \post | ||
4647 | * \note Because this is done only once (at the init stage), no need to be locked | ||
4648 | |||
4649 | IRQL = PASSIVE_LEVEL | ||
4650 | |||
4651 | */ | ||
4652 | int MlmeQueueInit(struct rt_mlme_queue *Queue) | ||
4653 | { | ||
4654 | int i; | ||
4655 | |||
4656 | NdisAllocateSpinLock(&Queue->Lock); | ||
4657 | |||
4658 | Queue->Num = 0; | ||
4659 | Queue->Head = 0; | ||
4660 | Queue->Tail = 0; | ||
4661 | |||
4662 | for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++) { | ||
4663 | Queue->Entry[i].Occupied = FALSE; | ||
4664 | Queue->Entry[i].MsgLen = 0; | ||
4665 | NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE); | ||
4666 | } | ||
4667 | |||
4668 | return NDIS_STATUS_SUCCESS; | ||
4669 | } | ||
4670 | |||
4671 | /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread | ||
4672 | * \param *Queue The MLME Queue | ||
4673 | * \param Machine The State Machine Id | ||
4674 | * \param MsgType The Message Type | ||
4675 | * \param MsgLen The Message length | ||
4676 | * \param *Msg The message pointer | ||
4677 | * \return TRUE if enqueue is successful, FALSE if the queue is full | ||
4678 | * \pre | ||
4679 | * \post | ||
4680 | * \note The message has to be initialized | ||
4681 | |||
4682 | IRQL = PASSIVE_LEVEL | ||
4683 | IRQL = DISPATCH_LEVEL | ||
4684 | |||
4685 | */ | ||
4686 | BOOLEAN MlmeEnqueue(struct rt_rtmp_adapter *pAd, | ||
4687 | unsigned long Machine, | ||
4688 | unsigned long MsgType, unsigned long MsgLen, void * Msg) | ||
4689 | { | ||
4690 | int Tail; | ||
4691 | struct rt_mlme_queue *Queue = (struct rt_mlme_queue *)& pAd->Mlme.Queue; | ||
4692 | |||
4693 | /* Do nothing if the driver is starting halt state. */ | ||
4694 | /* This might happen when timer already been fired before cancel timer with mlmehalt */ | ||
4695 | if (RTMP_TEST_FLAG | ||
4696 | (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) | ||
4697 | return FALSE; | ||
4698 | |||
4699 | /* First check the size, it MUST not exceed the mlme queue size */ | ||
4700 | if (MsgLen > MGMT_DMA_BUFFER_SIZE) { | ||
4701 | DBGPRINT_ERR("MlmeEnqueue: msg too large, size = %ld \n", MsgLen); | ||
4702 | return FALSE; | ||
4703 | } | ||
4704 | |||
4705 | if (MlmeQueueFull(Queue)) { | ||
4706 | return FALSE; | ||
4707 | } | ||
4708 | |||
4709 | NdisAcquireSpinLock(&(Queue->Lock)); | ||
4710 | Tail = Queue->Tail; | ||
4711 | Queue->Tail++; | ||
4712 | Queue->Num++; | ||
4713 | if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) { | ||
4714 | Queue->Tail = 0; | ||
4715 | } | ||
4716 | |||
4717 | Queue->Entry[Tail].Wcid = RESERVED_WCID; | ||
4718 | Queue->Entry[Tail].Occupied = TRUE; | ||
4719 | Queue->Entry[Tail].Machine = Machine; | ||
4720 | Queue->Entry[Tail].MsgType = MsgType; | ||
4721 | Queue->Entry[Tail].MsgLen = MsgLen; | ||
4722 | |||
4723 | if (Msg != NULL) { | ||
4724 | NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen); | ||
4725 | } | ||
4726 | |||
4727 | NdisReleaseSpinLock(&(Queue->Lock)); | ||
4728 | return TRUE; | ||
4729 | } | ||
4730 | |||
4731 | /*! \brief This function is used when Recv gets a MLME message | ||
4732 | * \param *Queue The MLME Queue | ||
4733 | * \param TimeStampHigh The upper 32 bit of timestamp | ||
4734 | * \param TimeStampLow The lower 32 bit of timestamp | ||
4735 | * \param Rssi The receiving RSSI strength | ||
4736 | * \param MsgLen The length of the message | ||
4737 | * \param *Msg The message pointer | ||
4738 | * \return TRUE if everything ok, FALSE otherwise (like Queue Full) | ||
4739 | * \pre | ||
4740 | * \post | ||
4741 | |||
4742 | IRQL = DISPATCH_LEVEL | ||
4743 | |||
4744 | */ | ||
4745 | BOOLEAN MlmeEnqueueForRecv(struct rt_rtmp_adapter *pAd, | ||
4746 | unsigned long Wcid, | ||
4747 | unsigned long TimeStampHigh, | ||
4748 | unsigned long TimeStampLow, | ||
4749 | u8 Rssi0, | ||
4750 | u8 Rssi1, | ||
4751 | u8 Rssi2, | ||
4752 | unsigned long MsgLen, void * Msg, u8 Signal) | ||
4753 | { | ||
4754 | int Tail, Machine; | ||
4755 | struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *) Msg; | ||
4756 | int MsgType; | ||
4757 | struct rt_mlme_queue *Queue = (struct rt_mlme_queue *)& pAd->Mlme.Queue; | ||
4758 | |||
4759 | /* Do nothing if the driver is starting halt state. */ | ||
4760 | /* This might happen when timer already been fired before cancel timer with mlmehalt */ | ||
4761 | if (RTMP_TEST_FLAG | ||
4762 | (pAd, | ||
4763 | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) { | ||
4764 | DBGPRINT_ERR("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"); | ||
4765 | return FALSE; | ||
4766 | } | ||
4767 | /* First check the size, it MUST not exceed the mlme queue size */ | ||
4768 | if (MsgLen > MGMT_DMA_BUFFER_SIZE) { | ||
4769 | DBGPRINT_ERR("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen); | ||
4770 | return FALSE; | ||
4771 | } | ||
4772 | |||
4773 | if (MlmeQueueFull(Queue)) { | ||
4774 | return FALSE; | ||
4775 | } | ||
4776 | |||
4777 | { | ||
4778 | if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType)) { | ||
4779 | DBGPRINT_ERR("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n", pFrame->Hdr.FC.SubType); | ||
4780 | return FALSE; | ||
4781 | } | ||
4782 | } | ||
4783 | |||
4784 | /* OK, we got all the informations, it is time to put things into queue */ | ||
4785 | NdisAcquireSpinLock(&(Queue->Lock)); | ||
4786 | Tail = Queue->Tail; | ||
4787 | Queue->Tail++; | ||
4788 | Queue->Num++; | ||
4789 | if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) { | ||
4790 | Queue->Tail = 0; | ||
4791 | } | ||
4792 | Queue->Entry[Tail].Occupied = TRUE; | ||
4793 | Queue->Entry[Tail].Machine = Machine; | ||
4794 | Queue->Entry[Tail].MsgType = MsgType; | ||
4795 | Queue->Entry[Tail].MsgLen = MsgLen; | ||
4796 | Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow; | ||
4797 | Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh; | ||
4798 | Queue->Entry[Tail].Rssi0 = Rssi0; | ||
4799 | Queue->Entry[Tail].Rssi1 = Rssi1; | ||
4800 | Queue->Entry[Tail].Rssi2 = Rssi2; | ||
4801 | Queue->Entry[Tail].Signal = Signal; | ||
4802 | Queue->Entry[Tail].Wcid = (u8)Wcid; | ||
4803 | |||
4804 | Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel; | ||
4805 | |||
4806 | if (Msg != NULL) { | ||
4807 | NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen); | ||
4808 | } | ||
4809 | |||
4810 | NdisReleaseSpinLock(&(Queue->Lock)); | ||
4811 | |||
4812 | RTMP_MLME_HANDLER(pAd); | ||
4813 | |||
4814 | return TRUE; | ||
4815 | } | ||
4816 | |||
4817 | /*! \brief Dequeue a message from the MLME Queue | ||
4818 | * \param *Queue The MLME Queue | ||
4819 | * \param *Elem The message dequeued from MLME Queue | ||
4820 | * \return TRUE if the Elem contains something, FALSE otherwise | ||
4821 | * \pre | ||
4822 | * \post | ||
4823 | |||
4824 | IRQL = DISPATCH_LEVEL | ||
4825 | |||
4826 | */ | ||
4827 | BOOLEAN MlmeDequeue(struct rt_mlme_queue *Queue, struct rt_mlme_queue_elem ** Elem) | ||
4828 | { | ||
4829 | NdisAcquireSpinLock(&(Queue->Lock)); | ||
4830 | *Elem = &(Queue->Entry[Queue->Head]); | ||
4831 | Queue->Num--; | ||
4832 | Queue->Head++; | ||
4833 | if (Queue->Head == MAX_LEN_OF_MLME_QUEUE) { | ||
4834 | Queue->Head = 0; | ||
4835 | } | ||
4836 | NdisReleaseSpinLock(&(Queue->Lock)); | ||
4837 | return TRUE; | ||
4838 | } | ||
4839 | |||
4840 | /* IRQL = DISPATCH_LEVEL */ | ||
4841 | void MlmeRestartStateMachine(struct rt_rtmp_adapter *pAd) | ||
4842 | { | ||
4843 | #ifdef RTMP_MAC_PCI | ||
4844 | struct rt_mlme_queue_elem *Elem = NULL; | ||
4845 | #endif /* RTMP_MAC_PCI // */ | ||
4846 | BOOLEAN Cancelled; | ||
4847 | |||
4848 | DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n")); | ||
4849 | |||
4850 | #ifdef RTMP_MAC_PCI | ||
4851 | NdisAcquireSpinLock(&pAd->Mlme.TaskLock); | ||
4852 | if (pAd->Mlme.bRunning) { | ||
4853 | NdisReleaseSpinLock(&pAd->Mlme.TaskLock); | ||
4854 | return; | ||
4855 | } else { | ||
4856 | pAd->Mlme.bRunning = TRUE; | ||
4857 | } | ||
4858 | NdisReleaseSpinLock(&pAd->Mlme.TaskLock); | ||
4859 | |||
4860 | /* Remove all Mlme queues elements */ | ||
4861 | while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) { | ||
4862 | /*From message type, determine which state machine I should drive */ | ||
4863 | if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) { | ||
4864 | /* free MLME element */ | ||
4865 | Elem->Occupied = FALSE; | ||
4866 | Elem->MsgLen = 0; | ||
4867 | |||
4868 | } else { | ||
4869 | DBGPRINT_ERR("MlmeRestartStateMachine: MlmeQueue empty\n"); | ||
4870 | } | ||
4871 | } | ||
4872 | #endif /* RTMP_MAC_PCI // */ | ||
4873 | |||
4874 | { | ||
4875 | /* Cancel all timer events */ | ||
4876 | /* Be careful to cancel new added timer */ | ||
4877 | RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled); | ||
4878 | RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled); | ||
4879 | RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled); | ||
4880 | RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled); | ||
4881 | RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled); | ||
4882 | RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); | ||
4883 | |||
4884 | } | ||
4885 | |||
4886 | /* Change back to original channel in case of doing scan */ | ||
4887 | AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); | ||
4888 | AsicLockChannel(pAd, pAd->CommonCfg.Channel); | ||
4889 | |||
4890 | /* Resume MSDU which is turned off durning scan */ | ||
4891 | RTMPResumeMsduTransmission(pAd); | ||
4892 | |||
4893 | { | ||
4894 | /* Set all state machines back IDLE */ | ||
4895 | pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; | ||
4896 | pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; | ||
4897 | pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; | ||
4898 | pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE; | ||
4899 | pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; | ||
4900 | pAd->Mlme.ActMachine.CurrState = ACT_IDLE; | ||
4901 | } | ||
4902 | |||
4903 | #ifdef RTMP_MAC_PCI | ||
4904 | /* Remove running state */ | ||
4905 | NdisAcquireSpinLock(&pAd->Mlme.TaskLock); | ||
4906 | pAd->Mlme.bRunning = FALSE; | ||
4907 | NdisReleaseSpinLock(&pAd->Mlme.TaskLock); | ||
4908 | #endif /* RTMP_MAC_PCI // */ | ||
4909 | } | ||
4910 | |||
4911 | /*! \brief test if the MLME Queue is empty | ||
4912 | * \param *Queue The MLME Queue | ||
4913 | * \return TRUE if the Queue is empty, FALSE otherwise | ||
4914 | * \pre | ||
4915 | * \post | ||
4916 | |||
4917 | IRQL = DISPATCH_LEVEL | ||
4918 | |||
4919 | */ | ||
4920 | BOOLEAN MlmeQueueEmpty(struct rt_mlme_queue *Queue) | ||
4921 | { | ||
4922 | BOOLEAN Ans; | ||
4923 | |||
4924 | NdisAcquireSpinLock(&(Queue->Lock)); | ||
4925 | Ans = (Queue->Num == 0); | ||
4926 | NdisReleaseSpinLock(&(Queue->Lock)); | ||
4927 | |||
4928 | return Ans; | ||
4929 | } | ||
4930 | |||
4931 | /*! \brief test if the MLME Queue is full | ||
4932 | * \param *Queue The MLME Queue | ||
4933 | * \return TRUE if the Queue is empty, FALSE otherwise | ||
4934 | * \pre | ||
4935 | * \post | ||
4936 | |||
4937 | IRQL = PASSIVE_LEVEL | ||
4938 | IRQL = DISPATCH_LEVEL | ||
4939 | |||
4940 | */ | ||
4941 | BOOLEAN MlmeQueueFull(struct rt_mlme_queue *Queue) | ||
4942 | { | ||
4943 | BOOLEAN Ans; | ||
4944 | |||
4945 | NdisAcquireSpinLock(&(Queue->Lock)); | ||
4946 | Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE | ||
4947 | || Queue->Entry[Queue->Tail].Occupied); | ||
4948 | NdisReleaseSpinLock(&(Queue->Lock)); | ||
4949 | |||
4950 | return Ans; | ||
4951 | } | ||
4952 | |||
4953 | /*! \brief The destructor of MLME Queue | ||
4954 | * \param | ||
4955 | * \return | ||
4956 | * \pre | ||
4957 | * \post | ||
4958 | * \note Clear Mlme Queue, Set Queue->Num to Zero. | ||
4959 | |||
4960 | IRQL = PASSIVE_LEVEL | ||
4961 | |||
4962 | */ | ||
4963 | void MlmeQueueDestroy(struct rt_mlme_queue *pQueue) | ||
4964 | { | ||
4965 | NdisAcquireSpinLock(&(pQueue->Lock)); | ||
4966 | pQueue->Num = 0; | ||
4967 | pQueue->Head = 0; | ||
4968 | pQueue->Tail = 0; | ||
4969 | NdisReleaseSpinLock(&(pQueue->Lock)); | ||
4970 | NdisFreeSpinLock(&(pQueue->Lock)); | ||
4971 | } | ||
4972 | |||
4973 | /*! \brief To substitute the message type if the message is coming from external | ||
4974 | * \param pFrame The frame received | ||
4975 | * \param *Machine The state machine | ||
4976 | * \param *MsgType the message type for the state machine | ||
4977 | * \return TRUE if the substitution is successful, FALSE otherwise | ||
4978 | * \pre | ||
4979 | * \post | ||
4980 | |||
4981 | IRQL = DISPATCH_LEVEL | ||
4982 | |||
4983 | */ | ||
4984 | BOOLEAN MsgTypeSubst(struct rt_rtmp_adapter *pAd, | ||
4985 | struct rt_frame_802_11 * pFrame, | ||
4986 | int * Machine, int * MsgType) | ||
4987 | { | ||
4988 | u16 Seq, Alg; | ||
4989 | u8 EAPType; | ||
4990 | u8 *pData; | ||
4991 | |||
4992 | /* Pointer to start of data frames including SNAP header */ | ||
4993 | pData = (u8 *)pFrame + LENGTH_802_11; | ||
4994 | |||
4995 | /* The only data type will pass to this function is EAPOL frame */ | ||
4996 | if (pFrame->Hdr.FC.Type == BTYPE_DATA) { | ||
4997 | { | ||
4998 | *Machine = WPA_STATE_MACHINE; | ||
4999 | EAPType = | ||
5000 | *((u8 *) pFrame + LENGTH_802_11 + | ||
5001 | LENGTH_802_1_H + 1); | ||
5002 | return (WpaMsgTypeSubst(EAPType, (int *) MsgType)); | ||
5003 | } | ||
5004 | } | ||
5005 | |||
5006 | switch (pFrame->Hdr.FC.SubType) { | ||
5007 | case SUBTYPE_ASSOC_REQ: | ||
5008 | *Machine = ASSOC_STATE_MACHINE; | ||
5009 | *MsgType = MT2_PEER_ASSOC_REQ; | ||
5010 | break; | ||
5011 | case SUBTYPE_ASSOC_RSP: | ||
5012 | *Machine = ASSOC_STATE_MACHINE; | ||
5013 | *MsgType = MT2_PEER_ASSOC_RSP; | ||
5014 | break; | ||
5015 | case SUBTYPE_REASSOC_REQ: | ||
5016 | *Machine = ASSOC_STATE_MACHINE; | ||
5017 | *MsgType = MT2_PEER_REASSOC_REQ; | ||
5018 | break; | ||
5019 | case SUBTYPE_REASSOC_RSP: | ||
5020 | *Machine = ASSOC_STATE_MACHINE; | ||
5021 | *MsgType = MT2_PEER_REASSOC_RSP; | ||
5022 | break; | ||
5023 | case SUBTYPE_PROBE_REQ: | ||
5024 | *Machine = SYNC_STATE_MACHINE; | ||
5025 | *MsgType = MT2_PEER_PROBE_REQ; | ||
5026 | break; | ||
5027 | case SUBTYPE_PROBE_RSP: | ||
5028 | *Machine = SYNC_STATE_MACHINE; | ||
5029 | *MsgType = MT2_PEER_PROBE_RSP; | ||
5030 | break; | ||
5031 | case SUBTYPE_BEACON: | ||
5032 | *Machine = SYNC_STATE_MACHINE; | ||
5033 | *MsgType = MT2_PEER_BEACON; | ||
5034 | break; | ||
5035 | case SUBTYPE_ATIM: | ||
5036 | *Machine = SYNC_STATE_MACHINE; | ||
5037 | *MsgType = MT2_PEER_ATIM; | ||
5038 | break; | ||
5039 | case SUBTYPE_DISASSOC: | ||
5040 | *Machine = ASSOC_STATE_MACHINE; | ||
5041 | *MsgType = MT2_PEER_DISASSOC_REQ; | ||
5042 | break; | ||
5043 | case SUBTYPE_AUTH: | ||
5044 | /* get the sequence number from payload 24 Mac Header + 2 bytes algorithm */ | ||
5045 | NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(u16)); | ||
5046 | NdisMoveMemory(&Alg, &pFrame->Octet[0], sizeof(u16)); | ||
5047 | if (Seq == 1 || Seq == 3) { | ||
5048 | *Machine = AUTH_RSP_STATE_MACHINE; | ||
5049 | *MsgType = MT2_PEER_AUTH_ODD; | ||
5050 | } else if (Seq == 2 || Seq == 4) { | ||
5051 | if (Alg == AUTH_MODE_OPEN || Alg == AUTH_MODE_KEY) { | ||
5052 | *Machine = AUTH_STATE_MACHINE; | ||
5053 | *MsgType = MT2_PEER_AUTH_EVEN; | ||
5054 | } | ||
5055 | } else { | ||
5056 | return FALSE; | ||
5057 | } | ||
5058 | break; | ||
5059 | case SUBTYPE_DEAUTH: | ||
5060 | *Machine = AUTH_RSP_STATE_MACHINE; | ||
5061 | *MsgType = MT2_PEER_DEAUTH; | ||
5062 | break; | ||
5063 | case SUBTYPE_ACTION: | ||
5064 | *Machine = ACTION_STATE_MACHINE; | ||
5065 | /* Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support */ | ||
5066 | if ((pFrame->Octet[0] & 0x7F) > MAX_PEER_CATE_MSG) { | ||
5067 | *MsgType = MT2_ACT_INVALID; | ||
5068 | } else { | ||
5069 | *MsgType = (pFrame->Octet[0] & 0x7F); | ||
5070 | } | ||
5071 | break; | ||
5072 | default: | ||
5073 | return FALSE; | ||
5074 | break; | ||
5075 | } | ||
5076 | |||
5077 | return TRUE; | ||
5078 | } | ||
5079 | |||
5080 | /* =========================================================================================== */ | ||
5081 | /* state_machine.c */ | ||
5082 | /* =========================================================================================== */ | ||
5083 | |||
5084 | /*! \brief Initialize the state machine. | ||
5085 | * \param *S pointer to the state machine | ||
5086 | * \param Trans State machine transition function | ||
5087 | * \param StNr number of states | ||
5088 | * \param MsgNr number of messages | ||
5089 | * \param DefFunc default function, when there is invalid state/message combination | ||
5090 | * \param InitState initial state of the state machine | ||
5091 | * \param Base StateMachine base, internal use only | ||
5092 | * \pre p_sm should be a legal pointer | ||
5093 | * \post | ||
5094 | |||
5095 | IRQL = PASSIVE_LEVEL | ||
5096 | |||
5097 | */ | ||
5098 | void StateMachineInit(struct rt_state_machine *S, | ||
5099 | IN STATE_MACHINE_FUNC Trans[], | ||
5100 | unsigned long StNr, | ||
5101 | unsigned long MsgNr, | ||
5102 | IN STATE_MACHINE_FUNC DefFunc, | ||
5103 | unsigned long InitState, unsigned long Base) | ||
5104 | { | ||
5105 | unsigned long i, j; | ||
5106 | |||
5107 | /* set number of states and messages */ | ||
5108 | S->NrState = StNr; | ||
5109 | S->NrMsg = MsgNr; | ||
5110 | S->Base = Base; | ||
5111 | |||
5112 | S->TransFunc = Trans; | ||
5113 | |||
5114 | /* init all state transition to default function */ | ||
5115 | for (i = 0; i < StNr; i++) { | ||
5116 | for (j = 0; j < MsgNr; j++) { | ||
5117 | S->TransFunc[i * MsgNr + j] = DefFunc; | ||
5118 | } | ||
5119 | } | ||
5120 | |||
5121 | /* set the starting state */ | ||
5122 | S->CurrState = InitState; | ||
5123 | } | ||
5124 | |||
5125 | /*! \brief This function fills in the function pointer into the cell in the state machine | ||
5126 | * \param *S pointer to the state machine | ||
5127 | * \param St state | ||
5128 | * \param Msg incoming message | ||
5129 | * \param f the function to be executed when (state, message) combination occurs at the state machine | ||
5130 | * \pre *S should be a legal pointer to the state machine, st, msg, should be all within the range, Base should be set in the initial state | ||
5131 | * \post | ||
5132 | |||
5133 | IRQL = PASSIVE_LEVEL | ||
5134 | |||
5135 | */ | ||
5136 | void StateMachineSetAction(struct rt_state_machine *S, | ||
5137 | unsigned long St, | ||
5138 | unsigned long Msg, IN STATE_MACHINE_FUNC Func) | ||
5139 | { | ||
5140 | unsigned long MsgIdx; | ||
5141 | |||
5142 | MsgIdx = Msg - S->Base; | ||
5143 | |||
5144 | if (St < S->NrState && MsgIdx < S->NrMsg) { | ||
5145 | /* boundary checking before setting the action */ | ||
5146 | S->TransFunc[St * S->NrMsg + MsgIdx] = Func; | ||
5147 | } | ||
5148 | } | ||
5149 | |||
5150 | /*! \brief This function does the state transition | ||
5151 | * \param *Adapter the NIC adapter pointer | ||
5152 | * \param *S the state machine | ||
5153 | * \param *Elem the message to be executed | ||
5154 | * \return None | ||
5155 | |||
5156 | IRQL = DISPATCH_LEVEL | ||
5157 | |||
5158 | */ | ||
5159 | void StateMachinePerformAction(struct rt_rtmp_adapter *pAd, | ||
5160 | struct rt_state_machine *S, struct rt_mlme_queue_elem *Elem) | ||
5161 | { | ||
5162 | (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base])) | ||
5163 | (pAd, Elem); | ||
5164 | } | ||
5165 | |||
5166 | /* | ||
5167 | ========================================================================== | ||
5168 | Description: | ||
5169 | The drop function, when machine executes this, the message is simply | ||
5170 | ignored. This function does nothing, the message is freed in | ||
5171 | StateMachinePerformAction() | ||
5172 | ========================================================================== | ||
5173 | */ | ||
5174 | void Drop(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) | ||
5175 | { | ||
5176 | } | ||
5177 | |||
5178 | /* =========================================================================================== */ | ||
5179 | /* lfsr.c */ | ||
5180 | /* =========================================================================================== */ | ||
5181 | |||
5182 | /* | ||
5183 | ========================================================================== | ||
5184 | Description: | ||
5185 | |||
5186 | IRQL = PASSIVE_LEVEL | ||
5187 | |||
5188 | ========================================================================== | ||
5189 | */ | ||
5190 | void LfsrInit(struct rt_rtmp_adapter *pAd, unsigned long Seed) | ||
5191 | { | ||
5192 | if (Seed == 0) | ||
5193 | pAd->Mlme.ShiftReg = 1; | ||
5194 | else | ||
5195 | pAd->Mlme.ShiftReg = Seed; | ||
5196 | } | ||
5197 | |||
5198 | /* | ||
5199 | ========================================================================== | ||
5200 | Description: | ||
5201 | ========================================================================== | ||
5202 | */ | ||
5203 | u8 RandomByte(struct rt_rtmp_adapter *pAd) | ||
5204 | { | ||
5205 | unsigned long i; | ||
5206 | u8 R, Result; | ||
5207 | |||
5208 | R = 0; | ||
5209 | |||
5210 | if (pAd->Mlme.ShiftReg == 0) | ||
5211 | NdisGetSystemUpTime((unsigned long *) & pAd->Mlme.ShiftReg); | ||
5212 | |||
5213 | for (i = 0; i < 8; i++) { | ||
5214 | if (pAd->Mlme.ShiftReg & 0x00000001) { | ||
5215 | pAd->Mlme.ShiftReg = | ||
5216 | ((pAd->Mlme. | ||
5217 | ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000; | ||
5218 | Result = 1; | ||
5219 | } else { | ||
5220 | pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1; | ||
5221 | Result = 0; | ||
5222 | } | ||
5223 | R = (R << 1) | Result; | ||
5224 | } | ||
5225 | |||
5226 | return R; | ||
5227 | } | ||
5228 | |||
5229 | /* | ||
5230 | ======================================================================== | ||
5231 | |||
5232 | Routine Description: | ||
5233 | Verify the support rate for different PHY type | ||
5234 | |||
5235 | Arguments: | ||
5236 | pAd Pointer to our adapter | ||
5237 | |||
5238 | Return Value: | ||
5239 | None | ||
5240 | |||
5241 | IRQL = PASSIVE_LEVEL | ||
5242 | |||
5243 | ======================================================================== | ||
5244 | */ | ||
5245 | void RTMPCheckRates(struct rt_rtmp_adapter *pAd, | ||
5246 | IN u8 SupRate[], IN u8 * SupRateLen) | ||
5247 | { | ||
5248 | u8 RateIdx, i, j; | ||
5249 | u8 NewRate[12], NewRateLen; | ||
5250 | |||
5251 | NewRateLen = 0; | ||
5252 | |||
5253 | if (pAd->CommonCfg.PhyMode == PHY_11B) | ||
5254 | RateIdx = 4; | ||
5255 | else | ||
5256 | RateIdx = 12; | ||
5257 | |||
5258 | /* Check for support rates exclude basic rate bit */ | ||
5259 | for (i = 0; i < *SupRateLen; i++) | ||
5260 | for (j = 0; j < RateIdx; j++) | ||
5261 | if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j]) | ||
5262 | NewRate[NewRateLen++] = SupRate[i]; | ||
5263 | |||
5264 | *SupRateLen = NewRateLen; | ||
5265 | NdisMoveMemory(SupRate, NewRate, NewRateLen); | ||
5266 | } | ||
5267 | |||
5268 | BOOLEAN RTMPCheckChannel(struct rt_rtmp_adapter *pAd, | ||
5269 | u8 CentralChannel, u8 Channel) | ||
5270 | { | ||
5271 | u8 k; | ||
5272 | u8 UpperChannel = 0, LowerChannel = 0; | ||
5273 | u8 NoEffectChannelinList = 0; | ||
5274 | |||
5275 | /* Find upper and lower channel according to 40MHz current operation. */ | ||
5276 | if (CentralChannel < Channel) { | ||
5277 | UpperChannel = Channel; | ||
5278 | if (CentralChannel > 2) | ||
5279 | LowerChannel = CentralChannel - 2; | ||
5280 | else | ||
5281 | return FALSE; | ||
5282 | } else if (CentralChannel > Channel) { | ||
5283 | UpperChannel = CentralChannel + 2; | ||
5284 | LowerChannel = Channel; | ||
5285 | } | ||
5286 | |||
5287 | for (k = 0; k < pAd->ChannelListNum; k++) { | ||
5288 | if (pAd->ChannelList[k].Channel == UpperChannel) { | ||
5289 | NoEffectChannelinList++; | ||
5290 | } | ||
5291 | if (pAd->ChannelList[k].Channel == LowerChannel) { | ||
5292 | NoEffectChannelinList++; | ||
5293 | } | ||
5294 | } | ||
5295 | |||
5296 | DBGPRINT(RT_DEBUG_TRACE, | ||
5297 | ("Total Channel in Channel List = [%d]\n", | ||
5298 | NoEffectChannelinList)); | ||
5299 | if (NoEffectChannelinList == 2) | ||
5300 | return TRUE; | ||
5301 | else | ||
5302 | return FALSE; | ||
5303 | } | ||
5304 | |||
5305 | /* | ||
5306 | ======================================================================== | ||
5307 | |||
5308 | Routine Description: | ||
5309 | Verify the support rate for HT phy type | ||
5310 | |||
5311 | Arguments: | ||
5312 | pAd Pointer to our adapter | ||
5313 | |||
5314 | Return Value: | ||
5315 | FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode) | ||
5316 | |||
5317 | IRQL = PASSIVE_LEVEL | ||
5318 | |||
5319 | ======================================================================== | ||
5320 | */ | ||
5321 | BOOLEAN RTMPCheckHt(struct rt_rtmp_adapter *pAd, | ||
5322 | u8 Wcid, | ||
5323 | struct rt_ht_capability_ie * pHtCapability, | ||
5324 | struct rt_add_ht_info_ie * pAddHtInfo) | ||
5325 | { | ||
5326 | if (Wcid >= MAX_LEN_OF_MAC_TABLE) | ||
5327 | return FALSE; | ||
5328 | |||
5329 | /* If use AMSDU, set flag. */ | ||
5330 | if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable) | ||
5331 | CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], | ||
5332 | fCLIENT_STATUS_AMSDU_INUSED); | ||
5333 | /* Save Peer Capability */ | ||
5334 | if (pHtCapability->HtCapInfo.ShortGIfor20) | ||
5335 | CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], | ||
5336 | fCLIENT_STATUS_SGI20_CAPABLE); | ||
5337 | if (pHtCapability->HtCapInfo.ShortGIfor40) | ||
5338 | CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], | ||
5339 | fCLIENT_STATUS_SGI40_CAPABLE); | ||
5340 | if (pHtCapability->HtCapInfo.TxSTBC) | ||
5341 | CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], | ||
5342 | fCLIENT_STATUS_TxSTBC_CAPABLE); | ||
5343 | if (pHtCapability->HtCapInfo.RxSTBC) | ||
5344 | CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], | ||
5345 | fCLIENT_STATUS_RxSTBC_CAPABLE); | ||
5346 | if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport) { | ||
5347 | CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], | ||
5348 | fCLIENT_STATUS_RDG_CAPABLE); | ||
5349 | } | ||
5350 | |||
5351 | if (Wcid < MAX_LEN_OF_MAC_TABLE) { | ||
5352 | pAd->MacTab.Content[Wcid].MpduDensity = | ||
5353 | pHtCapability->HtCapParm.MpduDensity; | ||
5354 | } | ||
5355 | /* Will check ChannelWidth for MCSSet[4] below */ | ||
5356 | pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1; | ||
5357 | switch (pAd->CommonCfg.RxStream) { | ||
5358 | case 1: | ||
5359 | pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff; | ||
5360 | pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00; | ||
5361 | pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00; | ||
5362 | pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00; | ||
5363 | break; | ||
5364 | case 2: | ||
5365 | pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff; | ||
5366 | pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff; | ||
5367 | pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00; | ||
5368 | pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00; | ||
5369 | break; | ||
5370 | case 3: | ||
5371 | pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff; | ||
5372 | pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff; | ||
5373 | pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff; | ||
5374 | pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00; | ||
5375 | break; | ||
5376 | } | ||
5377 | |||
5378 | pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = | ||
5379 | pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy. | ||
5380 | ChannelWidth; | ||
5381 | |||
5382 | DBGPRINT(RT_DEBUG_TRACE, | ||
5383 | ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n", | ||
5384 | pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, | ||
5385 | pAddHtInfo->AddHtInfo.RecomWidth, | ||
5386 | pAd->CommonCfg.DesiredHtPhy.ChannelWidth, | ||
5387 | pAd->NicConfig2.field.BW40MAvailForA, | ||
5388 | pAd->NicConfig2.field.BW40MAvailForG, | ||
5389 | pAd->CommonCfg.PhyMode)); | ||
5390 | |||
5391 | pAd->MlmeAux.HtCapability.HtCapInfo.GF = | ||
5392 | pHtCapability->HtCapInfo.GF & pAd->CommonCfg.DesiredHtPhy.GF; | ||
5393 | |||
5394 | /* Send Assoc Req with my HT capability. */ | ||
5395 | pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = | ||
5396 | pAd->CommonCfg.DesiredHtPhy.AmsduSize; | ||
5397 | pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = | ||
5398 | pAd->CommonCfg.DesiredHtPhy.MimoPs; | ||
5399 | pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = | ||
5400 | (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability-> | ||
5401 | HtCapInfo. | ||
5402 | ShortGIfor20); | ||
5403 | pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = | ||
5404 | (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability-> | ||
5405 | HtCapInfo. | ||
5406 | ShortGIfor40); | ||
5407 | pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = | ||
5408 | (pAd->CommonCfg.DesiredHtPhy.TxSTBC) & (pHtCapability->HtCapInfo. | ||
5409 | RxSTBC); | ||
5410 | pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = | ||
5411 | (pAd->CommonCfg.DesiredHtPhy.RxSTBC) & (pHtCapability->HtCapInfo. | ||
5412 | TxSTBC); | ||
5413 | pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = | ||
5414 | pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor; | ||
5415 | pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = | ||
5416 | pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity; | ||
5417 | pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = | ||
5418 | pHtCapability->ExtHtCapInfo.PlusHTC; | ||
5419 | pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = | ||
5420 | pHtCapability->ExtHtCapInfo.PlusHTC; | ||
5421 | if (pAd->CommonCfg.bRdg) { | ||
5422 | pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = | ||
5423 | pHtCapability->ExtHtCapInfo.RDGSupport; | ||
5424 | pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1; | ||
5425 | } | ||
5426 | |||
5427 | if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20) | ||
5428 | pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; /* BW20 can't transmit MCS32 */ | ||
5429 | |||
5430 | COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability); | ||
5431 | return TRUE; | ||
5432 | } | ||
5433 | |||
5434 | /* | ||
5435 | ======================================================================== | ||
5436 | |||
5437 | Routine Description: | ||
5438 | Verify the support rate for different PHY type | ||
5439 | |||
5440 | Arguments: | ||
5441 | pAd Pointer to our adapter | ||
5442 | |||
5443 | Return Value: | ||
5444 | None | ||
5445 | |||
5446 | IRQL = PASSIVE_LEVEL | ||
5447 | |||
5448 | ======================================================================== | ||
5449 | */ | ||
5450 | void RTMPUpdateMlmeRate(struct rt_rtmp_adapter *pAd) | ||
5451 | { | ||
5452 | u8 MinimumRate; | ||
5453 | u8 ProperMlmeRate; /*= RATE_54; */ | ||
5454 | u8 i, j, RateIdx = 12; /*1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */ | ||
5455 | BOOLEAN bMatch = FALSE; | ||
5456 | |||
5457 | switch (pAd->CommonCfg.PhyMode) { | ||
5458 | case PHY_11B: | ||
5459 | ProperMlmeRate = RATE_11; | ||
5460 | MinimumRate = RATE_1; | ||
5461 | break; | ||
5462 | case PHY_11BG_MIXED: | ||
5463 | case PHY_11ABGN_MIXED: | ||
5464 | case PHY_11BGN_MIXED: | ||
5465 | if ((pAd->MlmeAux.SupRateLen == 4) && | ||
5466 | (pAd->MlmeAux.ExtRateLen == 0)) | ||
5467 | /* B only AP */ | ||
5468 | ProperMlmeRate = RATE_11; | ||
5469 | else | ||
5470 | ProperMlmeRate = RATE_24; | ||
5471 | |||
5472 | if (pAd->MlmeAux.Channel <= 14) | ||
5473 | MinimumRate = RATE_1; | ||
5474 | else | ||
5475 | MinimumRate = RATE_6; | ||
5476 | break; | ||
5477 | case PHY_11A: | ||
5478 | case PHY_11N_2_4G: /* rt2860 need to check mlmerate for 802.11n */ | ||
5479 | case PHY_11GN_MIXED: | ||
5480 | case PHY_11AGN_MIXED: | ||
5481 | case PHY_11AN_MIXED: | ||
5482 | case PHY_11N_5G: | ||
5483 | ProperMlmeRate = RATE_24; | ||
5484 | MinimumRate = RATE_6; | ||
5485 | break; | ||
5486 | case PHY_11ABG_MIXED: | ||
5487 | ProperMlmeRate = RATE_24; | ||
5488 | if (pAd->MlmeAux.Channel <= 14) | ||
5489 | MinimumRate = RATE_1; | ||
5490 | else | ||
5491 | MinimumRate = RATE_6; | ||
5492 | break; | ||
5493 | default: /* error */ | ||
5494 | ProperMlmeRate = RATE_1; | ||
5495 | MinimumRate = RATE_1; | ||
5496 | break; | ||
5497 | } | ||
5498 | |||
5499 | for (i = 0; i < pAd->MlmeAux.SupRateLen; i++) { | ||
5500 | for (j = 0; j < RateIdx; j++) { | ||
5501 | if ((pAd->MlmeAux.SupRate[i] & 0x7f) == | ||
5502 | RateIdTo500Kbps[j]) { | ||
5503 | if (j == ProperMlmeRate) { | ||
5504 | bMatch = TRUE; | ||
5505 | break; | ||
5506 | } | ||
5507 | } | ||
5508 | } | ||
5509 | |||
5510 | if (bMatch) | ||
5511 | break; | ||
5512 | } | ||
5513 | |||
5514 | if (bMatch == FALSE) { | ||
5515 | for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++) { | ||
5516 | for (j = 0; j < RateIdx; j++) { | ||
5517 | if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == | ||
5518 | RateIdTo500Kbps[j]) { | ||
5519 | if (j == ProperMlmeRate) { | ||
5520 | bMatch = TRUE; | ||
5521 | break; | ||
5522 | } | ||
5523 | } | ||
5524 | } | ||
5525 | |||
5526 | if (bMatch) | ||
5527 | break; | ||
5528 | } | ||
5529 | } | ||
5530 | |||
5531 | if (bMatch == FALSE) { | ||
5532 | ProperMlmeRate = MinimumRate; | ||
5533 | } | ||
5534 | |||
5535 | pAd->CommonCfg.MlmeRate = MinimumRate; | ||
5536 | pAd->CommonCfg.RtsRate = ProperMlmeRate; | ||
5537 | if (pAd->CommonCfg.MlmeRate >= RATE_6) { | ||
5538 | pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; | ||
5539 | pAd->CommonCfg.MlmeTransmit.field.MCS = | ||
5540 | OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; | ||
5541 | pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = | ||
5542 | MODE_OFDM; | ||
5543 | pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = | ||
5544 | OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; | ||
5545 | } else { | ||
5546 | pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; | ||
5547 | pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate; | ||
5548 | pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = | ||
5549 | MODE_CCK; | ||
5550 | pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = | ||
5551 | pAd->CommonCfg.MlmeRate; | ||
5552 | } | ||
5553 | |||
5554 | DBGPRINT(RT_DEBUG_TRACE, | ||
5555 | ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n", | ||
5556 | pAd->CommonCfg.MlmeTransmit.word)); | ||
5557 | } | ||
5558 | |||
5559 | char RTMPMaxRssi(struct rt_rtmp_adapter *pAd, | ||
5560 | char Rssi0, char Rssi1, char Rssi2) | ||
5561 | { | ||
5562 | char larger = -127; | ||
5563 | |||
5564 | if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0)) { | ||
5565 | larger = Rssi0; | ||
5566 | } | ||
5567 | |||
5568 | if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0)) { | ||
5569 | larger = max(Rssi0, Rssi1); | ||
5570 | } | ||
5571 | |||
5572 | if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0)) { | ||
5573 | larger = max(larger, Rssi2); | ||
5574 | } | ||
5575 | |||
5576 | if (larger == -127) | ||
5577 | larger = 0; | ||
5578 | |||
5579 | return larger; | ||
5580 | } | ||
5581 | |||
5582 | /* | ||
5583 | ======================================================================== | ||
5584 | Routine Description: | ||
5585 | Periodic evaluate antenna link status | ||
5586 | |||
5587 | Arguments: | ||
5588 | pAd - Adapter pointer | ||
5589 | |||
5590 | Return Value: | ||
5591 | None | ||
5592 | |||
5593 | ======================================================================== | ||
5594 | */ | ||
5595 | void AsicEvaluateRxAnt(struct rt_rtmp_adapter *pAd) | ||
5596 | { | ||
5597 | u8 BBPR3 = 0; | ||
5598 | |||
5599 | if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS | | ||
5600 | fRTMP_ADAPTER_HALT_IN_PROGRESS | | ||
5601 | fRTMP_ADAPTER_RADIO_OFF | | ||
5602 | fRTMP_ADAPTER_NIC_NOT_EXIST | | ||
5603 | fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) || | ||
5604 | OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) | ||
5605 | #ifdef RT30xx | ||
5606 | || (pAd->EepromAccess) | ||
5607 | #endif /* RT30xx // */ | ||
5608 | #ifdef RT3090 | ||
5609 | || (pAd->bPCIclkOff == TRUE) | ||
5610 | #endif /* RT3090 // */ | ||
5611 | ) | ||
5612 | return; | ||
5613 | |||
5614 | { | ||
5615 | /*if (pAd->StaCfg.Psm == PWR_SAVE) */ | ||
5616 | /* return; */ | ||
5617 | |||
5618 | { | ||
5619 | |||
5620 | if (pAd->StaCfg.Psm == PWR_SAVE) | ||
5621 | return; | ||
5622 | |||
5623 | RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); | ||
5624 | BBPR3 &= (~0x18); | ||
5625 | if (pAd->Antenna.field.RxPath == 3) { | ||
5626 | BBPR3 |= (0x10); | ||
5627 | } else if (pAd->Antenna.field.RxPath == 2) { | ||
5628 | BBPR3 |= (0x8); | ||
5629 | } else if (pAd->Antenna.field.RxPath == 1) { | ||
5630 | BBPR3 |= (0x0); | ||
5631 | } | ||
5632 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); | ||
5633 | #ifdef RTMP_MAC_PCI | ||
5634 | pAd->StaCfg.BBPR3 = BBPR3; | ||
5635 | #endif /* RTMP_MAC_PCI // */ | ||
5636 | if (OPSTATUS_TEST_FLAG | ||
5637 | (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) | ||
5638 | ) { | ||
5639 | unsigned long TxTotalCnt = | ||
5640 | pAd->RalinkCounters.OneSecTxNoRetryOkCount + | ||
5641 | pAd->RalinkCounters.OneSecTxRetryOkCount + | ||
5642 | pAd->RalinkCounters.OneSecTxFailCount; | ||
5643 | |||
5644 | /* dynamic adjust antenna evaluation period according to the traffic */ | ||
5645 | if (TxTotalCnt > 50) { | ||
5646 | RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, | ||
5647 | 20); | ||
5648 | pAd->Mlme.bLowThroughput = FALSE; | ||
5649 | } else { | ||
5650 | RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, | ||
5651 | 300); | ||
5652 | pAd->Mlme.bLowThroughput = TRUE; | ||
5653 | } | ||
5654 | } | ||
5655 | } | ||
5656 | |||
5657 | } | ||
5658 | |||
5659 | } | ||
5660 | |||
5661 | /* | ||
5662 | ======================================================================== | ||
5663 | Routine Description: | ||
5664 | After evaluation, check antenna link status | ||
5665 | |||
5666 | Arguments: | ||
5667 | pAd - Adapter pointer | ||
5668 | |||
5669 | Return Value: | ||
5670 | None | ||
5671 | |||
5672 | ======================================================================== | ||
5673 | */ | ||
5674 | void AsicRxAntEvalTimeout(void *SystemSpecific1, | ||
5675 | void *FunctionContext, | ||
5676 | void *SystemSpecific2, void *SystemSpecific3) | ||
5677 | { | ||
5678 | struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; | ||
5679 | u8 BBPR3 = 0; | ||
5680 | char larger = -127, rssi0, rssi1, rssi2; | ||
5681 | |||
5682 | if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS | | ||
5683 | fRTMP_ADAPTER_HALT_IN_PROGRESS | | ||
5684 | fRTMP_ADAPTER_RADIO_OFF | | ||
5685 | fRTMP_ADAPTER_NIC_NOT_EXIST) || | ||
5686 | OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) | ||
5687 | #ifdef RT30xx | ||
5688 | || (pAd->EepromAccess) | ||
5689 | #endif /* RT30xx // */ | ||
5690 | #ifdef RT3090 | ||
5691 | || (pAd->bPCIclkOff == TRUE) | ||
5692 | #endif /* RT3090 // */ | ||
5693 | ) | ||
5694 | return; | ||
5695 | |||
5696 | { | ||
5697 | /*if (pAd->StaCfg.Psm == PWR_SAVE) */ | ||
5698 | /* return; */ | ||
5699 | { | ||
5700 | if (pAd->StaCfg.Psm == PWR_SAVE) | ||
5701 | return; | ||
5702 | |||
5703 | /* if the traffic is low, use average rssi as the criteria */ | ||
5704 | if (pAd->Mlme.bLowThroughput == TRUE) { | ||
5705 | rssi0 = pAd->StaCfg.RssiSample.LastRssi0; | ||
5706 | rssi1 = pAd->StaCfg.RssiSample.LastRssi1; | ||
5707 | rssi2 = pAd->StaCfg.RssiSample.LastRssi2; | ||
5708 | } else { | ||
5709 | rssi0 = pAd->StaCfg.RssiSample.AvgRssi0; | ||
5710 | rssi1 = pAd->StaCfg.RssiSample.AvgRssi1; | ||
5711 | rssi2 = pAd->StaCfg.RssiSample.AvgRssi2; | ||
5712 | } | ||
5713 | |||
5714 | if (pAd->Antenna.field.RxPath == 3) { | ||
5715 | larger = max(rssi0, rssi1); | ||
5716 | |||
5717 | if (larger > (rssi2 + 20)) | ||
5718 | pAd->Mlme.RealRxPath = 2; | ||
5719 | else | ||
5720 | pAd->Mlme.RealRxPath = 3; | ||
5721 | } else if (pAd->Antenna.field.RxPath == 2) { | ||
5722 | if (rssi0 > (rssi1 + 20)) | ||
5723 | pAd->Mlme.RealRxPath = 1; | ||
5724 | else | ||
5725 | pAd->Mlme.RealRxPath = 2; | ||
5726 | } | ||
5727 | |||
5728 | RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); | ||
5729 | BBPR3 &= (~0x18); | ||
5730 | if (pAd->Mlme.RealRxPath == 3) { | ||
5731 | BBPR3 |= (0x10); | ||
5732 | } else if (pAd->Mlme.RealRxPath == 2) { | ||
5733 | BBPR3 |= (0x8); | ||
5734 | } else if (pAd->Mlme.RealRxPath == 1) { | ||
5735 | BBPR3 |= (0x0); | ||
5736 | } | ||
5737 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); | ||
5738 | #ifdef RTMP_MAC_PCI | ||
5739 | pAd->StaCfg.BBPR3 = BBPR3; | ||
5740 | #endif /* RTMP_MAC_PCI // */ | ||
5741 | } | ||
5742 | } | ||
5743 | |||
5744 | } | ||
5745 | |||
5746 | void APSDPeriodicExec(void *SystemSpecific1, | ||
5747 | void *FunctionContext, | ||
5748 | void *SystemSpecific2, void *SystemSpecific3) | ||
5749 | { | ||
5750 | struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; | ||
5751 | |||
5752 | if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) | ||
5753 | return; | ||
5754 | |||
5755 | pAd->CommonCfg.TriggerTimerCount++; | ||
5756 | |||
5757 | /* Driver should not send trigger frame, it should be send by application layer */ | ||
5758 | /* | ||
5759 | if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable | ||
5760 | && (pAd->CommonCfg.bNeedSendTriggerFrame || | ||
5761 | (((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO)))) | ||
5762 | { | ||
5763 | DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n")); | ||
5764 | RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE); | ||
5765 | pAd->CommonCfg.bNeedSendTriggerFrame = FALSE; | ||
5766 | pAd->CommonCfg.TriggerTimerCount = 0; | ||
5767 | pAd->CommonCfg.bInServicePeriod = TRUE; | ||
5768 | }*/ | ||
5769 | } | ||
5770 | |||
5771 | /* | ||
5772 | ======================================================================== | ||
5773 | Routine Description: | ||
5774 | Set/reset MAC registers according to bPiggyBack parameter | ||
5775 | |||
5776 | Arguments: | ||
5777 | pAd - Adapter pointer | ||
5778 | bPiggyBack - Enable / Disable Piggy-Back | ||
5779 | |||
5780 | Return Value: | ||
5781 | None | ||
5782 | |||
5783 | ======================================================================== | ||
5784 | */ | ||
5785 | void RTMPSetPiggyBack(struct rt_rtmp_adapter *pAd, IN BOOLEAN bPiggyBack) | ||
5786 | { | ||
5787 | TX_LINK_CFG_STRUC TxLinkCfg; | ||
5788 | |||
5789 | RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); | ||
5790 | |||
5791 | TxLinkCfg.field.TxCFAckEn = bPiggyBack; | ||
5792 | RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); | ||
5793 | } | ||
5794 | |||
5795 | /* | ||
5796 | ======================================================================== | ||
5797 | Routine Description: | ||
5798 | check if this entry need to switch rate automatically | ||
5799 | |||
5800 | Arguments: | ||
5801 | pAd | ||
5802 | pEntry | ||
5803 | |||
5804 | Return Value: | ||
5805 | TURE | ||
5806 | FALSE | ||
5807 | |||
5808 | ======================================================================== | ||
5809 | */ | ||
5810 | BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(struct rt_rtmp_adapter *pAd, | ||
5811 | struct rt_mac_table_entry *pEntry) | ||
5812 | { | ||
5813 | BOOLEAN result = TRUE; | ||
5814 | |||
5815 | { | ||
5816 | /* only associated STA counts */ | ||
5817 | if (pEntry && (pEntry->ValidAsCLI) | ||
5818 | && (pEntry->Sst == SST_ASSOC)) { | ||
5819 | result = pAd->StaCfg.bAutoTxRateSwitch; | ||
5820 | } else | ||
5821 | result = FALSE; | ||
5822 | } | ||
5823 | |||
5824 | return result; | ||
5825 | } | ||
5826 | |||
5827 | BOOLEAN RTMPAutoRateSwitchCheck(struct rt_rtmp_adapter *pAd) | ||
5828 | { | ||
5829 | { | ||
5830 | if (pAd->StaCfg.bAutoTxRateSwitch) | ||
5831 | return TRUE; | ||
5832 | } | ||
5833 | return FALSE; | ||
5834 | } | ||
5835 | |||
5836 | /* | ||
5837 | ======================================================================== | ||
5838 | Routine Description: | ||
5839 | check if this entry need to fix tx legacy rate | ||
5840 | |||
5841 | Arguments: | ||
5842 | pAd | ||
5843 | pEntry | ||
5844 | |||
5845 | Return Value: | ||
5846 | TURE | ||
5847 | FALSE | ||
5848 | |||
5849 | ======================================================================== | ||
5850 | */ | ||
5851 | u8 RTMPStaFixedTxMode(struct rt_rtmp_adapter *pAd, struct rt_mac_table_entry *pEntry) | ||
5852 | { | ||
5853 | u8 tx_mode = FIXED_TXMODE_HT; | ||
5854 | |||
5855 | { | ||
5856 | tx_mode = | ||
5857 | (u8)pAd->StaCfg.DesiredTransmitSetting.field. | ||
5858 | FixedTxMode; | ||
5859 | } | ||
5860 | |||
5861 | return tx_mode; | ||
5862 | } | ||
5863 | |||
5864 | /* | ||
5865 | ======================================================================== | ||
5866 | Routine Description: | ||
5867 | Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified. | ||
5868 | |||
5869 | Arguments: | ||
5870 | pAd | ||
5871 | pEntry | ||
5872 | |||
5873 | Return Value: | ||
5874 | TURE | ||
5875 | FALSE | ||
5876 | |||
5877 | ======================================================================== | ||
5878 | */ | ||
5879 | void RTMPUpdateLegacyTxSetting(u8 fixed_tx_mode, struct rt_mac_table_entry *pEntry) | ||
5880 | { | ||
5881 | HTTRANSMIT_SETTING TransmitSetting; | ||
5882 | |||
5883 | if (fixed_tx_mode == FIXED_TXMODE_HT) | ||
5884 | return; | ||
5885 | |||
5886 | TransmitSetting.word = 0; | ||
5887 | |||
5888 | TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE; | ||
5889 | TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS; | ||
5890 | |||
5891 | if (fixed_tx_mode == FIXED_TXMODE_CCK) { | ||
5892 | TransmitSetting.field.MODE = MODE_CCK; | ||
5893 | /* CCK mode allow MCS 0~3 */ | ||
5894 | if (TransmitSetting.field.MCS > MCS_3) | ||
5895 | TransmitSetting.field.MCS = MCS_3; | ||
5896 | } else { | ||
5897 | TransmitSetting.field.MODE = MODE_OFDM; | ||
5898 | /* OFDM mode allow MCS 0~7 */ | ||
5899 | if (TransmitSetting.field.MCS > MCS_7) | ||
5900 | TransmitSetting.field.MCS = MCS_7; | ||
5901 | } | ||
5902 | |||
5903 | if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE) { | ||
5904 | pEntry->HTPhyMode.word = TransmitSetting.word; | ||
5905 | DBGPRINT(RT_DEBUG_TRACE, | ||
5906 | ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n", | ||
5907 | pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), | ||
5908 | pEntry->HTPhyMode.field.MCS)); | ||
5909 | } | ||
5910 | } | ||
5911 | |||
5912 | /* | ||
5913 | ========================================================================== | ||
5914 | Description: | ||
5915 | dynamic tune BBP R66 to find a balance between sensibility and | ||
5916 | noise isolation | ||
5917 | |||
5918 | IRQL = DISPATCH_LEVEL | ||
5919 | |||
5920 | ========================================================================== | ||
5921 | */ | ||
5922 | void AsicStaBbpTuning(struct rt_rtmp_adapter *pAd) | ||
5923 | { | ||
5924 | u8 OrigR66Value = 0, R66; /*, R66UpperBound = 0x30, R66LowerBound = 0x30; */ | ||
5925 | char Rssi; | ||
5926 | |||
5927 | /* 2860C did not support Fase CCA, therefore can't tune */ | ||
5928 | if (pAd->MACVersion == 0x28600100) | ||
5929 | return; | ||
5930 | |||
5931 | /* */ | ||
5932 | /* work as a STA */ | ||
5933 | /* */ | ||
5934 | if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) /* no R66 tuning when SCANNING */ | ||
5935 | return; | ||
5936 | |||
5937 | if ((pAd->OpMode == OPMODE_STA) | ||
5938 | && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) | ||
5939 | ) | ||
5940 | && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) | ||
5941 | #ifdef RTMP_MAC_PCI | ||
5942 | && (pAd->bPCIclkOff == FALSE) | ||
5943 | #endif /* RTMP_MAC_PCI // */ | ||
5944 | ) { | ||
5945 | RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value); | ||
5946 | R66 = OrigR66Value; | ||
5947 | |||
5948 | if (pAd->Antenna.field.RxPath > 1) | ||
5949 | Rssi = | ||
5950 | (pAd->StaCfg.RssiSample.AvgRssi0 + | ||
5951 | pAd->StaCfg.RssiSample.AvgRssi1) >> 1; | ||
5952 | else | ||
5953 | Rssi = pAd->StaCfg.RssiSample.AvgRssi0; | ||
5954 | |||
5955 | if (pAd->LatchRfRegs.Channel <= 14) { /*BG band */ | ||
5956 | #ifdef RT30xx | ||
5957 | /* RT3070 is a no LNA solution, it should have different control regarding to AGC gain control */ | ||
5958 | /* Otherwise, it will have some throughput side effect when low RSSI */ | ||
5959 | |||
5960 | if (IS_RT3070(pAd) || IS_RT3090(pAd) || IS_RT3572(pAd) | ||
5961 | || IS_RT3390(pAd)) { | ||
5962 | if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) { | ||
5963 | R66 = | ||
5964 | 0x1C + 2 * GET_LNA_GAIN(pAd) + 0x20; | ||
5965 | if (OrigR66Value != R66) { | ||
5966 | RTMP_BBP_IO_WRITE8_BY_REG_ID | ||
5967 | (pAd, BBP_R66, R66); | ||
5968 | } | ||
5969 | } else { | ||
5970 | R66 = 0x1C + 2 * GET_LNA_GAIN(pAd); | ||
5971 | if (OrigR66Value != R66) { | ||
5972 | RTMP_BBP_IO_WRITE8_BY_REG_ID | ||
5973 | (pAd, BBP_R66, R66); | ||
5974 | } | ||
5975 | } | ||
5976 | } else | ||
5977 | #endif /* RT30xx // */ | ||
5978 | { | ||
5979 | if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) { | ||
5980 | R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10; | ||
5981 | if (OrigR66Value != R66) { | ||
5982 | RTMP_BBP_IO_WRITE8_BY_REG_ID | ||
5983 | (pAd, BBP_R66, R66); | ||
5984 | } | ||
5985 | } else { | ||
5986 | R66 = 0x2E + GET_LNA_GAIN(pAd); | ||
5987 | if (OrigR66Value != R66) { | ||
5988 | RTMP_BBP_IO_WRITE8_BY_REG_ID | ||
5989 | (pAd, BBP_R66, R66); | ||
5990 | } | ||
5991 | } | ||
5992 | } | ||
5993 | } else { /*A band */ | ||
5994 | if (pAd->CommonCfg.BBPCurrentBW == BW_20) { | ||
5995 | if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) { | ||
5996 | R66 = | ||
5997 | 0x32 + (GET_LNA_GAIN(pAd) * 5) / 3 + | ||
5998 | 0x10; | ||
5999 | if (OrigR66Value != R66) { | ||
6000 | RTMP_BBP_IO_WRITE8_BY_REG_ID | ||
6001 | (pAd, BBP_R66, R66); | ||
6002 | } | ||
6003 | } else { | ||
6004 | R66 = | ||
6005 | 0x32 + (GET_LNA_GAIN(pAd) * 5) / 3; | ||
6006 | if (OrigR66Value != R66) { | ||
6007 | RTMP_BBP_IO_WRITE8_BY_REG_ID | ||
6008 | (pAd, BBP_R66, R66); | ||
6009 | } | ||
6010 | } | ||
6011 | } else { | ||
6012 | if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) { | ||
6013 | R66 = | ||
6014 | 0x3A + (GET_LNA_GAIN(pAd) * 5) / 3 + | ||
6015 | 0x10; | ||
6016 | if (OrigR66Value != R66) { | ||
6017 | RTMP_BBP_IO_WRITE8_BY_REG_ID | ||
6018 | (pAd, BBP_R66, R66); | ||
6019 | } | ||
6020 | } else { | ||
6021 | R66 = | ||
6022 | 0x3A + (GET_LNA_GAIN(pAd) * 5) / 3; | ||
6023 | if (OrigR66Value != R66) { | ||
6024 | RTMP_BBP_IO_WRITE8_BY_REG_ID | ||
6025 | (pAd, BBP_R66, R66); | ||
6026 | } | ||
6027 | } | ||
6028 | } | ||
6029 | } | ||
6030 | |||
6031 | } | ||
6032 | } | ||
6033 | |||
6034 | void RTMPSetAGCInitValue(struct rt_rtmp_adapter *pAd, u8 BandWidth) | ||
6035 | { | ||
6036 | u8 R66 = 0x30; | ||
6037 | |||
6038 | if (pAd->LatchRfRegs.Channel <= 14) { /* BG band */ | ||
6039 | #ifdef RT30xx | ||
6040 | /* Gary was verified Amazon AP and find that RT307x has BBP_R66 invalid default value */ | ||
6041 | |||
6042 | if (IS_RT3070(pAd) || IS_RT3090(pAd) || IS_RT3572(pAd) | ||
6043 | || IS_RT3390(pAd)) { | ||
6044 | R66 = 0x1C + 2 * GET_LNA_GAIN(pAd); | ||
6045 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); | ||
6046 | } else | ||
6047 | #endif /* RT30xx // */ | ||
6048 | { | ||
6049 | R66 = 0x2E + GET_LNA_GAIN(pAd); | ||
6050 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); | ||
6051 | } | ||
6052 | } else { /*A band */ | ||
6053 | { | ||
6054 | if (BandWidth == BW_20) { | ||
6055 | R66 = | ||
6056 | (u8)(0x32 + | ||
6057 | (GET_LNA_GAIN(pAd) * 5) / 3); | ||
6058 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); | ||
6059 | } else { | ||
6060 | R66 = | ||
6061 | (u8)(0x3A + | ||
6062 | (GET_LNA_GAIN(pAd) * 5) / 3); | ||
6063 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); | ||
6064 | } | ||
6065 | } | ||
6066 | } | ||
6067 | |||
6068 | } | ||
diff --git a/drivers/staging/rt2860/common/rt_channel.c b/drivers/staging/rt2860/common/rt_channel.c deleted file mode 100644 index 53879898117..00000000000 --- a/drivers/staging/rt2860/common/rt_channel.c +++ /dev/null | |||
@@ -1,1705 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | */ | ||
27 | #include "../rt_config.h" | ||
28 | |||
29 | struct rt_ch_freq_map CH_HZ_ID_MAP[] = { | ||
30 | {1, 2412} | ||
31 | , | ||
32 | {2, 2417} | ||
33 | , | ||
34 | {3, 2422} | ||
35 | , | ||
36 | {4, 2427} | ||
37 | , | ||
38 | {5, 2432} | ||
39 | , | ||
40 | {6, 2437} | ||
41 | , | ||
42 | {7, 2442} | ||
43 | , | ||
44 | {8, 2447} | ||
45 | , | ||
46 | {9, 2452} | ||
47 | , | ||
48 | {10, 2457} | ||
49 | , | ||
50 | {11, 2462} | ||
51 | , | ||
52 | {12, 2467} | ||
53 | , | ||
54 | {13, 2472} | ||
55 | , | ||
56 | {14, 2484} | ||
57 | , | ||
58 | |||
59 | /* UNII */ | ||
60 | {36, 5180} | ||
61 | , | ||
62 | {40, 5200} | ||
63 | , | ||
64 | {44, 5220} | ||
65 | , | ||
66 | {48, 5240} | ||
67 | , | ||
68 | {52, 5260} | ||
69 | , | ||
70 | {56, 5280} | ||
71 | , | ||
72 | {60, 5300} | ||
73 | , | ||
74 | {64, 5320} | ||
75 | , | ||
76 | {149, 5745} | ||
77 | , | ||
78 | {153, 5765} | ||
79 | , | ||
80 | {157, 5785} | ||
81 | , | ||
82 | {161, 5805} | ||
83 | , | ||
84 | {165, 5825} | ||
85 | , | ||
86 | {167, 5835} | ||
87 | , | ||
88 | {169, 5845} | ||
89 | , | ||
90 | {171, 5855} | ||
91 | , | ||
92 | {173, 5865} | ||
93 | , | ||
94 | |||
95 | /* HiperLAN2 */ | ||
96 | {100, 5500} | ||
97 | , | ||
98 | {104, 5520} | ||
99 | , | ||
100 | {108, 5540} | ||
101 | , | ||
102 | {112, 5560} | ||
103 | , | ||
104 | {116, 5580} | ||
105 | , | ||
106 | {120, 5600} | ||
107 | , | ||
108 | {124, 5620} | ||
109 | , | ||
110 | {128, 5640} | ||
111 | , | ||
112 | {132, 5660} | ||
113 | , | ||
114 | {136, 5680} | ||
115 | , | ||
116 | {140, 5700} | ||
117 | , | ||
118 | |||
119 | /* Japan MMAC */ | ||
120 | {34, 5170} | ||
121 | , | ||
122 | {38, 5190} | ||
123 | , | ||
124 | {42, 5210} | ||
125 | , | ||
126 | {46, 5230} | ||
127 | , | ||
128 | |||
129 | /* Japan */ | ||
130 | {184, 4920} | ||
131 | , | ||
132 | {188, 4940} | ||
133 | , | ||
134 | {192, 4960} | ||
135 | , | ||
136 | {196, 4980} | ||
137 | , | ||
138 | |||
139 | {208, 5040} | ||
140 | , /* Japan, means J08 */ | ||
141 | {212, 5060} | ||
142 | , /* Japan, means J12 */ | ||
143 | {216, 5080} | ||
144 | , /* Japan, means J16 */ | ||
145 | }; | ||
146 | |||
147 | int CH_HZ_ID_MAP_NUM = (sizeof(CH_HZ_ID_MAP) / sizeof(struct rt_ch_freq_map)); | ||
148 | |||
149 | struct rt_ch_region ChRegion[] = { | ||
150 | { /* Antigua and Berbuda */ | ||
151 | "AG", | ||
152 | CE, | ||
153 | { | ||
154 | {1, 13, 20, BOTH, FALSE} | ||
155 | , /* 2.4 G, ch 1~13 */ | ||
156 | {36, 4, 23, BOTH, FALSE} | ||
157 | , /* 5G, ch 36~48 */ | ||
158 | {52, 4, 23, BOTH, FALSE} | ||
159 | , /* 5G, ch 52~64 */ | ||
160 | {100, 11, 30, BOTH, FALSE} | ||
161 | , /* 5G, ch 100~140 */ | ||
162 | {0} | ||
163 | , /* end */ | ||
164 | } | ||
165 | } | ||
166 | , | ||
167 | |||
168 | { /* Argentina */ | ||
169 | "AR", | ||
170 | CE, | ||
171 | { | ||
172 | {1, 13, 20, BOTH, FALSE} | ||
173 | , /* 2.4 G, ch 1~13 */ | ||
174 | {52, 4, 24, BOTH, FALSE} | ||
175 | , /* 5G, ch 52~64 */ | ||
176 | {149, 4, 30, BOTH, FALSE} | ||
177 | , /* 5G, ch 149~161 */ | ||
178 | {0} | ||
179 | , /* end */ | ||
180 | } | ||
181 | } | ||
182 | , | ||
183 | |||
184 | { /* Aruba */ | ||
185 | "AW", | ||
186 | CE, | ||
187 | { | ||
188 | {1, 13, 20, BOTH, FALSE} | ||
189 | , /* 2.4 G, ch 1~13 */ | ||
190 | {36, 4, 23, BOTH, FALSE} | ||
191 | , /* 5G, ch 36~48 */ | ||
192 | {52, 4, 23, BOTH, FALSE} | ||
193 | , /* 5G, ch 52~64 */ | ||
194 | {100, 11, 30, BOTH, FALSE} | ||
195 | , /* 5G, ch 100~140 */ | ||
196 | {0} | ||
197 | , /* end */ | ||
198 | } | ||
199 | } | ||
200 | , | ||
201 | |||
202 | { /* Australia */ | ||
203 | "AU", | ||
204 | CE, | ||
205 | { | ||
206 | {1, 13, 20, BOTH, FALSE} | ||
207 | , /* 2.4 G, ch 1~13 */ | ||
208 | {36, 4, 23, BOTH, FALSE} | ||
209 | , /* 5G, ch 36~48 */ | ||
210 | {52, 4, 24, BOTH, FALSE} | ||
211 | , /* 5G, ch 52~64 */ | ||
212 | {149, 5, 30, BOTH, FALSE} | ||
213 | , /* 5G, ch 149~165 */ | ||
214 | {0} | ||
215 | , /* end */ | ||
216 | } | ||
217 | } | ||
218 | , | ||
219 | |||
220 | { /* Austria */ | ||
221 | "AT", | ||
222 | CE, | ||
223 | { | ||
224 | {1, 13, 20, BOTH, FALSE} | ||
225 | , /* 2.4 G, ch 1~13 */ | ||
226 | {36, 4, 23, IDOR, TRUE} | ||
227 | , /* 5G, ch 36~48 */ | ||
228 | {52, 4, 23, IDOR, TRUE} | ||
229 | , /* 5G, ch 52~64 */ | ||
230 | {100, 11, 30, BOTH, TRUE} | ||
231 | , /* 5G, ch 100~140 */ | ||
232 | {0} | ||
233 | , /* end */ | ||
234 | } | ||
235 | } | ||
236 | , | ||
237 | |||
238 | { /* Bahamas */ | ||
239 | "BS", | ||
240 | CE, | ||
241 | { | ||
242 | {1, 13, 20, BOTH, FALSE} | ||
243 | , /* 2.4 G, ch 1~13 */ | ||
244 | {36, 4, 23, BOTH, FALSE} | ||
245 | , /* 5G, ch 36~48 */ | ||
246 | {52, 4, 24, BOTH, FALSE} | ||
247 | , /* 5G, ch 52~64 */ | ||
248 | {149, 5, 30, BOTH, FALSE} | ||
249 | , /* 5G, ch 149~165 */ | ||
250 | {0} | ||
251 | , /* end */ | ||
252 | } | ||
253 | } | ||
254 | , | ||
255 | |||
256 | { /* Barbados */ | ||
257 | "BB", | ||
258 | CE, | ||
259 | { | ||
260 | {1, 13, 20, BOTH, FALSE} | ||
261 | , /* 2.4 G, ch 1~13 */ | ||
262 | {36, 4, 23, BOTH, FALSE} | ||
263 | , /* 5G, ch 36~48 */ | ||
264 | {52, 4, 24, BOTH, FALSE} | ||
265 | , /* 5G, ch 52~64 */ | ||
266 | {100, 11, 30, BOTH, FALSE} | ||
267 | , /* 5G, ch 100~140 */ | ||
268 | {0} | ||
269 | , /* end */ | ||
270 | } | ||
271 | } | ||
272 | , | ||
273 | |||
274 | { /* Bermuda */ | ||
275 | "BM", | ||
276 | CE, | ||
277 | { | ||
278 | {1, 13, 20, BOTH, FALSE} | ||
279 | , /* 2.4 G, ch 1~13 */ | ||
280 | {36, 4, 23, BOTH, FALSE} | ||
281 | , /* 5G, ch 36~48 */ | ||
282 | {52, 4, 24, BOTH, FALSE} | ||
283 | , /* 5G, ch 52~64 */ | ||
284 | {100, 11, 30, BOTH, FALSE} | ||
285 | , /* 5G, ch 100~140 */ | ||
286 | {0} | ||
287 | , /* end */ | ||
288 | } | ||
289 | } | ||
290 | , | ||
291 | |||
292 | { /* Brazil */ | ||
293 | "BR", | ||
294 | CE, | ||
295 | { | ||
296 | {1, 13, 20, BOTH, FALSE} | ||
297 | , /* 2.4 G, ch 1~13 */ | ||
298 | {36, 4, 23, BOTH, FALSE} | ||
299 | , /* 5G, ch 36~48 */ | ||
300 | {52, 4, 24, BOTH, FALSE} | ||
301 | , /* 5G, ch 52~64 */ | ||
302 | {100, 11, 24, BOTH, FALSE} | ||
303 | , /* 5G, ch 100~140 */ | ||
304 | {149, 5, 30, BOTH, FALSE} | ||
305 | , /* 5G, ch 100~140 */ | ||
306 | {0} | ||
307 | , /* end */ | ||
308 | } | ||
309 | } | ||
310 | , | ||
311 | |||
312 | { /* Belgium */ | ||
313 | "BE", | ||
314 | CE, | ||
315 | { | ||
316 | {1, 13, 20, BOTH, FALSE} | ||
317 | , /* 2.4 G, ch 1~13 */ | ||
318 | {36, 4, 18, IDOR, FALSE} | ||
319 | , /* 5G, ch 36~48 */ | ||
320 | {52, 4, 18, IDOR, FALSE} | ||
321 | , /* 5G, ch 52~64 */ | ||
322 | {0} | ||
323 | , /* end */ | ||
324 | } | ||
325 | } | ||
326 | , | ||
327 | |||
328 | { /* Bulgaria */ | ||
329 | "BG", | ||
330 | CE, | ||
331 | { | ||
332 | {1, 13, 20, BOTH, FALSE} | ||
333 | , /* 2.4 G, ch 1~13 */ | ||
334 | {36, 4, 23, IDOR, FALSE} | ||
335 | , /* 5G, ch 36~48 */ | ||
336 | {52, 4, 23, IDOR, TRUE} | ||
337 | , /* 5G, ch 52~64 */ | ||
338 | {100, 11, 30, ODOR, TRUE} | ||
339 | , /* 5G, ch 100~140 */ | ||
340 | {0} | ||
341 | , /* end */ | ||
342 | } | ||
343 | } | ||
344 | , | ||
345 | |||
346 | { /* Canada */ | ||
347 | "CA", | ||
348 | CE, | ||
349 | { | ||
350 | {1, 13, 20, BOTH, FALSE} | ||
351 | , /* 2.4 G, ch 1~13 */ | ||
352 | {36, 4, 23, BOTH, FALSE} | ||
353 | , /* 5G, ch 36~48 */ | ||
354 | {52, 4, 23, BOTH, FALSE} | ||
355 | , /* 5G, ch 52~64 */ | ||
356 | {149, 5, 30, BOTH, FALSE} | ||
357 | , /* 5G, ch 149~165 */ | ||
358 | {0} | ||
359 | , /* end */ | ||
360 | } | ||
361 | } | ||
362 | , | ||
363 | |||
364 | { /* Cayman IsLands */ | ||
365 | "KY", | ||
366 | CE, | ||
367 | { | ||
368 | {1, 13, 20, BOTH, FALSE} | ||
369 | , /* 2.4 G, ch 1~13 */ | ||
370 | {36, 4, 23, BOTH, FALSE} | ||
371 | , /* 5G, ch 36~48 */ | ||
372 | {52, 4, 24, BOTH, FALSE} | ||
373 | , /* 5G, ch 52~64 */ | ||
374 | {100, 11, 30, BOTH, FALSE} | ||
375 | , /* 5G, ch 100~140 */ | ||
376 | {0} | ||
377 | , /* end */ | ||
378 | } | ||
379 | } | ||
380 | , | ||
381 | |||
382 | { /* Chile */ | ||
383 | "CL", | ||
384 | CE, | ||
385 | { | ||
386 | {1, 13, 20, BOTH, FALSE} | ||
387 | , /* 2.4 G, ch 1~13 */ | ||
388 | {36, 4, 20, BOTH, FALSE} | ||
389 | , /* 5G, ch 36~48 */ | ||
390 | {52, 4, 20, BOTH, FALSE} | ||
391 | , /* 5G, ch 52~64 */ | ||
392 | {149, 5, 20, BOTH, FALSE} | ||
393 | , /* 5G, ch 149~165 */ | ||
394 | {0} | ||
395 | , /* end */ | ||
396 | } | ||
397 | } | ||
398 | , | ||
399 | |||
400 | { /* China */ | ||
401 | "CN", | ||
402 | CE, | ||
403 | { | ||
404 | {1, 13, 20, BOTH, FALSE} | ||
405 | , /* 2.4 G, ch 1~13 */ | ||
406 | {149, 4, 27, BOTH, FALSE} | ||
407 | , /* 5G, ch 149~161 */ | ||
408 | {0} | ||
409 | , /* end */ | ||
410 | } | ||
411 | } | ||
412 | , | ||
413 | |||
414 | { /* Colombia */ | ||
415 | "CO", | ||
416 | CE, | ||
417 | { | ||
418 | {1, 13, 20, BOTH, FALSE} | ||
419 | , /* 2.4 G, ch 1~13 */ | ||
420 | {36, 4, 17, BOTH, FALSE} | ||
421 | , /* 5G, ch 36~48 */ | ||
422 | {52, 4, 24, BOTH, FALSE} | ||
423 | , /* 5G, ch 52~64 */ | ||
424 | {100, 11, 30, BOTH, FALSE} | ||
425 | , /* 5G, ch 100~140 */ | ||
426 | {149, 5, 30, BOTH, FALSE} | ||
427 | , /* 5G, ch 149~165 */ | ||
428 | {0} | ||
429 | , /* end */ | ||
430 | } | ||
431 | } | ||
432 | , | ||
433 | |||
434 | { /* Costa Rica */ | ||
435 | "CR", | ||
436 | CE, | ||
437 | { | ||
438 | {1, 13, 20, BOTH, FALSE} | ||
439 | , /* 2.4 G, ch 1~13 */ | ||
440 | {36, 4, 17, BOTH, FALSE} | ||
441 | , /* 5G, ch 36~48 */ | ||
442 | {52, 4, 24, BOTH, FALSE} | ||
443 | , /* 5G, ch 52~64 */ | ||
444 | {149, 4, 30, BOTH, FALSE} | ||
445 | , /* 5G, ch 149~161 */ | ||
446 | {0} | ||
447 | , /* end */ | ||
448 | } | ||
449 | } | ||
450 | , | ||
451 | |||
452 | { /* Cyprus */ | ||
453 | "CY", | ||
454 | CE, | ||
455 | { | ||
456 | {1, 13, 20, BOTH, FALSE} | ||
457 | , /* 2.4 G, ch 1~13 */ | ||
458 | {36, 4, 23, IDOR, FALSE} | ||
459 | , /* 5G, ch 36~48 */ | ||
460 | {52, 4, 24, IDOR, TRUE} | ||
461 | , /* 5G, ch 52~64 */ | ||
462 | {100, 11, 30, BOTH, TRUE} | ||
463 | , /* 5G, ch 100~140 */ | ||
464 | {0} | ||
465 | , /* end */ | ||
466 | } | ||
467 | } | ||
468 | , | ||
469 | |||
470 | { /* Czech_Republic */ | ||
471 | "CZ", | ||
472 | CE, | ||
473 | { | ||
474 | {1, 13, 20, BOTH, FALSE} | ||
475 | , /* 2.4 G, ch 1~13 */ | ||
476 | {36, 4, 23, IDOR, FALSE} | ||
477 | , /* 5G, ch 36~48 */ | ||
478 | {52, 4, 23, IDOR, TRUE} | ||
479 | , /* 5G, ch 52~64 */ | ||
480 | {0} | ||
481 | , /* end */ | ||
482 | } | ||
483 | } | ||
484 | , | ||
485 | |||
486 | { /* Denmark */ | ||
487 | "DK", | ||
488 | CE, | ||
489 | { | ||
490 | {1, 13, 20, BOTH, FALSE} | ||
491 | , /* 2.4 G, ch 1~13 */ | ||
492 | {36, 4, 23, IDOR, FALSE} | ||
493 | , /* 5G, ch 36~48 */ | ||
494 | {52, 4, 23, IDOR, TRUE} | ||
495 | , /* 5G, ch 52~64 */ | ||
496 | {100, 11, 30, BOTH, TRUE} | ||
497 | , /* 5G, ch 100~140 */ | ||
498 | {0} | ||
499 | , /* end */ | ||
500 | } | ||
501 | } | ||
502 | , | ||
503 | |||
504 | { /* Dominican Republic */ | ||
505 | "DO", | ||
506 | CE, | ||
507 | { | ||
508 | {1, 0, 20, BOTH, FALSE} | ||
509 | , /* 2.4 G, ch 0 */ | ||
510 | {149, 4, 20, BOTH, FALSE} | ||
511 | , /* 5G, ch 149~161 */ | ||
512 | {0} | ||
513 | , /* end */ | ||
514 | } | ||
515 | } | ||
516 | , | ||
517 | |||
518 | { /* Equador */ | ||
519 | "EC", | ||
520 | CE, | ||
521 | { | ||
522 | {1, 13, 20, BOTH, FALSE} | ||
523 | , /* 2.4 G, ch 1~13 */ | ||
524 | {100, 11, 27, BOTH, FALSE} | ||
525 | , /* 5G, ch 100~140 */ | ||
526 | {0} | ||
527 | , /* end */ | ||
528 | } | ||
529 | } | ||
530 | , | ||
531 | |||
532 | { /* El Salvador */ | ||
533 | "SV", | ||
534 | CE, | ||
535 | { | ||
536 | {1, 13, 20, BOTH, FALSE} | ||
537 | , /* 2.4 G, ch 1~13 */ | ||
538 | {36, 4, 23, IDOR, FALSE} | ||
539 | , /* 5G, ch 36~48 */ | ||
540 | {52, 4, 30, BOTH, TRUE} | ||
541 | , /* 5G, ch 52~64 */ | ||
542 | {149, 4, 36, BOTH, TRUE} | ||
543 | , /* 5G, ch 149~165 */ | ||
544 | {0} | ||
545 | , /* end */ | ||
546 | } | ||
547 | } | ||
548 | , | ||
549 | |||
550 | { /* Finland */ | ||
551 | "FI", | ||
552 | CE, | ||
553 | { | ||
554 | {1, 13, 20, BOTH, FALSE} | ||
555 | , /* 2.4 G, ch 1~13 */ | ||
556 | {36, 4, 23, IDOR, FALSE} | ||
557 | , /* 5G, ch 36~48 */ | ||
558 | {52, 4, 23, IDOR, TRUE} | ||
559 | , /* 5G, ch 52~64 */ | ||
560 | {100, 11, 30, BOTH, TRUE} | ||
561 | , /* 5G, ch 100~140 */ | ||
562 | {0} | ||
563 | , /* end */ | ||
564 | } | ||
565 | } | ||
566 | , | ||
567 | |||
568 | { /* France */ | ||
569 | "FR", | ||
570 | CE, | ||
571 | { | ||
572 | {1, 13, 20, BOTH, FALSE} | ||
573 | , /* 2.4 G, ch 1~13 */ | ||
574 | {36, 4, 23, IDOR, FALSE} | ||
575 | , /* 5G, ch 36~48 */ | ||
576 | {52, 4, 23, IDOR, TRUE} | ||
577 | , /* 5G, ch 52~64 */ | ||
578 | {0} | ||
579 | , /* end */ | ||
580 | } | ||
581 | } | ||
582 | , | ||
583 | |||
584 | { /* Germany */ | ||
585 | "DE", | ||
586 | CE, | ||
587 | { | ||
588 | {1, 13, 20, BOTH, FALSE} | ||
589 | , /* 2.4 G, ch 1~13 */ | ||
590 | {36, 4, 23, IDOR, FALSE} | ||
591 | , /* 5G, ch 36~48 */ | ||
592 | {52, 4, 23, IDOR, TRUE} | ||
593 | , /* 5G, ch 52~64 */ | ||
594 | {100, 11, 30, BOTH, TRUE} | ||
595 | , /* 5G, ch 100~140 */ | ||
596 | {0} | ||
597 | , /* end */ | ||
598 | } | ||
599 | } | ||
600 | , | ||
601 | |||
602 | { /* Greece */ | ||
603 | "GR", | ||
604 | CE, | ||
605 | { | ||
606 | {1, 13, 20, BOTH, FALSE} | ||
607 | , /* 2.4 G, ch 1~13 */ | ||
608 | {36, 4, 23, IDOR, FALSE} | ||
609 | , /* 5G, ch 36~48 */ | ||
610 | {52, 4, 23, IDOR, TRUE} | ||
611 | , /* 5G, ch 52~64 */ | ||
612 | {100, 11, 30, ODOR, TRUE} | ||
613 | , /* 5G, ch 100~140 */ | ||
614 | {0} | ||
615 | , /* end */ | ||
616 | } | ||
617 | } | ||
618 | , | ||
619 | |||
620 | { /* Guam */ | ||
621 | "GU", | ||
622 | CE, | ||
623 | { | ||
624 | {1, 11, 20, BOTH, FALSE} | ||
625 | , /* 2.4 G, ch 1~11 */ | ||
626 | {36, 4, 17, BOTH, FALSE} | ||
627 | , /* 5G, ch 36~48 */ | ||
628 | {52, 4, 24, BOTH, FALSE} | ||
629 | , /* 5G, ch 52~64 */ | ||
630 | {100, 11, 30, BOTH, FALSE} | ||
631 | , /* 5G, ch 100~140 */ | ||
632 | {149, 5, 30, BOTH, FALSE} | ||
633 | , /* 5G, ch 149~165 */ | ||
634 | {0} | ||
635 | , /* end */ | ||
636 | } | ||
637 | } | ||
638 | , | ||
639 | |||
640 | { /* Guatemala */ | ||
641 | "GT", | ||
642 | CE, | ||
643 | { | ||
644 | {1, 13, 20, BOTH, FALSE} | ||
645 | , /* 2.4 G, ch 1~13 */ | ||
646 | {36, 4, 17, BOTH, FALSE} | ||
647 | , /* 5G, ch 36~48 */ | ||
648 | {52, 4, 24, BOTH, FALSE} | ||
649 | , /* 5G, ch 52~64 */ | ||
650 | {149, 4, 30, BOTH, FALSE} | ||
651 | , /* 5G, ch 149~161 */ | ||
652 | {0} | ||
653 | , /* end */ | ||
654 | } | ||
655 | } | ||
656 | , | ||
657 | |||
658 | { /* Haiti */ | ||
659 | "HT", | ||
660 | CE, | ||
661 | { | ||
662 | {1, 13, 20, BOTH, FALSE} | ||
663 | , /* 2.4 G, ch 1~13 */ | ||
664 | {36, 4, 17, BOTH, FALSE} | ||
665 | , /* 5G, ch 36~48 */ | ||
666 | {52, 4, 24, BOTH, FALSE} | ||
667 | , /* 5G, ch 52~64 */ | ||
668 | {149, 4, 30, BOTH, FALSE} | ||
669 | , /* 5G, ch 149~161 */ | ||
670 | {0} | ||
671 | , /* end */ | ||
672 | } | ||
673 | } | ||
674 | , | ||
675 | |||
676 | { /* Honduras */ | ||
677 | "HN", | ||
678 | CE, | ||
679 | { | ||
680 | {1, 13, 20, BOTH, FALSE} | ||
681 | , /* 2.4 G, ch 1~13 */ | ||
682 | {149, 4, 27, BOTH, FALSE} | ||
683 | , /* 5G, ch 149~161 */ | ||
684 | {0} | ||
685 | , /* end */ | ||
686 | } | ||
687 | } | ||
688 | , | ||
689 | |||
690 | { /* Hong Kong */ | ||
691 | "HK", | ||
692 | CE, | ||
693 | { | ||
694 | {1, 13, 20, BOTH, FALSE} | ||
695 | , /* 2.4 G, ch 1~13 */ | ||
696 | {36, 4, 23, IDOR, FALSE} | ||
697 | , /* 5G, ch 36~48 */ | ||
698 | {52, 4, 23, IDOR, FALSE} | ||
699 | , /* 5G, ch 52~64 */ | ||
700 | {149, 4, 30, BOTH, FALSE} | ||
701 | , /* 5G, ch 149~161 */ | ||
702 | {0} | ||
703 | , /* end */ | ||
704 | } | ||
705 | } | ||
706 | , | ||
707 | |||
708 | { /* Hungary */ | ||
709 | "HU", | ||
710 | CE, | ||
711 | { | ||
712 | {1, 13, 20, BOTH, FALSE} | ||
713 | , /* 2.4 G, ch 1~13 */ | ||
714 | {36, 4, 23, IDOR, FALSE} | ||
715 | , /* 5G, ch 36~48 */ | ||
716 | {52, 4, 23, IDOR, TRUE} | ||
717 | , /* 5G, ch 52~64 */ | ||
718 | {0} | ||
719 | , /* end */ | ||
720 | } | ||
721 | } | ||
722 | , | ||
723 | |||
724 | { /* Iceland */ | ||
725 | "IS", | ||
726 | CE, | ||
727 | { | ||
728 | {1, 13, 20, BOTH, FALSE} | ||
729 | , /* 2.4 G, ch 1~13 */ | ||
730 | {36, 4, 23, IDOR, FALSE} | ||
731 | , /* 5G, ch 36~48 */ | ||
732 | {52, 4, 23, IDOR, TRUE} | ||
733 | , /* 5G, ch 52~64 */ | ||
734 | {100, 11, 30, BOTH, TRUE} | ||
735 | , /* 5G, ch 100~140 */ | ||
736 | {0} | ||
737 | , /* end */ | ||
738 | } | ||
739 | } | ||
740 | , | ||
741 | |||
742 | { /* India */ | ||
743 | "IN", | ||
744 | CE, | ||
745 | { | ||
746 | {1, 13, 20, BOTH, FALSE} | ||
747 | , /* 2.4 G, ch 1~13 */ | ||
748 | {149, 4, 24, IDOR, FALSE} | ||
749 | , /* 5G, ch 149~161 */ | ||
750 | {0} | ||
751 | , /* end */ | ||
752 | } | ||
753 | } | ||
754 | , | ||
755 | |||
756 | { /* Indonesia */ | ||
757 | "ID", | ||
758 | CE, | ||
759 | { | ||
760 | {1, 13, 20, BOTH, FALSE} | ||
761 | , /* 2.4 G, ch 1~13 */ | ||
762 | {149, 4, 27, BOTH, FALSE} | ||
763 | , /* 5G, ch 149~161 */ | ||
764 | {0} | ||
765 | , /* end */ | ||
766 | } | ||
767 | } | ||
768 | , | ||
769 | |||
770 | { /* Ireland */ | ||
771 | "IE", | ||
772 | CE, | ||
773 | { | ||
774 | {1, 13, 20, BOTH, FALSE} | ||
775 | , /* 2.4 G, ch 1~13 */ | ||
776 | {36, 4, 23, IDOR, FALSE} | ||
777 | , /* 5G, ch 36~48 */ | ||
778 | {52, 4, 23, IDOR, TRUE} | ||
779 | , /* 5G, ch 52~64 */ | ||
780 | {100, 11, 30, ODOR, TRUE} | ||
781 | , /* 5G, ch 100~140 */ | ||
782 | {0} | ||
783 | , /* end */ | ||
784 | } | ||
785 | } | ||
786 | , | ||
787 | |||
788 | { /* Israel */ | ||
789 | "IL", | ||
790 | CE, | ||
791 | { | ||
792 | {1, 3, 20, IDOR, FALSE} | ||
793 | , /* 2.4 G, ch 1~3 */ | ||
794 | {4, 6, 20, BOTH, FALSE} | ||
795 | , /* 2.4 G, ch 4~9 */ | ||
796 | {10, 4, 20, IDOR, FALSE} | ||
797 | , /* 2.4 G, ch 10~13 */ | ||
798 | {0} | ||
799 | , /* end */ | ||
800 | } | ||
801 | } | ||
802 | , | ||
803 | |||
804 | { /* Italy */ | ||
805 | "IT", | ||
806 | CE, | ||
807 | { | ||
808 | {1, 13, 20, BOTH, FALSE} | ||
809 | , /* 2.4 G, ch 1~13 */ | ||
810 | {36, 4, 23, IDOR, FALSE} | ||
811 | , /* 5G, ch 36~48 */ | ||
812 | {52, 4, 23, IDOR, TRUE} | ||
813 | , /* 5G, ch 52~64 */ | ||
814 | {100, 11, 30, ODOR, TRUE} | ||
815 | , /* 5G, ch 100~140 */ | ||
816 | {0} | ||
817 | , /* end */ | ||
818 | } | ||
819 | } | ||
820 | , | ||
821 | |||
822 | { /* Japan */ | ||
823 | "JP", | ||
824 | JAP, | ||
825 | { | ||
826 | {1, 14, 20, BOTH, FALSE} | ||
827 | , /* 2.4 G, ch 1~14 */ | ||
828 | {36, 4, 23, IDOR, FALSE} | ||
829 | , /* 5G, ch 36~48 */ | ||
830 | {0} | ||
831 | , /* end */ | ||
832 | } | ||
833 | } | ||
834 | , | ||
835 | |||
836 | { /* Jordan */ | ||
837 | "JO", | ||
838 | CE, | ||
839 | { | ||
840 | {1, 13, 20, IDOR, FALSE} | ||
841 | , /* 2.4 G, ch 1~13 */ | ||
842 | {36, 4, 23, IDOR, FALSE} | ||
843 | , /* 5G, ch 36~48 */ | ||
844 | {149, 4, 23, IDOR, FALSE} | ||
845 | , /* 5G, ch 149~161 */ | ||
846 | {0} | ||
847 | , /* end */ | ||
848 | } | ||
849 | } | ||
850 | , | ||
851 | |||
852 | { /* Latvia */ | ||
853 | "LV", | ||
854 | CE, | ||
855 | { | ||
856 | {1, 13, 20, BOTH, FALSE} | ||
857 | , /* 2.4 G, ch 1~13 */ | ||
858 | {36, 4, 23, IDOR, FALSE} | ||
859 | , /* 5G, ch 36~48 */ | ||
860 | {52, 4, 23, IDOR, TRUE} | ||
861 | , /* 5G, ch 52~64 */ | ||
862 | {100, 11, 30, BOTH, TRUE} | ||
863 | , /* 5G, ch 100~140 */ | ||
864 | {0} | ||
865 | , /* end */ | ||
866 | } | ||
867 | } | ||
868 | , | ||
869 | |||
870 | { /* Liechtenstein */ | ||
871 | "LI", | ||
872 | CE, | ||
873 | { | ||
874 | {1, 13, 20, BOTH, FALSE} | ||
875 | , /* 2.4 G, ch 1~13 */ | ||
876 | {52, 4, 23, IDOR, TRUE} | ||
877 | , /* 5G, ch 52~64 */ | ||
878 | {100, 11, 30, BOTH, TRUE} | ||
879 | , /* 5G, ch 100~140 */ | ||
880 | {0} | ||
881 | , /* end */ | ||
882 | } | ||
883 | } | ||
884 | , | ||
885 | |||
886 | { /* Lithuania */ | ||
887 | "LT", | ||
888 | CE, | ||
889 | { | ||
890 | {1, 13, 20, BOTH, FALSE} | ||
891 | , /* 2.4 G, ch 1~13 */ | ||
892 | {36, 4, 23, IDOR, FALSE} | ||
893 | , /* 5G, ch 36~48 */ | ||
894 | {52, 4, 23, IDOR, TRUE} | ||
895 | , /* 5G, ch 52~64 */ | ||
896 | {100, 11, 30, BOTH, TRUE} | ||
897 | , /* 5G, ch 100~140 */ | ||
898 | {0} | ||
899 | , /* end */ | ||
900 | } | ||
901 | } | ||
902 | , | ||
903 | |||
904 | { /* Luxemburg */ | ||
905 | "LU", | ||
906 | CE, | ||
907 | { | ||
908 | {1, 13, 20, BOTH, FALSE} | ||
909 | , /* 2.4 G, ch 1~13 */ | ||
910 | {36, 4, 23, IDOR, FALSE} | ||
911 | , /* 5G, ch 36~48 */ | ||
912 | {52, 4, 23, IDOR, TRUE} | ||
913 | , /* 5G, ch 52~64 */ | ||
914 | {100, 11, 30, BOTH, TRUE} | ||
915 | , /* 5G, ch 100~140 */ | ||
916 | {0} | ||
917 | , /* end */ | ||
918 | } | ||
919 | } | ||
920 | , | ||
921 | |||
922 | { /* Malaysia */ | ||
923 | "MY", | ||
924 | CE, | ||
925 | { | ||
926 | {36, 4, 23, BOTH, FALSE} | ||
927 | , /* 5G, ch 36~48 */ | ||
928 | {52, 4, 23, BOTH, FALSE} | ||
929 | , /* 5G, ch 52~64 */ | ||
930 | {149, 5, 20, BOTH, FALSE} | ||
931 | , /* 5G, ch 149~165 */ | ||
932 | {0} | ||
933 | , /* end */ | ||
934 | } | ||
935 | } | ||
936 | , | ||
937 | |||
938 | { /* Malta */ | ||
939 | "MT", | ||
940 | CE, | ||
941 | { | ||
942 | {1, 13, 20, BOTH, FALSE} | ||
943 | , /* 2.4 G, ch 1~13 */ | ||
944 | {36, 4, 23, IDOR, FALSE} | ||
945 | , /* 5G, ch 36~48 */ | ||
946 | {52, 4, 23, IDOR, TRUE} | ||
947 | , /* 5G, ch 52~64 */ | ||
948 | {100, 11, 30, BOTH, TRUE} | ||
949 | , /* 5G, ch 100~140 */ | ||
950 | {0} | ||
951 | , /* end */ | ||
952 | } | ||
953 | } | ||
954 | , | ||
955 | |||
956 | { /* Marocco */ | ||
957 | "MA", | ||
958 | CE, | ||
959 | { | ||
960 | {1, 13, 20, BOTH, FALSE} | ||
961 | , /* 2.4 G, ch 1~13 */ | ||
962 | {36, 4, 24, IDOR, FALSE} | ||
963 | , /* 5G, ch 36~48 */ | ||
964 | {0} | ||
965 | , /* end */ | ||
966 | } | ||
967 | } | ||
968 | , | ||
969 | |||
970 | { /* Mexico */ | ||
971 | "MX", | ||
972 | CE, | ||
973 | { | ||
974 | {1, 13, 20, BOTH, FALSE} | ||
975 | , /* 2.4 G, ch 1~13 */ | ||
976 | {36, 4, 23, BOTH, FALSE} | ||
977 | , /* 5G, ch 36~48 */ | ||
978 | {52, 4, 24, BOTH, FALSE} | ||
979 | , /* 5G, ch 52~64 */ | ||
980 | {149, 5, 30, IDOR, FALSE} | ||
981 | , /* 5G, ch 149~165 */ | ||
982 | {0} | ||
983 | , /* end */ | ||
984 | } | ||
985 | } | ||
986 | , | ||
987 | |||
988 | { /* Netherlands */ | ||
989 | "NL", | ||
990 | CE, | ||
991 | { | ||
992 | {1, 13, 20, BOTH, FALSE} | ||
993 | , /* 2.4 G, ch 1~13 */ | ||
994 | {36, 4, 23, IDOR, FALSE} | ||
995 | , /* 5G, ch 36~48 */ | ||
996 | {52, 4, 24, IDOR, TRUE} | ||
997 | , /* 5G, ch 52~64 */ | ||
998 | {100, 11, 30, BOTH, TRUE} | ||
999 | , /* 5G, ch 100~140 */ | ||
1000 | {0} | ||
1001 | , /* end */ | ||
1002 | } | ||
1003 | } | ||
1004 | , | ||
1005 | |||
1006 | { /* New Zealand */ | ||
1007 | "NZ", | ||
1008 | CE, | ||
1009 | { | ||
1010 | {1, 13, 20, BOTH, FALSE} | ||
1011 | , /* 2.4 G, ch 1~13 */ | ||
1012 | {36, 4, 24, BOTH, FALSE} | ||
1013 | , /* 5G, ch 36~48 */ | ||
1014 | {52, 4, 24, BOTH, FALSE} | ||
1015 | , /* 5G, ch 52~64 */ | ||
1016 | {149, 4, 30, BOTH, FALSE} | ||
1017 | , /* 5G, ch 149~161 */ | ||
1018 | {0} | ||
1019 | , /* end */ | ||
1020 | } | ||
1021 | } | ||
1022 | , | ||
1023 | |||
1024 | { /* Norway */ | ||
1025 | "NO", | ||
1026 | CE, | ||
1027 | { | ||
1028 | {1, 13, 20, BOTH, FALSE} | ||
1029 | , /* 2.4 G, ch 1~13 */ | ||
1030 | {36, 4, 24, IDOR, FALSE} | ||
1031 | , /* 5G, ch 36~48 */ | ||
1032 | {52, 4, 24, IDOR, TRUE} | ||
1033 | , /* 5G, ch 52~64 */ | ||
1034 | {100, 11, 30, BOTH, TRUE} | ||
1035 | , /* 5G, ch 149~161 */ | ||
1036 | {0} | ||
1037 | , /* end */ | ||
1038 | } | ||
1039 | } | ||
1040 | , | ||
1041 | |||
1042 | { /* Peru */ | ||
1043 | "PE", | ||
1044 | CE, | ||
1045 | { | ||
1046 | {1, 13, 20, BOTH, FALSE} | ||
1047 | , /* 2.4 G, ch 1~13 */ | ||
1048 | {149, 4, 27, BOTH, FALSE} | ||
1049 | , /* 5G, ch 149~161 */ | ||
1050 | {0} | ||
1051 | , /* end */ | ||
1052 | } | ||
1053 | } | ||
1054 | , | ||
1055 | |||
1056 | { /* Portugal */ | ||
1057 | "PT", | ||
1058 | CE, | ||
1059 | { | ||
1060 | {1, 13, 20, BOTH, FALSE} | ||
1061 | , /* 2.4 G, ch 1~13 */ | ||
1062 | {36, 4, 23, IDOR, FALSE} | ||
1063 | , /* 5G, ch 36~48 */ | ||
1064 | {52, 4, 23, IDOR, TRUE} | ||
1065 | , /* 5G, ch 52~64 */ | ||
1066 | {100, 11, 30, BOTH, TRUE} | ||
1067 | , /* 5G, ch 100~140 */ | ||
1068 | {0} | ||
1069 | , /* end */ | ||
1070 | } | ||
1071 | } | ||
1072 | , | ||
1073 | |||
1074 | { /* Poland */ | ||
1075 | "PL", | ||
1076 | CE, | ||
1077 | { | ||
1078 | {1, 13, 20, BOTH, FALSE} | ||
1079 | , /* 2.4 G, ch 1~13 */ | ||
1080 | {36, 4, 23, IDOR, FALSE} | ||
1081 | , /* 5G, ch 36~48 */ | ||
1082 | {52, 4, 23, IDOR, TRUE} | ||
1083 | , /* 5G, ch 52~64 */ | ||
1084 | {100, 11, 30, BOTH, TRUE} | ||
1085 | , /* 5G, ch 100~140 */ | ||
1086 | {0} | ||
1087 | , /* end */ | ||
1088 | } | ||
1089 | } | ||
1090 | , | ||
1091 | |||
1092 | { /* Romania */ | ||
1093 | "RO", | ||
1094 | CE, | ||
1095 | { | ||
1096 | {1, 13, 20, BOTH, FALSE} | ||
1097 | , /* 2.4 G, ch 1~13 */ | ||
1098 | {36, 4, 23, IDOR, FALSE} | ||
1099 | , /* 5G, ch 36~48 */ | ||
1100 | {52, 4, 23, IDOR, TRUE} | ||
1101 | , /* 5G, ch 52~64 */ | ||
1102 | {100, 11, 30, BOTH, TRUE} | ||
1103 | , /* 5G, ch 100~140 */ | ||
1104 | {0} | ||
1105 | , /* end */ | ||
1106 | } | ||
1107 | } | ||
1108 | , | ||
1109 | |||
1110 | { /* Russia */ | ||
1111 | "RU", | ||
1112 | CE, | ||
1113 | { | ||
1114 | {1, 13, 20, BOTH, FALSE} | ||
1115 | , /* 2.4 G, ch 1~13 */ | ||
1116 | {149, 4, 20, IDOR, FALSE} | ||
1117 | , /* 5G, ch 149~161 */ | ||
1118 | {0} | ||
1119 | , /* end */ | ||
1120 | } | ||
1121 | } | ||
1122 | , | ||
1123 | |||
1124 | { /* Saudi Arabia */ | ||
1125 | "SA", | ||
1126 | CE, | ||
1127 | { | ||
1128 | {1, 13, 20, BOTH, FALSE} | ||
1129 | , /* 2.4 G, ch 1~13 */ | ||
1130 | {36, 4, 23, BOTH, FALSE} | ||
1131 | , /* 5G, ch 36~48 */ | ||
1132 | {52, 4, 23, BOTH, FALSE} | ||
1133 | , /* 5G, ch 52~64 */ | ||
1134 | {149, 4, 23, BOTH, FALSE} | ||
1135 | , /* 5G, ch 149~161 */ | ||
1136 | {0} | ||
1137 | , /* end */ | ||
1138 | } | ||
1139 | } | ||
1140 | , | ||
1141 | |||
1142 | { /* Serbia_and_Montenegro */ | ||
1143 | "CS", | ||
1144 | CE, | ||
1145 | { | ||
1146 | {1, 13, 20, BOTH, FALSE} | ||
1147 | , /* 2.4 G, ch 1~13 */ | ||
1148 | {0} | ||
1149 | , /* end */ | ||
1150 | } | ||
1151 | } | ||
1152 | , | ||
1153 | |||
1154 | { /* Singapore */ | ||
1155 | "SG", | ||
1156 | CE, | ||
1157 | { | ||
1158 | {1, 13, 20, BOTH, FALSE} | ||
1159 | , /* 2.4 G, ch 1~13 */ | ||
1160 | {36, 4, 23, BOTH, FALSE} | ||
1161 | , /* 5G, ch 36~48 */ | ||
1162 | {52, 4, 23, BOTH, FALSE} | ||
1163 | , /* 5G, ch 52~64 */ | ||
1164 | {149, 4, 20, BOTH, FALSE} | ||
1165 | , /* 5G, ch 149~161 */ | ||
1166 | {0} | ||
1167 | , /* end */ | ||
1168 | } | ||
1169 | } | ||
1170 | , | ||
1171 | |||
1172 | { /* Slovakia */ | ||
1173 | "SK", | ||
1174 | CE, | ||
1175 | { | ||
1176 | {1, 13, 20, BOTH, FALSE} | ||
1177 | , /* 2.4 G, ch 1~13 */ | ||
1178 | {36, 4, 23, IDOR, FALSE} | ||
1179 | , /* 5G, ch 36~48 */ | ||
1180 | {52, 4, 23, IDOR, TRUE} | ||
1181 | , /* 5G, ch 52~64 */ | ||
1182 | {100, 11, 30, BOTH, TRUE} | ||
1183 | , /* 5G, ch 100~140 */ | ||
1184 | {0} | ||
1185 | , /* end */ | ||
1186 | } | ||
1187 | } | ||
1188 | , | ||
1189 | |||
1190 | { /* Slovenia */ | ||
1191 | "SI", | ||
1192 | CE, | ||
1193 | { | ||
1194 | {1, 13, 20, BOTH, FALSE} | ||
1195 | , /* 2.4 G, ch 1~13 */ | ||
1196 | {36, 4, 23, IDOR, FALSE} | ||
1197 | , /* 5G, ch 36~48 */ | ||
1198 | {52, 4, 23, IDOR, TRUE} | ||
1199 | , /* 5G, ch 52~64 */ | ||
1200 | {0} | ||
1201 | , /* end */ | ||
1202 | } | ||
1203 | } | ||
1204 | , | ||
1205 | |||
1206 | { /* South Africa */ | ||
1207 | "ZA", | ||
1208 | CE, | ||
1209 | { | ||
1210 | {1, 13, 20, BOTH, FALSE} | ||
1211 | , /* 2.4 G, ch 1~13 */ | ||
1212 | {36, 4, 23, BOTH, FALSE} | ||
1213 | , /* 5G, ch 36~48 */ | ||
1214 | {52, 4, 23, IDOR, FALSE} | ||
1215 | , /* 5G, ch 52~64 */ | ||
1216 | {100, 11, 30, BOTH, TRUE} | ||
1217 | , /* 5G, ch 100~140 */ | ||
1218 | {149, 4, 30, BOTH, FALSE} | ||
1219 | , /* 5G, ch 149~161 */ | ||
1220 | {0} | ||
1221 | , /* end */ | ||
1222 | } | ||
1223 | } | ||
1224 | , | ||
1225 | |||
1226 | { /* South Korea */ | ||
1227 | "KR", | ||
1228 | CE, | ||
1229 | { | ||
1230 | {1, 13, 20, BOTH, FALSE} | ||
1231 | , /* 2.4 G, ch 1~13 */ | ||
1232 | {36, 4, 20, BOTH, FALSE} | ||
1233 | , /* 5G, ch 36~48 */ | ||
1234 | {52, 4, 20, BOTH, FALSE} | ||
1235 | , /* 5G, ch 52~64 */ | ||
1236 | {100, 8, 20, BOTH, FALSE} | ||
1237 | , /* 5G, ch 100~128 */ | ||
1238 | {149, 4, 20, BOTH, FALSE} | ||
1239 | , /* 5G, ch 149~161 */ | ||
1240 | {0} | ||
1241 | , /* end */ | ||
1242 | } | ||
1243 | } | ||
1244 | , | ||
1245 | |||
1246 | { /* Spain */ | ||
1247 | "ES", | ||
1248 | CE, | ||
1249 | { | ||
1250 | {1, 13, 20, BOTH, FALSE} | ||
1251 | , /* 2.4 G, ch 1~13 */ | ||
1252 | {36, 4, 17, IDOR, FALSE} | ||
1253 | , /* 5G, ch 36~48 */ | ||
1254 | {52, 4, 23, IDOR, TRUE} | ||
1255 | , /* 5G, ch 52~64 */ | ||
1256 | {100, 11, 30, BOTH, TRUE} | ||
1257 | , /* 5G, ch 100~140 */ | ||
1258 | {0} | ||
1259 | , /* end */ | ||
1260 | } | ||
1261 | } | ||
1262 | , | ||
1263 | |||
1264 | { /* Sweden */ | ||
1265 | "SE", | ||
1266 | CE, | ||
1267 | { | ||
1268 | {1, 13, 20, BOTH, FALSE} | ||
1269 | , /* 2.4 G, ch 1~13 */ | ||
1270 | {36, 4, 23, IDOR, FALSE} | ||
1271 | , /* 5G, ch 36~48 */ | ||
1272 | {52, 4, 23, IDOR, TRUE} | ||
1273 | , /* 5G, ch 52~64 */ | ||
1274 | {100, 11, 30, BOTH, TRUE} | ||
1275 | , /* 5G, ch 100~140 */ | ||
1276 | {0} | ||
1277 | , /* end */ | ||
1278 | } | ||
1279 | } | ||
1280 | , | ||
1281 | |||
1282 | { /* Switzerland */ | ||
1283 | "CH", | ||
1284 | CE, | ||
1285 | { | ||
1286 | {1, 13, 20, BOTH, FALSE} | ||
1287 | , /* 2.4 G, ch 1~13 */ | ||
1288 | {36, 4, 23, IDOR, TRUE} | ||
1289 | , /* 5G, ch 36~48 */ | ||
1290 | {52, 4, 23, IDOR, TRUE} | ||
1291 | , /* 5G, ch 52~64 */ | ||
1292 | {0} | ||
1293 | , /* end */ | ||
1294 | } | ||
1295 | } | ||
1296 | , | ||
1297 | |||
1298 | { /* Taiwan */ | ||
1299 | "TW", | ||
1300 | CE, | ||
1301 | { | ||
1302 | {1, 11, 30, BOTH, FALSE} | ||
1303 | , /* 2.4 G, ch 1~11 */ | ||
1304 | {52, 4, 23, IDOR, FALSE} | ||
1305 | , /* 5G, ch 52~64 */ | ||
1306 | {0} | ||
1307 | , /* end */ | ||
1308 | } | ||
1309 | } | ||
1310 | , | ||
1311 | |||
1312 | { /* Turkey */ | ||
1313 | "TR", | ||
1314 | CE, | ||
1315 | { | ||
1316 | {1, 13, 20, BOTH, FALSE} | ||
1317 | , /* 2.4 G, ch 1~11 */ | ||
1318 | {36, 4, 23, BOTH, FALSE} | ||
1319 | , /* 5G, ch 36~48 */ | ||
1320 | {52, 4, 23, BOTH, FALSE} | ||
1321 | , /* 5G, ch 52~64 */ | ||
1322 | {0} | ||
1323 | , /* end */ | ||
1324 | } | ||
1325 | } | ||
1326 | , | ||
1327 | |||
1328 | { /* UK */ | ||
1329 | "GB", | ||
1330 | CE, | ||
1331 | { | ||
1332 | {1, 13, 20, BOTH, FALSE} | ||
1333 | , /* 2.4 G, ch 1~11 */ | ||
1334 | {36, 4, 23, IDOR, FALSE} | ||
1335 | , /* 5G, ch 52~64 */ | ||
1336 | {52, 4, 23, IDOR, TRUE} | ||
1337 | , /* 5G, ch 52~64 */ | ||
1338 | {100, 11, 30, BOTH, TRUE} | ||
1339 | , /* 5G, ch 100~140 */ | ||
1340 | {0} | ||
1341 | , /* end */ | ||
1342 | } | ||
1343 | } | ||
1344 | , | ||
1345 | |||
1346 | { /* Ukraine */ | ||
1347 | "UA", | ||
1348 | CE, | ||
1349 | { | ||
1350 | {1, 13, 20, BOTH, FALSE} | ||
1351 | , /* 2.4 G, ch 1~11 */ | ||
1352 | {0} | ||
1353 | , /* end */ | ||
1354 | } | ||
1355 | } | ||
1356 | , | ||
1357 | |||
1358 | { /* United_Arab_Emirates */ | ||
1359 | "AE", | ||
1360 | CE, | ||
1361 | { | ||
1362 | {1, 13, 20, BOTH, FALSE} | ||
1363 | , /* 2.4 G, ch 1~11 */ | ||
1364 | {0} | ||
1365 | , /* end */ | ||
1366 | } | ||
1367 | } | ||
1368 | , | ||
1369 | |||
1370 | { /* United_States */ | ||
1371 | "US", | ||
1372 | CE, | ||
1373 | { | ||
1374 | {1, 11, 30, BOTH, FALSE} | ||
1375 | , /* 2.4 G, ch 1~11 */ | ||
1376 | {36, 4, 17, IDOR, FALSE} | ||
1377 | , /* 5G, ch 52~64 */ | ||
1378 | {52, 4, 24, BOTH, TRUE} | ||
1379 | , /* 5G, ch 52~64 */ | ||
1380 | {100, 11, 30, BOTH, TRUE} | ||
1381 | , /* 5G, ch 100~140 */ | ||
1382 | {149, 5, 30, BOTH, FALSE} | ||
1383 | , /* 5G, ch 149~165 */ | ||
1384 | {0} | ||
1385 | , /* end */ | ||
1386 | } | ||
1387 | } | ||
1388 | , | ||
1389 | |||
1390 | { /* Venezuela */ | ||
1391 | "VE", | ||
1392 | CE, | ||
1393 | { | ||
1394 | {1, 13, 20, BOTH, FALSE} | ||
1395 | , /* 2.4 G, ch 1~11 */ | ||
1396 | {149, 4, 27, BOTH, FALSE} | ||
1397 | , /* 5G, ch 149~161 */ | ||
1398 | {0} | ||
1399 | , /* end */ | ||
1400 | } | ||
1401 | } | ||
1402 | , | ||
1403 | |||
1404 | { /* Default */ | ||
1405 | "", | ||
1406 | CE, | ||
1407 | { | ||
1408 | {1, 11, 20, BOTH, FALSE} | ||
1409 | , /* 2.4 G, ch 1~11 */ | ||
1410 | {36, 4, 20, BOTH, FALSE} | ||
1411 | , /* 5G, ch 52~64 */ | ||
1412 | {52, 4, 20, BOTH, FALSE} | ||
1413 | , /* 5G, ch 52~64 */ | ||
1414 | {100, 11, 20, BOTH, FALSE} | ||
1415 | , /* 5G, ch 100~140 */ | ||
1416 | {149, 5, 20, BOTH, FALSE} | ||
1417 | , /* 5G, ch 149~165 */ | ||
1418 | {0} | ||
1419 | , /* end */ | ||
1420 | } | ||
1421 | } | ||
1422 | , | ||
1423 | }; | ||
1424 | |||
1425 | static struct rt_ch_region *GetChRegion(u8 *CntryCode) | ||
1426 | { | ||
1427 | int loop = 0; | ||
1428 | struct rt_ch_region *pChRegion = NULL; | ||
1429 | |||
1430 | while (strcmp((char *)ChRegion[loop].CountReg, "") != 0) { | ||
1431 | if (strncmp | ||
1432 | ((char *)ChRegion[loop].CountReg, (char *)CntryCode, | ||
1433 | 2) == 0) { | ||
1434 | pChRegion = &ChRegion[loop]; | ||
1435 | break; | ||
1436 | } | ||
1437 | loop++; | ||
1438 | } | ||
1439 | |||
1440 | if (pChRegion == NULL) | ||
1441 | pChRegion = &ChRegion[loop]; | ||
1442 | return pChRegion; | ||
1443 | } | ||
1444 | |||
1445 | static void ChBandCheck(u8 PhyMode, u8 *pChType) | ||
1446 | { | ||
1447 | switch (PhyMode) { | ||
1448 | case PHY_11A: | ||
1449 | case PHY_11AN_MIXED: | ||
1450 | *pChType = BAND_5G; | ||
1451 | break; | ||
1452 | case PHY_11ABG_MIXED: | ||
1453 | case PHY_11AGN_MIXED: | ||
1454 | case PHY_11ABGN_MIXED: | ||
1455 | *pChType = BAND_BOTH; | ||
1456 | break; | ||
1457 | |||
1458 | default: | ||
1459 | *pChType = BAND_24G; | ||
1460 | break; | ||
1461 | } | ||
1462 | } | ||
1463 | |||
1464 | static u8 FillChList(struct rt_rtmp_adapter *pAd, | ||
1465 | struct rt_ch_desp *pChDesp, | ||
1466 | u8 Offset, u8 increment) | ||
1467 | { | ||
1468 | int i, j, l; | ||
1469 | u8 channel; | ||
1470 | |||
1471 | j = Offset; | ||
1472 | for (i = 0; i < pChDesp->NumOfCh; i++) { | ||
1473 | channel = pChDesp->FirstChannel + i * increment; | ||
1474 | for (l = 0; l < MAX_NUM_OF_CHANNELS; l++) { | ||
1475 | if (channel == pAd->TxPower[l].Channel) { | ||
1476 | pAd->ChannelList[j].Power = | ||
1477 | pAd->TxPower[l].Power; | ||
1478 | pAd->ChannelList[j].Power2 = | ||
1479 | pAd->TxPower[l].Power2; | ||
1480 | break; | ||
1481 | } | ||
1482 | } | ||
1483 | if (l == MAX_NUM_OF_CHANNELS) | ||
1484 | continue; | ||
1485 | |||
1486 | pAd->ChannelList[j].Channel = | ||
1487 | pChDesp->FirstChannel + i * increment; | ||
1488 | pAd->ChannelList[j].MaxTxPwr = pChDesp->MaxTxPwr; | ||
1489 | pAd->ChannelList[j].DfsReq = pChDesp->DfsReq; | ||
1490 | j++; | ||
1491 | } | ||
1492 | pAd->ChannelListNum = j; | ||
1493 | |||
1494 | return j; | ||
1495 | } | ||
1496 | |||
1497 | static inline void CreateChList(struct rt_rtmp_adapter *pAd, | ||
1498 | struct rt_ch_region *pChRegion, u8 Geography) | ||
1499 | { | ||
1500 | int i; | ||
1501 | u8 offset = 0; | ||
1502 | struct rt_ch_desp *pChDesp; | ||
1503 | u8 ChType; | ||
1504 | u8 increment; | ||
1505 | |||
1506 | if (pChRegion == NULL) | ||
1507 | return; | ||
1508 | |||
1509 | ChBandCheck(pAd->CommonCfg.PhyMode, &ChType); | ||
1510 | |||
1511 | for (i = 0; i < 10; i++) { | ||
1512 | pChDesp = &pChRegion->ChDesp[i]; | ||
1513 | if (pChDesp->FirstChannel == 0) | ||
1514 | break; | ||
1515 | |||
1516 | if (ChType == BAND_5G) { | ||
1517 | if (pChDesp->FirstChannel <= 14) | ||
1518 | continue; | ||
1519 | } else if (ChType == BAND_24G) { | ||
1520 | if (pChDesp->FirstChannel > 14) | ||
1521 | continue; | ||
1522 | } | ||
1523 | |||
1524 | if ((pChDesp->Geography == BOTH) | ||
1525 | || (pChDesp->Geography == Geography)) { | ||
1526 | if (pChDesp->FirstChannel > 14) | ||
1527 | increment = 4; | ||
1528 | else | ||
1529 | increment = 1; | ||
1530 | offset = FillChList(pAd, pChDesp, offset, increment); | ||
1531 | } | ||
1532 | } | ||
1533 | } | ||
1534 | |||
1535 | void BuildChannelListEx(struct rt_rtmp_adapter *pAd) | ||
1536 | { | ||
1537 | struct rt_ch_region *pChReg; | ||
1538 | |||
1539 | pChReg = GetChRegion(pAd->CommonCfg.CountryCode); | ||
1540 | CreateChList(pAd, pChReg, pAd->CommonCfg.Geography); | ||
1541 | } | ||
1542 | |||
1543 | void BuildBeaconChList(struct rt_rtmp_adapter *pAd, | ||
1544 | u8 *pBuf, unsigned long *pBufLen) | ||
1545 | { | ||
1546 | int i; | ||
1547 | unsigned long TmpLen; | ||
1548 | struct rt_ch_region *pChRegion; | ||
1549 | struct rt_ch_desp *pChDesp; | ||
1550 | u8 ChType; | ||
1551 | |||
1552 | pChRegion = GetChRegion(pAd->CommonCfg.CountryCode); | ||
1553 | |||
1554 | if (pChRegion == NULL) | ||
1555 | return; | ||
1556 | |||
1557 | ChBandCheck(pAd->CommonCfg.PhyMode, &ChType); | ||
1558 | *pBufLen = 0; | ||
1559 | |||
1560 | for (i = 0; i < 10; i++) { | ||
1561 | pChDesp = &pChRegion->ChDesp[i]; | ||
1562 | if (pChDesp->FirstChannel == 0) | ||
1563 | break; | ||
1564 | |||
1565 | if (ChType == BAND_5G) { | ||
1566 | if (pChDesp->FirstChannel <= 14) | ||
1567 | continue; | ||
1568 | } else if (ChType == BAND_24G) { | ||
1569 | if (pChDesp->FirstChannel > 14) | ||
1570 | continue; | ||
1571 | } | ||
1572 | |||
1573 | if ((pChDesp->Geography == BOTH) | ||
1574 | || (pChDesp->Geography == pAd->CommonCfg.Geography)) { | ||
1575 | MakeOutgoingFrame(pBuf + *pBufLen, &TmpLen, | ||
1576 | 1, &pChDesp->FirstChannel, | ||
1577 | 1, &pChDesp->NumOfCh, | ||
1578 | 1, &pChDesp->MaxTxPwr, END_OF_ARGS); | ||
1579 | *pBufLen += TmpLen; | ||
1580 | } | ||
1581 | } | ||
1582 | } | ||
1583 | |||
1584 | static BOOLEAN IsValidChannel(struct rt_rtmp_adapter *pAd, u8 channel) | ||
1585 | { | ||
1586 | int i; | ||
1587 | |||
1588 | for (i = 0; i < pAd->ChannelListNum; i++) { | ||
1589 | if (pAd->ChannelList[i].Channel == channel) | ||
1590 | break; | ||
1591 | } | ||
1592 | |||
1593 | if (i == pAd->ChannelListNum) | ||
1594 | return FALSE; | ||
1595 | else | ||
1596 | return TRUE; | ||
1597 | } | ||
1598 | |||
1599 | static u8 GetExtCh(u8 Channel, u8 Direction) | ||
1600 | { | ||
1601 | char ExtCh; | ||
1602 | |||
1603 | if (Direction == EXTCHA_ABOVE) | ||
1604 | ExtCh = Channel + 4; | ||
1605 | else | ||
1606 | ExtCh = (Channel - 4) > 0 ? (Channel - 4) : 0; | ||
1607 | |||
1608 | return ExtCh; | ||
1609 | } | ||
1610 | |||
1611 | void N_ChannelCheck(struct rt_rtmp_adapter *pAd) | ||
1612 | { | ||
1613 | /*u8 ChannelNum = pAd->ChannelListNum; */ | ||
1614 | u8 Channel = pAd->CommonCfg.Channel; | ||
1615 | |||
1616 | if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) | ||
1617 | && (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)) { | ||
1618 | if (Channel > 14) { | ||
1619 | if ((Channel == 36) || (Channel == 44) | ||
1620 | || (Channel == 52) || (Channel == 60) | ||
1621 | || (Channel == 100) || (Channel == 108) | ||
1622 | || (Channel == 116) || (Channel == 124) | ||
1623 | || (Channel == 132) || (Channel == 149) | ||
1624 | || (Channel == 157)) { | ||
1625 | pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = | ||
1626 | EXTCHA_ABOVE; | ||
1627 | } else if ((Channel == 40) || (Channel == 48) | ||
1628 | || (Channel == 56) || (Channel == 64) | ||
1629 | || (Channel == 104) || (Channel == 112) | ||
1630 | || (Channel == 120) || (Channel == 128) | ||
1631 | || (Channel == 136) || (Channel == 153) | ||
1632 | || (Channel == 161)) { | ||
1633 | pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = | ||
1634 | EXTCHA_BELOW; | ||
1635 | } else { | ||
1636 | pAd->CommonCfg.RegTransmitSetting.field.BW = | ||
1637 | BW_20; | ||
1638 | } | ||
1639 | } else { | ||
1640 | do { | ||
1641 | u8 ExtCh; | ||
1642 | u8 Dir = | ||
1643 | pAd->CommonCfg.RegTransmitSetting.field. | ||
1644 | EXTCHA; | ||
1645 | ExtCh = GetExtCh(Channel, Dir); | ||
1646 | if (IsValidChannel(pAd, ExtCh)) | ||
1647 | break; | ||
1648 | |||
1649 | Dir = | ||
1650 | (Dir == | ||
1651 | EXTCHA_ABOVE) ? EXTCHA_BELOW : | ||
1652 | EXTCHA_ABOVE; | ||
1653 | ExtCh = GetExtCh(Channel, Dir); | ||
1654 | if (IsValidChannel(pAd, ExtCh)) { | ||
1655 | pAd->CommonCfg.RegTransmitSetting.field. | ||
1656 | EXTCHA = Dir; | ||
1657 | break; | ||
1658 | } | ||
1659 | pAd->CommonCfg.RegTransmitSetting.field.BW = | ||
1660 | BW_20; | ||
1661 | } while (FALSE); | ||
1662 | |||
1663 | if (Channel == 14) { | ||
1664 | pAd->CommonCfg.RegTransmitSetting.field.BW = | ||
1665 | BW_20; | ||
1666 | /*pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_NONE; // We didn't set the ExtCh as NONE due to it'll set in RTMPSetHT() */ | ||
1667 | } | ||
1668 | } | ||
1669 | } | ||
1670 | |||
1671 | } | ||
1672 | |||
1673 | void N_SetCenCh(struct rt_rtmp_adapter *pAd) | ||
1674 | { | ||
1675 | if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) { | ||
1676 | if (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == | ||
1677 | EXTCHA_ABOVE) { | ||
1678 | pAd->CommonCfg.CentralChannel = | ||
1679 | pAd->CommonCfg.Channel + 2; | ||
1680 | } else { | ||
1681 | if (pAd->CommonCfg.Channel == 14) | ||
1682 | pAd->CommonCfg.CentralChannel = | ||
1683 | pAd->CommonCfg.Channel - 1; | ||
1684 | else | ||
1685 | pAd->CommonCfg.CentralChannel = | ||
1686 | pAd->CommonCfg.Channel - 2; | ||
1687 | } | ||
1688 | } else { | ||
1689 | pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; | ||
1690 | } | ||
1691 | } | ||
1692 | |||
1693 | u8 GetCuntryMaxTxPwr(struct rt_rtmp_adapter *pAd, u8 channel) | ||
1694 | { | ||
1695 | int i; | ||
1696 | for (i = 0; i < pAd->ChannelListNum; i++) { | ||
1697 | if (pAd->ChannelList[i].Channel == channel) | ||
1698 | break; | ||
1699 | } | ||
1700 | |||
1701 | if (i == pAd->ChannelListNum) | ||
1702 | return 0xff; | ||
1703 | else | ||
1704 | return pAd->ChannelList[i].MaxTxPwr; | ||
1705 | } | ||
diff --git a/drivers/staging/rt2860/common/rt_rf.c b/drivers/staging/rt2860/common/rt_rf.c deleted file mode 100644 index 2895447ffc4..00000000000 --- a/drivers/staging/rt2860/common/rt_rf.c +++ /dev/null | |||
@@ -1,187 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | |||
27 | Module Name: | ||
28 | rt_rf.c | ||
29 | |||
30 | Abstract: | ||
31 | Ralink Wireless driver RF related functions | ||
32 | |||
33 | Revision History: | ||
34 | Who When What | ||
35 | -------- ---------- ---------------------------------------------- | ||
36 | */ | ||
37 | |||
38 | #include "../rt_config.h" | ||
39 | |||
40 | #ifdef RTMP_RF_RW_SUPPORT | ||
41 | /* | ||
42 | ======================================================================== | ||
43 | |||
44 | Routine Description: Write RT30xx RF register through MAC | ||
45 | |||
46 | Arguments: | ||
47 | |||
48 | Return Value: | ||
49 | |||
50 | IRQL = | ||
51 | |||
52 | Note: | ||
53 | |||
54 | ======================================================================== | ||
55 | */ | ||
56 | int RT30xxWriteRFRegister(struct rt_rtmp_adapter *pAd, | ||
57 | u8 regID, u8 value) | ||
58 | { | ||
59 | RF_CSR_CFG_STRUC rfcsr; | ||
60 | u32 i = 0; | ||
61 | |||
62 | do { | ||
63 | RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word); | ||
64 | |||
65 | if (!rfcsr.field.RF_CSR_KICK) | ||
66 | break; | ||
67 | i++; | ||
68 | } | ||
69 | while ((i < RETRY_LIMIT) | ||
70 | && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))); | ||
71 | |||
72 | if ((i == RETRY_LIMIT) | ||
73 | || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) { | ||
74 | DBGPRINT_RAW(RT_DEBUG_ERROR, | ||
75 | ("Retry count exhausted or device removed!\n")); | ||
76 | return STATUS_UNSUCCESSFUL; | ||
77 | } | ||
78 | |||
79 | rfcsr.field.RF_CSR_WR = 1; | ||
80 | rfcsr.field.RF_CSR_KICK = 1; | ||
81 | rfcsr.field.TESTCSR_RFACC_REGNUM = regID; | ||
82 | rfcsr.field.RF_CSR_DATA = value; | ||
83 | |||
84 | RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word); | ||
85 | |||
86 | return NDIS_STATUS_SUCCESS; | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | ======================================================================== | ||
91 | |||
92 | Routine Description: Read RT30xx RF register through MAC | ||
93 | |||
94 | Arguments: | ||
95 | |||
96 | Return Value: | ||
97 | |||
98 | IRQL = | ||
99 | |||
100 | Note: | ||
101 | |||
102 | ======================================================================== | ||
103 | */ | ||
104 | int RT30xxReadRFRegister(struct rt_rtmp_adapter *pAd, | ||
105 | u8 regID, u8 *pValue) | ||
106 | { | ||
107 | RF_CSR_CFG_STRUC rfcsr; | ||
108 | u32 i = 0, k = 0; | ||
109 | |||
110 | for (i = 0; i < MAX_BUSY_COUNT; i++) { | ||
111 | RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word); | ||
112 | |||
113 | if (rfcsr.field.RF_CSR_KICK == BUSY) { | ||
114 | continue; | ||
115 | } | ||
116 | rfcsr.word = 0; | ||
117 | rfcsr.field.RF_CSR_WR = 0; | ||
118 | rfcsr.field.RF_CSR_KICK = 1; | ||
119 | rfcsr.field.TESTCSR_RFACC_REGNUM = regID; | ||
120 | RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word); | ||
121 | for (k = 0; k < MAX_BUSY_COUNT; k++) { | ||
122 | RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word); | ||
123 | |||
124 | if (rfcsr.field.RF_CSR_KICK == IDLE) | ||
125 | break; | ||
126 | } | ||
127 | if ((rfcsr.field.RF_CSR_KICK == IDLE) && | ||
128 | (rfcsr.field.TESTCSR_RFACC_REGNUM == regID)) { | ||
129 | *pValue = (u8)rfcsr.field.RF_CSR_DATA; | ||
130 | break; | ||
131 | } | ||
132 | } | ||
133 | if (rfcsr.field.RF_CSR_KICK == BUSY) { | ||
134 | DBGPRINT_ERR("RF read R%d=0x%x fail, i[%d], k[%d]\n", regID, rfcsr.word, i, k); | ||
135 | return STATUS_UNSUCCESSFUL; | ||
136 | } | ||
137 | |||
138 | return STATUS_SUCCESS; | ||
139 | } | ||
140 | |||
141 | void NICInitRFRegisters(struct rt_rtmp_adapter *pAd) | ||
142 | { | ||
143 | if (pAd->chipOps.AsicRfInit) | ||
144 | pAd->chipOps.AsicRfInit(pAd); | ||
145 | } | ||
146 | |||
147 | void RtmpChipOpsRFHook(struct rt_rtmp_adapter *pAd) | ||
148 | { | ||
149 | struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps; | ||
150 | |||
151 | pChipOps->pRFRegTable = NULL; | ||
152 | pChipOps->AsicRfInit = NULL; | ||
153 | pChipOps->AsicRfTurnOn = NULL; | ||
154 | pChipOps->AsicRfTurnOff = NULL; | ||
155 | pChipOps->AsicReverseRfFromSleepMode = NULL; | ||
156 | pChipOps->AsicHaltAction = NULL; | ||
157 | /* We depends on RfICType and MACVersion to assign the corresponding operation callbacks. */ | ||
158 | |||
159 | #ifdef RT30xx | ||
160 | if (IS_RT30xx(pAd)) { | ||
161 | pChipOps->pRFRegTable = RT30xx_RFRegTable; | ||
162 | pChipOps->AsicHaltAction = RT30xxHaltAction; | ||
163 | #ifdef RT3070 | ||
164 | if ((IS_RT3070(pAd) || IS_RT3071(pAd)) | ||
165 | && (pAd->infType == RTMP_DEV_INF_USB)) { | ||
166 | pChipOps->AsicRfInit = NICInitRT3070RFRegisters; | ||
167 | if (IS_RT3071(pAd)) { | ||
168 | pChipOps->AsicRfTurnOff = | ||
169 | RT30xxLoadRFSleepModeSetup; | ||
170 | pChipOps->AsicReverseRfFromSleepMode = | ||
171 | RT30xxReverseRFSleepModeSetup; | ||
172 | } | ||
173 | } | ||
174 | #endif /* RT3070 // */ | ||
175 | #ifdef RT3090 | ||
176 | if (IS_RT3090(pAd) && (pAd->infType == RTMP_DEV_INF_PCI)) { | ||
177 | pChipOps->AsicRfTurnOff = RT30xxLoadRFSleepModeSetup; | ||
178 | pChipOps->AsicRfInit = NICInitRT3090RFRegisters; | ||
179 | pChipOps->AsicReverseRfFromSleepMode = | ||
180 | RT30xxReverseRFSleepModeSetup; | ||
181 | } | ||
182 | #endif /* RT3090 // */ | ||
183 | } | ||
184 | #endif /* RT30xx // */ | ||
185 | } | ||
186 | |||
187 | #endif /* RTMP_RF_RW_SUPPORT // */ | ||
diff --git a/drivers/staging/rt2860/common/rtmp_init.c b/drivers/staging/rt2860/common/rtmp_init.c deleted file mode 100644 index 5fa193eac0d..00000000000 --- a/drivers/staging/rt2860/common/rtmp_init.c +++ /dev/null | |||
@@ -1,3536 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | |||
27 | Module Name: | ||
28 | rtmp_init.c | ||
29 | |||
30 | Abstract: | ||
31 | Miniport generic portion header file | ||
32 | |||
33 | Revision History: | ||
34 | Who When What | ||
35 | -------- ---------- ---------------------------------------------- | ||
36 | */ | ||
37 | #include "../rt_config.h" | ||
38 | |||
39 | u8 BIT8[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; | ||
40 | char *CipherName[] = | ||
41 | { "none", "wep64", "wep128", "TKIP", "AES", "CKIP64", "CKIP128" }; | ||
42 | |||
43 | /* */ | ||
44 | /* BBP register initialization set */ | ||
45 | /* */ | ||
46 | struct rt_reg_pair BBPRegTable[] = { | ||
47 | {BBP_R65, 0x2C}, /* fix rssi issue */ | ||
48 | {BBP_R66, 0x38}, /* Also set this default value to pAd->BbpTuning.R66CurrentValue at initial */ | ||
49 | {BBP_R69, 0x12}, | ||
50 | {BBP_R70, 0xa}, /* BBP_R70 will change to 0x8 in ApStartUp and LinkUp for rt2860C, otherwise value is 0xa */ | ||
51 | {BBP_R73, 0x10}, | ||
52 | {BBP_R81, 0x37}, | ||
53 | {BBP_R82, 0x62}, | ||
54 | {BBP_R83, 0x6A}, | ||
55 | {BBP_R84, 0x99}, /* 0x19 is for rt2860E and after. This is for extension channel overlapping IOT. 0x99 is for rt2860D and before */ | ||
56 | {BBP_R86, 0x00}, /* middle range issue, Rory @2008-01-28 */ | ||
57 | {BBP_R91, 0x04}, /* middle range issue, Rory @2008-01-28 */ | ||
58 | {BBP_R92, 0x00}, /* middle range issue, Rory @2008-01-28 */ | ||
59 | {BBP_R103, 0x00}, /* near range high-power issue, requested from Gary @2008-0528 */ | ||
60 | {BBP_R105, 0x05}, /* 0x05 is for rt2860E to turn on FEQ control. It is safe for rt2860D and before, because Bit 7:2 are reserved in rt2860D and before. */ | ||
61 | {BBP_R106, 0x35}, /* for ShortGI throughput */ | ||
62 | }; | ||
63 | |||
64 | #define NUM_BBP_REG_PARMS (sizeof(BBPRegTable) / sizeof(struct rt_reg_pair)) | ||
65 | |||
66 | /* */ | ||
67 | /* ASIC register initialization sets */ | ||
68 | /* */ | ||
69 | |||
70 | struct rt_rtmp_reg_pair MACRegTable[] = { | ||
71 | #if defined(HW_BEACON_OFFSET) && (HW_BEACON_OFFSET == 0x200) | ||
72 | {BCN_OFFSET0, 0xf8f0e8e0}, /* 0x3800(e0), 0x3A00(e8), 0x3C00(f0), 0x3E00(f8), 512B for each beacon */ | ||
73 | {BCN_OFFSET1, 0x6f77d0c8}, /* 0x3200(c8), 0x3400(d0), 0x1DC0(77), 0x1BC0(6f), 512B for each beacon */ | ||
74 | #elif defined(HW_BEACON_OFFSET) && (HW_BEACON_OFFSET == 0x100) | ||
75 | {BCN_OFFSET0, 0xece8e4e0}, /* 0x3800, 0x3A00, 0x3C00, 0x3E00, 512B for each beacon */ | ||
76 | {BCN_OFFSET1, 0xfcf8f4f0}, /* 0x3800, 0x3A00, 0x3C00, 0x3E00, 512B for each beacon */ | ||
77 | #else | ||
78 | #error You must re-calculate new value for BCN_OFFSET0 & BCN_OFFSET1 in MACRegTable[]! | ||
79 | #endif /* HW_BEACON_OFFSET // */ | ||
80 | |||
81 | {LEGACY_BASIC_RATE, 0x0000013f}, /* Basic rate set bitmap */ | ||
82 | {HT_BASIC_RATE, 0x00008003}, /* Basic HT rate set , 20M, MCS=3, MM. Format is the same as in TXWI. */ | ||
83 | {MAC_SYS_CTRL, 0x00}, /* 0x1004, , default Disable RX */ | ||
84 | {RX_FILTR_CFG, 0x17f97}, /*0x1400 , RX filter control, */ | ||
85 | {BKOFF_SLOT_CFG, 0x209}, /* default set short slot time, CC_DELAY_TIME should be 2 */ | ||
86 | /*{TX_SW_CFG0, 0x40a06}, // Gary,2006-08-23 */ | ||
87 | {TX_SW_CFG0, 0x0}, /* Gary,2008-05-21 for CWC test */ | ||
88 | {TX_SW_CFG1, 0x80606}, /* Gary,2006-08-23 */ | ||
89 | {TX_LINK_CFG, 0x1020}, /* Gary,2006-08-23 */ | ||
90 | /*{TX_TIMEOUT_CFG, 0x00182090}, // CCK has some problem. So increase timieout value. 2006-10-09// MArvek RT */ | ||
91 | {TX_TIMEOUT_CFG, 0x000a2090}, /* CCK has some problem. So increase timieout value. 2006-10-09// MArvek RT , Modify for 2860E ,2007-08-01 */ | ||
92 | {MAX_LEN_CFG, MAX_AGGREGATION_SIZE | 0x00001000}, /* 0x3018, MAX frame length. Max PSDU = 16kbytes. */ | ||
93 | {LED_CFG, 0x7f031e46}, /* Gary, 2006-08-23 */ | ||
94 | |||
95 | {PBF_MAX_PCNT, 0x1F3FBF9F}, /*0x1F3f7f9f}, //Jan, 2006/04/20 */ | ||
96 | |||
97 | {TX_RTY_CFG, 0x47d01f0f}, /* Jan, 2006/11/16, Set TxWI->ACK =0 in Probe Rsp Modify for 2860E ,2007-08-03 */ | ||
98 | |||
99 | {AUTO_RSP_CFG, 0x00000013}, /* Initial Auto_Responder, because QA will turn off Auto-Responder */ | ||
100 | {CCK_PROT_CFG, 0x05740003 /*0x01740003 */ }, /* Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled. */ | ||
101 | {OFDM_PROT_CFG, 0x05740003 /*0x01740003 */ }, /* Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled. */ | ||
102 | #ifdef RTMP_MAC_USB | ||
103 | {PBF_CFG, 0xf40006}, /* Only enable Queue 2 */ | ||
104 | {MM40_PROT_CFG, 0x3F44084}, /* Initial Auto_Responder, because QA will turn off Auto-Responder */ | ||
105 | {WPDMA_GLO_CFG, 0x00000030}, | ||
106 | #endif /* RTMP_MAC_USB // */ | ||
107 | {GF20_PROT_CFG, 0x01744004}, /* set 19:18 --> Short NAV for MIMO PS */ | ||
108 | {GF40_PROT_CFG, 0x03F44084}, | ||
109 | {MM20_PROT_CFG, 0x01744004}, | ||
110 | #ifdef RTMP_MAC_PCI | ||
111 | {MM40_PROT_CFG, 0x03F54084}, | ||
112 | #endif /* RTMP_MAC_PCI // */ | ||
113 | {TXOP_CTRL_CFG, 0x0000583f, /*0x0000243f *//*0x000024bf */ }, /*Extension channel backoff. */ | ||
114 | {TX_RTS_CFG, 0x00092b20}, | ||
115 | {EXP_ACK_TIME, 0x002400ca}, /* default value */ | ||
116 | |||
117 | {TXOP_HLDR_ET, 0x00000002}, | ||
118 | |||
119 | /* Jerry comments 2008/01/16: we use SIFS = 10us in CCK defaultly, but it seems that 10us | ||
120 | is too small for INTEL 2200bg card, so in MBSS mode, the delta time between beacon0 | ||
121 | and beacon1 is SIFS (10us), so if INTEL 2200bg card connects to BSS0, the ping | ||
122 | will always lost. So we change the SIFS of CCK from 10us to 16us. */ | ||
123 | {XIFS_TIME_CFG, 0x33a41010}, | ||
124 | {PWR_PIN_CFG, 0x00000003}, /* patch for 2880-E */ | ||
125 | }; | ||
126 | |||
127 | struct rt_rtmp_reg_pair STAMACRegTable[] = { | ||
128 | {WMM_AIFSN_CFG, 0x00002273}, | ||
129 | {WMM_CWMIN_CFG, 0x00002344}, | ||
130 | {WMM_CWMAX_CFG, 0x000034aa}, | ||
131 | }; | ||
132 | |||
133 | #define NUM_MAC_REG_PARMS (sizeof(MACRegTable) / sizeof(struct rt_rtmp_reg_pair)) | ||
134 | #define NUM_STA_MAC_REG_PARMS (sizeof(STAMACRegTable) / sizeof(struct rt_rtmp_reg_pair)) | ||
135 | |||
136 | /* | ||
137 | ======================================================================== | ||
138 | |||
139 | Routine Description: | ||
140 | Allocate struct rt_rtmp_adapter data block and do some initialization | ||
141 | |||
142 | Arguments: | ||
143 | Adapter Pointer to our adapter | ||
144 | |||
145 | Return Value: | ||
146 | NDIS_STATUS_SUCCESS | ||
147 | NDIS_STATUS_FAILURE | ||
148 | |||
149 | IRQL = PASSIVE_LEVEL | ||
150 | |||
151 | Note: | ||
152 | |||
153 | ======================================================================== | ||
154 | */ | ||
155 | int RTMPAllocAdapterBlock(void *handle, | ||
156 | struct rt_rtmp_adapter * * ppAdapter) | ||
157 | { | ||
158 | struct rt_rtmp_adapter *pAd; | ||
159 | int Status; | ||
160 | int index; | ||
161 | u8 *pBeaconBuf = NULL; | ||
162 | |||
163 | DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocAdapterBlock\n")); | ||
164 | |||
165 | *ppAdapter = NULL; | ||
166 | |||
167 | do { | ||
168 | /* Allocate struct rt_rtmp_adapter memory block */ | ||
169 | pBeaconBuf = kmalloc(MAX_BEACON_SIZE, MEM_ALLOC_FLAG); | ||
170 | if (pBeaconBuf == NULL) { | ||
171 | Status = NDIS_STATUS_FAILURE; | ||
172 | DBGPRINT_ERR("Failed to allocate memory - BeaconBuf!\n"); | ||
173 | break; | ||
174 | } | ||
175 | NdisZeroMemory(pBeaconBuf, MAX_BEACON_SIZE); | ||
176 | |||
177 | Status = AdapterBlockAllocateMemory(handle, (void **) & pAd); | ||
178 | if (Status != NDIS_STATUS_SUCCESS) { | ||
179 | DBGPRINT_ERR("Failed to allocate memory - ADAPTER\n"); | ||
180 | break; | ||
181 | } | ||
182 | pAd->BeaconBuf = pBeaconBuf; | ||
183 | DBGPRINT(RT_DEBUG_OFF, | ||
184 | ("=== pAd = %p, size = %d ===\n", pAd, | ||
185 | (u32)sizeof(struct rt_rtmp_adapter))); | ||
186 | |||
187 | /* Init spin locks */ | ||
188 | NdisAllocateSpinLock(&pAd->MgmtRingLock); | ||
189 | #ifdef RTMP_MAC_PCI | ||
190 | NdisAllocateSpinLock(&pAd->RxRingLock); | ||
191 | #ifdef RT3090 | ||
192 | NdisAllocateSpinLock(&pAd->McuCmdLock); | ||
193 | #endif /* RT3090 // */ | ||
194 | #endif /* RTMP_MAC_PCI // */ | ||
195 | |||
196 | for (index = 0; index < NUM_OF_TX_RING; index++) { | ||
197 | NdisAllocateSpinLock(&pAd->TxSwQueueLock[index]); | ||
198 | NdisAllocateSpinLock(&pAd->DeQueueLock[index]); | ||
199 | pAd->DeQueueRunning[index] = FALSE; | ||
200 | } | ||
201 | |||
202 | NdisAllocateSpinLock(&pAd->irq_lock); | ||
203 | |||
204 | } while (FALSE); | ||
205 | |||
206 | if ((Status != NDIS_STATUS_SUCCESS) && (pBeaconBuf)) | ||
207 | kfree(pBeaconBuf); | ||
208 | |||
209 | *ppAdapter = pAd; | ||
210 | |||
211 | DBGPRINT_S(Status, ("<-- RTMPAllocAdapterBlock, Status=%x\n", Status)); | ||
212 | return Status; | ||
213 | } | ||
214 | |||
215 | /* | ||
216 | ======================================================================== | ||
217 | |||
218 | Routine Description: | ||
219 | Read initial Tx power per MCS and BW from EEPROM | ||
220 | |||
221 | Arguments: | ||
222 | Adapter Pointer to our adapter | ||
223 | |||
224 | Return Value: | ||
225 | None | ||
226 | |||
227 | IRQL = PASSIVE_LEVEL | ||
228 | |||
229 | Note: | ||
230 | |||
231 | ======================================================================== | ||
232 | */ | ||
233 | void RTMPReadTxPwrPerRate(struct rt_rtmp_adapter *pAd) | ||
234 | { | ||
235 | unsigned long data, Adata, Gdata; | ||
236 | u16 i, value, value2; | ||
237 | int Apwrdelta, Gpwrdelta; | ||
238 | u8 t1, t2, t3, t4; | ||
239 | BOOLEAN bApwrdeltaMinus = TRUE, bGpwrdeltaMinus = TRUE; | ||
240 | |||
241 | /* */ | ||
242 | /* Get power delta for 20MHz and 40MHz. */ | ||
243 | /* */ | ||
244 | DBGPRINT(RT_DEBUG_TRACE, ("Txpower per Rate\n")); | ||
245 | RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_DELTA, value2); | ||
246 | Apwrdelta = 0; | ||
247 | Gpwrdelta = 0; | ||
248 | |||
249 | if ((value2 & 0xff) != 0xff) { | ||
250 | if ((value2 & 0x80)) | ||
251 | Gpwrdelta = (value2 & 0xf); | ||
252 | |||
253 | if ((value2 & 0x40)) | ||
254 | bGpwrdeltaMinus = FALSE; | ||
255 | else | ||
256 | bGpwrdeltaMinus = TRUE; | ||
257 | } | ||
258 | if ((value2 & 0xff00) != 0xff00) { | ||
259 | if ((value2 & 0x8000)) | ||
260 | Apwrdelta = ((value2 & 0xf00) >> 8); | ||
261 | |||
262 | if ((value2 & 0x4000)) | ||
263 | bApwrdeltaMinus = FALSE; | ||
264 | else | ||
265 | bApwrdeltaMinus = TRUE; | ||
266 | } | ||
267 | DBGPRINT(RT_DEBUG_TRACE, | ||
268 | ("Gpwrdelta = %x, Apwrdelta = %x .\n", Gpwrdelta, Apwrdelta)); | ||
269 | |||
270 | /* */ | ||
271 | /* Get Txpower per MCS for 20MHz in 2.4G. */ | ||
272 | /* */ | ||
273 | for (i = 0; i < 5; i++) { | ||
274 | RT28xx_EEPROM_READ16(pAd, | ||
275 | EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i * 4, | ||
276 | value); | ||
277 | data = value; | ||
278 | if (bApwrdeltaMinus == FALSE) { | ||
279 | t1 = (value & 0xf) + (Apwrdelta); | ||
280 | if (t1 > 0xf) | ||
281 | t1 = 0xf; | ||
282 | t2 = ((value & 0xf0) >> 4) + (Apwrdelta); | ||
283 | if (t2 > 0xf) | ||
284 | t2 = 0xf; | ||
285 | t3 = ((value & 0xf00) >> 8) + (Apwrdelta); | ||
286 | if (t3 > 0xf) | ||
287 | t3 = 0xf; | ||
288 | t4 = ((value & 0xf000) >> 12) + (Apwrdelta); | ||
289 | if (t4 > 0xf) | ||
290 | t4 = 0xf; | ||
291 | } else { | ||
292 | if ((value & 0xf) > Apwrdelta) | ||
293 | t1 = (value & 0xf) - (Apwrdelta); | ||
294 | else | ||
295 | t1 = 0; | ||
296 | if (((value & 0xf0) >> 4) > Apwrdelta) | ||
297 | t2 = ((value & 0xf0) >> 4) - (Apwrdelta); | ||
298 | else | ||
299 | t2 = 0; | ||
300 | if (((value & 0xf00) >> 8) > Apwrdelta) | ||
301 | t3 = ((value & 0xf00) >> 8) - (Apwrdelta); | ||
302 | else | ||
303 | t3 = 0; | ||
304 | if (((value & 0xf000) >> 12) > Apwrdelta) | ||
305 | t4 = ((value & 0xf000) >> 12) - (Apwrdelta); | ||
306 | else | ||
307 | t4 = 0; | ||
308 | } | ||
309 | Adata = t1 + (t2 << 4) + (t3 << 8) + (t4 << 12); | ||
310 | if (bGpwrdeltaMinus == FALSE) { | ||
311 | t1 = (value & 0xf) + (Gpwrdelta); | ||
312 | if (t1 > 0xf) | ||
313 | t1 = 0xf; | ||
314 | t2 = ((value & 0xf0) >> 4) + (Gpwrdelta); | ||
315 | if (t2 > 0xf) | ||
316 | t2 = 0xf; | ||
317 | t3 = ((value & 0xf00) >> 8) + (Gpwrdelta); | ||
318 | if (t3 > 0xf) | ||
319 | t3 = 0xf; | ||
320 | t4 = ((value & 0xf000) >> 12) + (Gpwrdelta); | ||
321 | if (t4 > 0xf) | ||
322 | t4 = 0xf; | ||
323 | } else { | ||
324 | if ((value & 0xf) > Gpwrdelta) | ||
325 | t1 = (value & 0xf) - (Gpwrdelta); | ||
326 | else | ||
327 | t1 = 0; | ||
328 | if (((value & 0xf0) >> 4) > Gpwrdelta) | ||
329 | t2 = ((value & 0xf0) >> 4) - (Gpwrdelta); | ||
330 | else | ||
331 | t2 = 0; | ||
332 | if (((value & 0xf00) >> 8) > Gpwrdelta) | ||
333 | t3 = ((value & 0xf00) >> 8) - (Gpwrdelta); | ||
334 | else | ||
335 | t3 = 0; | ||
336 | if (((value & 0xf000) >> 12) > Gpwrdelta) | ||
337 | t4 = ((value & 0xf000) >> 12) - (Gpwrdelta); | ||
338 | else | ||
339 | t4 = 0; | ||
340 | } | ||
341 | Gdata = t1 + (t2 << 4) + (t3 << 8) + (t4 << 12); | ||
342 | |||
343 | RT28xx_EEPROM_READ16(pAd, | ||
344 | EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i * 4 + | ||
345 | 2, value); | ||
346 | if (bApwrdeltaMinus == FALSE) { | ||
347 | t1 = (value & 0xf) + (Apwrdelta); | ||
348 | if (t1 > 0xf) | ||
349 | t1 = 0xf; | ||
350 | t2 = ((value & 0xf0) >> 4) + (Apwrdelta); | ||
351 | if (t2 > 0xf) | ||
352 | t2 = 0xf; | ||
353 | t3 = ((value & 0xf00) >> 8) + (Apwrdelta); | ||
354 | if (t3 > 0xf) | ||
355 | t3 = 0xf; | ||
356 | t4 = ((value & 0xf000) >> 12) + (Apwrdelta); | ||
357 | if (t4 > 0xf) | ||
358 | t4 = 0xf; | ||
359 | } else { | ||
360 | if ((value & 0xf) > Apwrdelta) | ||
361 | t1 = (value & 0xf) - (Apwrdelta); | ||
362 | else | ||
363 | t1 = 0; | ||
364 | if (((value & 0xf0) >> 4) > Apwrdelta) | ||
365 | t2 = ((value & 0xf0) >> 4) - (Apwrdelta); | ||
366 | else | ||
367 | t2 = 0; | ||
368 | if (((value & 0xf00) >> 8) > Apwrdelta) | ||
369 | t3 = ((value & 0xf00) >> 8) - (Apwrdelta); | ||
370 | else | ||
371 | t3 = 0; | ||
372 | if (((value & 0xf000) >> 12) > Apwrdelta) | ||
373 | t4 = ((value & 0xf000) >> 12) - (Apwrdelta); | ||
374 | else | ||
375 | t4 = 0; | ||
376 | } | ||
377 | Adata |= ((t1 << 16) + (t2 << 20) + (t3 << 24) + (t4 << 28)); | ||
378 | if (bGpwrdeltaMinus == FALSE) { | ||
379 | t1 = (value & 0xf) + (Gpwrdelta); | ||
380 | if (t1 > 0xf) | ||
381 | t1 = 0xf; | ||
382 | t2 = ((value & 0xf0) >> 4) + (Gpwrdelta); | ||
383 | if (t2 > 0xf) | ||
384 | t2 = 0xf; | ||
385 | t3 = ((value & 0xf00) >> 8) + (Gpwrdelta); | ||
386 | if (t3 > 0xf) | ||
387 | t3 = 0xf; | ||
388 | t4 = ((value & 0xf000) >> 12) + (Gpwrdelta); | ||
389 | if (t4 > 0xf) | ||
390 | t4 = 0xf; | ||
391 | } else { | ||
392 | if ((value & 0xf) > Gpwrdelta) | ||
393 | t1 = (value & 0xf) - (Gpwrdelta); | ||
394 | else | ||
395 | t1 = 0; | ||
396 | if (((value & 0xf0) >> 4) > Gpwrdelta) | ||
397 | t2 = ((value & 0xf0) >> 4) - (Gpwrdelta); | ||
398 | else | ||
399 | t2 = 0; | ||
400 | if (((value & 0xf00) >> 8) > Gpwrdelta) | ||
401 | t3 = ((value & 0xf00) >> 8) - (Gpwrdelta); | ||
402 | else | ||
403 | t3 = 0; | ||
404 | if (((value & 0xf000) >> 12) > Gpwrdelta) | ||
405 | t4 = ((value & 0xf000) >> 12) - (Gpwrdelta); | ||
406 | else | ||
407 | t4 = 0; | ||
408 | } | ||
409 | Gdata |= ((t1 << 16) + (t2 << 20) + (t3 << 24) + (t4 << 28)); | ||
410 | data |= (value << 16); | ||
411 | |||
412 | /* For 20M/40M Power Delta issue */ | ||
413 | pAd->Tx20MPwrCfgABand[i] = data; | ||
414 | pAd->Tx20MPwrCfgGBand[i] = data; | ||
415 | pAd->Tx40MPwrCfgABand[i] = Adata; | ||
416 | pAd->Tx40MPwrCfgGBand[i] = Gdata; | ||
417 | |||
418 | if (data != 0xffffffff) | ||
419 | RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i * 4, data); | ||
420 | DBGPRINT_RAW(RT_DEBUG_TRACE, | ||
421 | ("20MHz BW, 2.4G band-%lx, Adata = %lx, Gdata = %lx \n", | ||
422 | data, Adata, Gdata)); | ||
423 | } | ||
424 | } | ||
425 | |||
426 | /* | ||
427 | ======================================================================== | ||
428 | |||
429 | Routine Description: | ||
430 | Read initial channel power parameters from EEPROM | ||
431 | |||
432 | Arguments: | ||
433 | Adapter Pointer to our adapter | ||
434 | |||
435 | Return Value: | ||
436 | None | ||
437 | |||
438 | IRQL = PASSIVE_LEVEL | ||
439 | |||
440 | Note: | ||
441 | |||
442 | ======================================================================== | ||
443 | */ | ||
444 | void RTMPReadChannelPwr(struct rt_rtmp_adapter *pAd) | ||
445 | { | ||
446 | u8 i, choffset; | ||
447 | EEPROM_TX_PWR_STRUC Power; | ||
448 | EEPROM_TX_PWR_STRUC Power2; | ||
449 | |||
450 | /* Read Tx power value for all channels */ | ||
451 | /* Value from 1 - 0x7f. Default value is 24. */ | ||
452 | /* Power value : 2.4G 0x00 (0) ~ 0x1F (31) */ | ||
453 | /* : 5.5G 0xF9 (-7) ~ 0x0F (15) */ | ||
454 | |||
455 | /* 0. 11b/g, ch1 - ch 14 */ | ||
456 | for (i = 0; i < 7; i++) { | ||
457 | RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX_PWR_OFFSET + i * 2, | ||
458 | Power.word); | ||
459 | RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX2_PWR_OFFSET + i * 2, | ||
460 | Power2.word); | ||
461 | pAd->TxPower[i * 2].Channel = i * 2 + 1; | ||
462 | pAd->TxPower[i * 2 + 1].Channel = i * 2 + 2; | ||
463 | |||
464 | if ((Power.field.Byte0 > 31) || (Power.field.Byte0 < 0)) | ||
465 | pAd->TxPower[i * 2].Power = DEFAULT_RF_TX_POWER; | ||
466 | else | ||
467 | pAd->TxPower[i * 2].Power = Power.field.Byte0; | ||
468 | |||
469 | if ((Power.field.Byte1 > 31) || (Power.field.Byte1 < 0)) | ||
470 | pAd->TxPower[i * 2 + 1].Power = DEFAULT_RF_TX_POWER; | ||
471 | else | ||
472 | pAd->TxPower[i * 2 + 1].Power = Power.field.Byte1; | ||
473 | |||
474 | if ((Power2.field.Byte0 > 31) || (Power2.field.Byte0 < 0)) | ||
475 | pAd->TxPower[i * 2].Power2 = DEFAULT_RF_TX_POWER; | ||
476 | else | ||
477 | pAd->TxPower[i * 2].Power2 = Power2.field.Byte0; | ||
478 | |||
479 | if ((Power2.field.Byte1 > 31) || (Power2.field.Byte1 < 0)) | ||
480 | pAd->TxPower[i * 2 + 1].Power2 = DEFAULT_RF_TX_POWER; | ||
481 | else | ||
482 | pAd->TxPower[i * 2 + 1].Power2 = Power2.field.Byte1; | ||
483 | } | ||
484 | |||
485 | /* 1. U-NII lower/middle band: 36, 38, 40; 44, 46, 48; 52, 54, 56; 60, 62, 64 (including central frequency in BW 40MHz) */ | ||
486 | /* 1.1 Fill up channel */ | ||
487 | choffset = 14; | ||
488 | for (i = 0; i < 4; i++) { | ||
489 | pAd->TxPower[3 * i + choffset + 0].Channel = 36 + i * 8 + 0; | ||
490 | pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER; | ||
491 | pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; | ||
492 | |||
493 | pAd->TxPower[3 * i + choffset + 1].Channel = 36 + i * 8 + 2; | ||
494 | pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER; | ||
495 | pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; | ||
496 | |||
497 | pAd->TxPower[3 * i + choffset + 2].Channel = 36 + i * 8 + 4; | ||
498 | pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER; | ||
499 | pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER; | ||
500 | } | ||
501 | |||
502 | /* 1.2 Fill up power */ | ||
503 | for (i = 0; i < 6; i++) { | ||
504 | RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + i * 2, | ||
505 | Power.word); | ||
506 | RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + i * 2, | ||
507 | Power2.word); | ||
508 | |||
509 | if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7)) | ||
510 | pAd->TxPower[i * 2 + choffset + 0].Power = | ||
511 | Power.field.Byte0; | ||
512 | |||
513 | if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7)) | ||
514 | pAd->TxPower[i * 2 + choffset + 1].Power = | ||
515 | Power.field.Byte1; | ||
516 | |||
517 | if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7)) | ||
518 | pAd->TxPower[i * 2 + choffset + 0].Power2 = | ||
519 | Power2.field.Byte0; | ||
520 | |||
521 | if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7)) | ||
522 | pAd->TxPower[i * 2 + choffset + 1].Power2 = | ||
523 | Power2.field.Byte1; | ||
524 | } | ||
525 | |||
526 | /* 2. HipperLAN 2 100, 102 ,104; 108, 110, 112; 116, 118, 120; 124, 126, 128; 132, 134, 136; 140 (including central frequency in BW 40MHz) */ | ||
527 | /* 2.1 Fill up channel */ | ||
528 | choffset = 14 + 12; | ||
529 | for (i = 0; i < 5; i++) { | ||
530 | pAd->TxPower[3 * i + choffset + 0].Channel = 100 + i * 8 + 0; | ||
531 | pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER; | ||
532 | pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; | ||
533 | |||
534 | pAd->TxPower[3 * i + choffset + 1].Channel = 100 + i * 8 + 2; | ||
535 | pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER; | ||
536 | pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; | ||
537 | |||
538 | pAd->TxPower[3 * i + choffset + 2].Channel = 100 + i * 8 + 4; | ||
539 | pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER; | ||
540 | pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER; | ||
541 | } | ||
542 | pAd->TxPower[3 * 5 + choffset + 0].Channel = 140; | ||
543 | pAd->TxPower[3 * 5 + choffset + 0].Power = DEFAULT_RF_TX_POWER; | ||
544 | pAd->TxPower[3 * 5 + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; | ||
545 | |||
546 | /* 2.2 Fill up power */ | ||
547 | for (i = 0; i < 8; i++) { | ||
548 | RT28xx_EEPROM_READ16(pAd, | ||
549 | EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + | ||
550 | i * 2, Power.word); | ||
551 | RT28xx_EEPROM_READ16(pAd, | ||
552 | EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + | ||
553 | i * 2, Power2.word); | ||
554 | |||
555 | if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7)) | ||
556 | pAd->TxPower[i * 2 + choffset + 0].Power = | ||
557 | Power.field.Byte0; | ||
558 | |||
559 | if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7)) | ||
560 | pAd->TxPower[i * 2 + choffset + 1].Power = | ||
561 | Power.field.Byte1; | ||
562 | |||
563 | if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7)) | ||
564 | pAd->TxPower[i * 2 + choffset + 0].Power2 = | ||
565 | Power2.field.Byte0; | ||
566 | |||
567 | if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7)) | ||
568 | pAd->TxPower[i * 2 + choffset + 1].Power2 = | ||
569 | Power2.field.Byte1; | ||
570 | } | ||
571 | |||
572 | /* 3. U-NII upper band: 149, 151, 153; 157, 159, 161; 165, 167, 169; 171, 173 (including central frequency in BW 40MHz) */ | ||
573 | /* 3.1 Fill up channel */ | ||
574 | choffset = 14 + 12 + 16; | ||
575 | /*for (i = 0; i < 2; i++) */ | ||
576 | for (i = 0; i < 3; i++) { | ||
577 | pAd->TxPower[3 * i + choffset + 0].Channel = 149 + i * 8 + 0; | ||
578 | pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER; | ||
579 | pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; | ||
580 | |||
581 | pAd->TxPower[3 * i + choffset + 1].Channel = 149 + i * 8 + 2; | ||
582 | pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER; | ||
583 | pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; | ||
584 | |||
585 | pAd->TxPower[3 * i + choffset + 2].Channel = 149 + i * 8 + 4; | ||
586 | pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER; | ||
587 | pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER; | ||
588 | } | ||
589 | pAd->TxPower[3 * 3 + choffset + 0].Channel = 171; | ||
590 | pAd->TxPower[3 * 3 + choffset + 0].Power = DEFAULT_RF_TX_POWER; | ||
591 | pAd->TxPower[3 * 3 + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; | ||
592 | |||
593 | pAd->TxPower[3 * 3 + choffset + 1].Channel = 173; | ||
594 | pAd->TxPower[3 * 3 + choffset + 1].Power = DEFAULT_RF_TX_POWER; | ||
595 | pAd->TxPower[3 * 3 + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; | ||
596 | |||
597 | /* 3.2 Fill up power */ | ||
598 | /*for (i = 0; i < 4; i++) */ | ||
599 | for (i = 0; i < 6; i++) { | ||
600 | RT28xx_EEPROM_READ16(pAd, | ||
601 | EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + | ||
602 | i * 2, Power.word); | ||
603 | RT28xx_EEPROM_READ16(pAd, | ||
604 | EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + | ||
605 | i * 2, Power2.word); | ||
606 | |||
607 | if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7)) | ||
608 | pAd->TxPower[i * 2 + choffset + 0].Power = | ||
609 | Power.field.Byte0; | ||
610 | |||
611 | if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7)) | ||
612 | pAd->TxPower[i * 2 + choffset + 1].Power = | ||
613 | Power.field.Byte1; | ||
614 | |||
615 | if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7)) | ||
616 | pAd->TxPower[i * 2 + choffset + 0].Power2 = | ||
617 | Power2.field.Byte0; | ||
618 | |||
619 | if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7)) | ||
620 | pAd->TxPower[i * 2 + choffset + 1].Power2 = | ||
621 | Power2.field.Byte1; | ||
622 | } | ||
623 | |||
624 | /* 4. Print and Debug */ | ||
625 | /*choffset = 14 + 12 + 16 + 7; */ | ||
626 | choffset = 14 + 12 + 16 + 11; | ||
627 | |||
628 | } | ||
629 | |||
630 | /* | ||
631 | ======================================================================== | ||
632 | |||
633 | Routine Description: | ||
634 | Read the following from the registry | ||
635 | 1. All the parameters | ||
636 | 2. NetworkAddres | ||
637 | |||
638 | Arguments: | ||
639 | Adapter Pointer to our adapter | ||
640 | WrapperConfigurationContext For use by NdisOpenConfiguration | ||
641 | |||
642 | Return Value: | ||
643 | NDIS_STATUS_SUCCESS | ||
644 | NDIS_STATUS_FAILURE | ||
645 | NDIS_STATUS_RESOURCES | ||
646 | |||
647 | IRQL = PASSIVE_LEVEL | ||
648 | |||
649 | Note: | ||
650 | |||
651 | ======================================================================== | ||
652 | */ | ||
653 | int NICReadRegParameters(struct rt_rtmp_adapter *pAd, | ||
654 | void *WrapperConfigurationContext) | ||
655 | { | ||
656 | int Status = NDIS_STATUS_SUCCESS; | ||
657 | DBGPRINT_S(Status, ("<-- NICReadRegParameters, Status=%x\n", Status)); | ||
658 | return Status; | ||
659 | } | ||
660 | |||
661 | /* | ||
662 | ======================================================================== | ||
663 | |||
664 | Routine Description: | ||
665 | Read initial parameters from EEPROM | ||
666 | |||
667 | Arguments: | ||
668 | Adapter Pointer to our adapter | ||
669 | |||
670 | Return Value: | ||
671 | None | ||
672 | |||
673 | IRQL = PASSIVE_LEVEL | ||
674 | |||
675 | Note: | ||
676 | |||
677 | ======================================================================== | ||
678 | */ | ||
679 | void NICReadEEPROMParameters(struct rt_rtmp_adapter *pAd, u8 *mac_addr) | ||
680 | { | ||
681 | u32 data = 0; | ||
682 | u16 i, value, value2; | ||
683 | u8 TmpPhy; | ||
684 | EEPROM_TX_PWR_STRUC Power; | ||
685 | EEPROM_VERSION_STRUC Version; | ||
686 | EEPROM_ANTENNA_STRUC Antenna; | ||
687 | EEPROM_NIC_CONFIG2_STRUC NicConfig2; | ||
688 | |||
689 | DBGPRINT(RT_DEBUG_TRACE, ("--> NICReadEEPROMParameters\n")); | ||
690 | |||
691 | if (pAd->chipOps.eeinit) | ||
692 | pAd->chipOps.eeinit(pAd); | ||
693 | |||
694 | /* Init EEPROM Address Number, before access EEPROM; if 93c46, EEPROMAddressNum=6, else if 93c66, EEPROMAddressNum=8 */ | ||
695 | RTMP_IO_READ32(pAd, E2PROM_CSR, &data); | ||
696 | DBGPRINT(RT_DEBUG_TRACE, ("--> E2PROM_CSR = 0x%x\n", data)); | ||
697 | |||
698 | if ((data & 0x30) == 0) | ||
699 | pAd->EEPROMAddressNum = 6; /* 93C46 */ | ||
700 | else if ((data & 0x30) == 0x10) | ||
701 | pAd->EEPROMAddressNum = 8; /* 93C66 */ | ||
702 | else | ||
703 | pAd->EEPROMAddressNum = 8; /* 93C86 */ | ||
704 | DBGPRINT(RT_DEBUG_TRACE, | ||
705 | ("--> EEPROMAddressNum = %d\n", pAd->EEPROMAddressNum)); | ||
706 | |||
707 | /* RT2860 MAC no longer auto load MAC address from E2PROM. Driver has to initialize */ | ||
708 | /* MAC address registers according to E2PROM setting */ | ||
709 | if (mac_addr == NULL || | ||
710 | strlen((char *)mac_addr) != 17 || | ||
711 | mac_addr[2] != ':' || mac_addr[5] != ':' || mac_addr[8] != ':' || | ||
712 | mac_addr[11] != ':' || mac_addr[14] != ':') { | ||
713 | u16 Addr01, Addr23, Addr45; | ||
714 | |||
715 | RT28xx_EEPROM_READ16(pAd, 0x04, Addr01); | ||
716 | RT28xx_EEPROM_READ16(pAd, 0x06, Addr23); | ||
717 | RT28xx_EEPROM_READ16(pAd, 0x08, Addr45); | ||
718 | |||
719 | pAd->PermanentAddress[0] = (u8)(Addr01 & 0xff); | ||
720 | pAd->PermanentAddress[1] = (u8)(Addr01 >> 8); | ||
721 | pAd->PermanentAddress[2] = (u8)(Addr23 & 0xff); | ||
722 | pAd->PermanentAddress[3] = (u8)(Addr23 >> 8); | ||
723 | pAd->PermanentAddress[4] = (u8)(Addr45 & 0xff); | ||
724 | pAd->PermanentAddress[5] = (u8)(Addr45 >> 8); | ||
725 | |||
726 | DBGPRINT(RT_DEBUG_TRACE, | ||
727 | ("Initialize MAC Address from E2PROM \n")); | ||
728 | } else { | ||
729 | int j; | ||
730 | char *macptr; | ||
731 | |||
732 | macptr = (char *)mac_addr; | ||
733 | |||
734 | for (j = 0; j < MAC_ADDR_LEN; j++) { | ||
735 | AtoH(macptr, &pAd->PermanentAddress[j], 1); | ||
736 | macptr = macptr + 3; | ||
737 | } | ||
738 | |||
739 | DBGPRINT(RT_DEBUG_TRACE, | ||
740 | ("Initialize MAC Address from module parameter \n")); | ||
741 | } | ||
742 | |||
743 | { | ||
744 | /*more conveninet to test mbssid, so ap's bssid &0xf1 */ | ||
745 | if (pAd->PermanentAddress[0] == 0xff) | ||
746 | pAd->PermanentAddress[0] = RandomByte(pAd) & 0xf8; | ||
747 | |||
748 | /*if (pAd->PermanentAddress[5] == 0xff) */ | ||
749 | /* pAd->PermanentAddress[5] = RandomByte(pAd)&0xf8; */ | ||
750 | |||
751 | DBGPRINT_RAW(RT_DEBUG_TRACE, | ||
752 | ("E2PROM MAC: =%pM\n", pAd->PermanentAddress)); | ||
753 | if (pAd->bLocalAdminMAC == FALSE) { | ||
754 | MAC_DW0_STRUC csr2; | ||
755 | MAC_DW1_STRUC csr3; | ||
756 | COPY_MAC_ADDR(pAd->CurrentAddress, | ||
757 | pAd->PermanentAddress); | ||
758 | csr2.field.Byte0 = pAd->CurrentAddress[0]; | ||
759 | csr2.field.Byte1 = pAd->CurrentAddress[1]; | ||
760 | csr2.field.Byte2 = pAd->CurrentAddress[2]; | ||
761 | csr2.field.Byte3 = pAd->CurrentAddress[3]; | ||
762 | RTMP_IO_WRITE32(pAd, MAC_ADDR_DW0, csr2.word); | ||
763 | csr3.word = 0; | ||
764 | csr3.field.Byte4 = pAd->CurrentAddress[4]; | ||
765 | csr3.field.Byte5 = pAd->CurrentAddress[5]; | ||
766 | csr3.field.U2MeMask = 0xff; | ||
767 | RTMP_IO_WRITE32(pAd, MAC_ADDR_DW1, csr3.word); | ||
768 | DBGPRINT_RAW(RT_DEBUG_TRACE, | ||
769 | ("E2PROM MAC: =%pM\n", | ||
770 | pAd->PermanentAddress)); | ||
771 | } | ||
772 | } | ||
773 | |||
774 | /* if not return early. cause fail at emulation. */ | ||
775 | /* Init the channel number for TX channel power */ | ||
776 | RTMPReadChannelPwr(pAd); | ||
777 | |||
778 | /* if E2PROM version mismatch with driver's expectation, then skip */ | ||
779 | /* all subsequent E2RPOM retieval and set a system error bit to notify GUI */ | ||
780 | RT28xx_EEPROM_READ16(pAd, EEPROM_VERSION_OFFSET, Version.word); | ||
781 | pAd->EepromVersion = | ||
782 | Version.field.Version + Version.field.FaeReleaseNumber * 256; | ||
783 | DBGPRINT(RT_DEBUG_TRACE, | ||
784 | ("E2PROM: Version = %d, FAE release #%d\n", | ||
785 | Version.field.Version, Version.field.FaeReleaseNumber)); | ||
786 | |||
787 | if (Version.field.Version > VALID_EEPROM_VERSION) { | ||
788 | DBGPRINT_ERR("E2PROM: WRONG VERSION 0x%x, should be %d\n", Version.field.Version, VALID_EEPROM_VERSION); | ||
789 | /*pAd->SystemErrorBitmap |= 0x00000001; | ||
790 | |||
791 | // hard-code default value when no proper E2PROM installed | ||
792 | pAd->bAutoTxAgcA = FALSE; | ||
793 | pAd->bAutoTxAgcG = FALSE; | ||
794 | |||
795 | // Default the channel power | ||
796 | for (i = 0; i < MAX_NUM_OF_CHANNELS; i++) | ||
797 | pAd->TxPower[i].Power = DEFAULT_RF_TX_POWER; | ||
798 | |||
799 | // Default the channel power | ||
800 | for (i = 0; i < MAX_NUM_OF_11JCHANNELS; i++) | ||
801 | pAd->TxPower11J[i].Power = DEFAULT_RF_TX_POWER; | ||
802 | |||
803 | for(i = 0; i < NUM_EEPROM_BBP_PARMS; i++) | ||
804 | pAd->EEPROMDefaultValue[i] = 0xffff; | ||
805 | return; */ | ||
806 | } | ||
807 | /* Read BBP default value from EEPROM and store to array(EEPROMDefaultValue) in pAd */ | ||
808 | RT28xx_EEPROM_READ16(pAd, EEPROM_NIC1_OFFSET, value); | ||
809 | pAd->EEPROMDefaultValue[0] = value; | ||
810 | |||
811 | RT28xx_EEPROM_READ16(pAd, EEPROM_NIC2_OFFSET, value); | ||
812 | pAd->EEPROMDefaultValue[1] = value; | ||
813 | |||
814 | RT28xx_EEPROM_READ16(pAd, 0x38, value); /* Country Region */ | ||
815 | pAd->EEPROMDefaultValue[2] = value; | ||
816 | |||
817 | for (i = 0; i < 8; i++) { | ||
818 | RT28xx_EEPROM_READ16(pAd, EEPROM_BBP_BASE_OFFSET + i * 2, | ||
819 | value); | ||
820 | pAd->EEPROMDefaultValue[i + 3] = value; | ||
821 | } | ||
822 | |||
823 | /* We have to parse NIC configuration 0 at here. */ | ||
824 | /* If TSSI did not have preloaded value, it should reset the TxAutoAgc to false */ | ||
825 | /* Therefore, we have to read TxAutoAgc control beforehand. */ | ||
826 | /* Read Tx AGC control bit */ | ||
827 | Antenna.word = pAd->EEPROMDefaultValue[0]; | ||
828 | if (Antenna.word == 0xFFFF) { | ||
829 | #ifdef RT30xx | ||
830 | if (IS_RT3090(pAd) || IS_RT3390(pAd)) { | ||
831 | Antenna.word = 0; | ||
832 | Antenna.field.RfIcType = RFIC_3020; | ||
833 | Antenna.field.TxPath = 1; | ||
834 | Antenna.field.RxPath = 1; | ||
835 | } else | ||
836 | #endif /* RT30xx // */ | ||
837 | { | ||
838 | |||
839 | Antenna.word = 0; | ||
840 | Antenna.field.RfIcType = RFIC_2820; | ||
841 | Antenna.field.TxPath = 1; | ||
842 | Antenna.field.RxPath = 2; | ||
843 | DBGPRINT(RT_DEBUG_WARN, | ||
844 | ("E2PROM error, hard code as 0x%04x\n", | ||
845 | Antenna.word)); | ||
846 | } | ||
847 | } | ||
848 | /* Choose the desired Tx&Rx stream. */ | ||
849 | if ((pAd->CommonCfg.TxStream == 0) | ||
850 | || (pAd->CommonCfg.TxStream > Antenna.field.TxPath)) | ||
851 | pAd->CommonCfg.TxStream = Antenna.field.TxPath; | ||
852 | |||
853 | if ((pAd->CommonCfg.RxStream == 0) | ||
854 | || (pAd->CommonCfg.RxStream > Antenna.field.RxPath)) { | ||
855 | pAd->CommonCfg.RxStream = Antenna.field.RxPath; | ||
856 | |||
857 | if ((pAd->MACVersion < RALINK_2883_VERSION) && | ||
858 | (pAd->CommonCfg.RxStream > 2)) { | ||
859 | /* only 2 Rx streams for RT2860 series */ | ||
860 | pAd->CommonCfg.RxStream = 2; | ||
861 | } | ||
862 | } | ||
863 | /* 3*3 */ | ||
864 | /* read value from EEPROM and set them to CSR174 ~ 177 in chain0 ~ chain2 */ | ||
865 | /* yet implement */ | ||
866 | for (i = 0; i < 3; i++) { | ||
867 | } | ||
868 | |||
869 | NicConfig2.word = pAd->EEPROMDefaultValue[1]; | ||
870 | |||
871 | { | ||
872 | if ((NicConfig2.word & 0x00ff) == 0xff) { | ||
873 | NicConfig2.word &= 0xff00; | ||
874 | } | ||
875 | |||
876 | if ((NicConfig2.word >> 8) == 0xff) { | ||
877 | NicConfig2.word &= 0x00ff; | ||
878 | } | ||
879 | } | ||
880 | |||
881 | if (NicConfig2.field.DynamicTxAgcControl == 1) | ||
882 | pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = TRUE; | ||
883 | else | ||
884 | pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = FALSE; | ||
885 | |||
886 | DBGPRINT_RAW(RT_DEBUG_TRACE, | ||
887 | ("NICReadEEPROMParameters: RxPath = %d, TxPath = %d\n", | ||
888 | Antenna.field.RxPath, Antenna.field.TxPath)); | ||
889 | |||
890 | /* Save the antenna for future use */ | ||
891 | pAd->Antenna.word = Antenna.word; | ||
892 | |||
893 | /* Set the RfICType here, then we can initialize RFIC related operation callbacks */ | ||
894 | pAd->Mlme.RealRxPath = (u8)Antenna.field.RxPath; | ||
895 | pAd->RfIcType = (u8)Antenna.field.RfIcType; | ||
896 | |||
897 | #ifdef RTMP_RF_RW_SUPPORT | ||
898 | RtmpChipOpsRFHook(pAd); | ||
899 | #endif /* RTMP_RF_RW_SUPPORT // */ | ||
900 | |||
901 | #ifdef RTMP_MAC_PCI | ||
902 | sprintf((char *)pAd->nickname, "RT2860STA"); | ||
903 | #endif /* RTMP_MAC_PCI // */ | ||
904 | |||
905 | /* */ | ||
906 | /* Reset PhyMode if we don't support 802.11a */ | ||
907 | /* Only RFIC_2850 & RFIC_2750 support 802.11a */ | ||
908 | /* */ | ||
909 | if ((Antenna.field.RfIcType != RFIC_2850) | ||
910 | && (Antenna.field.RfIcType != RFIC_2750) | ||
911 | && (Antenna.field.RfIcType != RFIC_3052)) { | ||
912 | if ((pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) || | ||
913 | (pAd->CommonCfg.PhyMode == PHY_11A)) | ||
914 | pAd->CommonCfg.PhyMode = PHY_11BG_MIXED; | ||
915 | else if ((pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) || | ||
916 | (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED) || | ||
917 | (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) || | ||
918 | (pAd->CommonCfg.PhyMode == PHY_11N_5G)) | ||
919 | pAd->CommonCfg.PhyMode = PHY_11BGN_MIXED; | ||
920 | } | ||
921 | /* Read TSSI reference and TSSI boundary for temperature compensation. This is ugly */ | ||
922 | /* 0. 11b/g */ | ||
923 | { | ||
924 | /* these are tempature reference value (0x00 ~ 0xFE) | ||
925 | ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0 | ||
926 | TssiPlusBoundaryG [4] [3] [2] [1] [0] (smaller) + | ||
927 | TssiMinusBoundaryG[0] [1] [2] [3] [4] (larger) */ | ||
928 | RT28xx_EEPROM_READ16(pAd, 0x6E, Power.word); | ||
929 | pAd->TssiMinusBoundaryG[4] = Power.field.Byte0; | ||
930 | pAd->TssiMinusBoundaryG[3] = Power.field.Byte1; | ||
931 | RT28xx_EEPROM_READ16(pAd, 0x70, Power.word); | ||
932 | pAd->TssiMinusBoundaryG[2] = Power.field.Byte0; | ||
933 | pAd->TssiMinusBoundaryG[1] = Power.field.Byte1; | ||
934 | RT28xx_EEPROM_READ16(pAd, 0x72, Power.word); | ||
935 | pAd->TssiRefG = Power.field.Byte0; /* reference value [0] */ | ||
936 | pAd->TssiPlusBoundaryG[1] = Power.field.Byte1; | ||
937 | RT28xx_EEPROM_READ16(pAd, 0x74, Power.word); | ||
938 | pAd->TssiPlusBoundaryG[2] = Power.field.Byte0; | ||
939 | pAd->TssiPlusBoundaryG[3] = Power.field.Byte1; | ||
940 | RT28xx_EEPROM_READ16(pAd, 0x76, Power.word); | ||
941 | pAd->TssiPlusBoundaryG[4] = Power.field.Byte0; | ||
942 | pAd->TxAgcStepG = Power.field.Byte1; | ||
943 | pAd->TxAgcCompensateG = 0; | ||
944 | pAd->TssiMinusBoundaryG[0] = pAd->TssiRefG; | ||
945 | pAd->TssiPlusBoundaryG[0] = pAd->TssiRefG; | ||
946 | |||
947 | /* Disable TxAgc if the based value is not right */ | ||
948 | if (pAd->TssiRefG == 0xff) | ||
949 | pAd->bAutoTxAgcG = FALSE; | ||
950 | |||
951 | DBGPRINT(RT_DEBUG_TRACE, | ||
952 | ("E2PROM: G Tssi[-4 .. +4] = %d %d %d %d - %d -%d %d %d %d, step=%d, tuning=%d\n", | ||
953 | pAd->TssiMinusBoundaryG[4], | ||
954 | pAd->TssiMinusBoundaryG[3], | ||
955 | pAd->TssiMinusBoundaryG[2], | ||
956 | pAd->TssiMinusBoundaryG[1], pAd->TssiRefG, | ||
957 | pAd->TssiPlusBoundaryG[1], pAd->TssiPlusBoundaryG[2], | ||
958 | pAd->TssiPlusBoundaryG[3], pAd->TssiPlusBoundaryG[4], | ||
959 | pAd->TxAgcStepG, pAd->bAutoTxAgcG)); | ||
960 | } | ||
961 | /* 1. 11a */ | ||
962 | { | ||
963 | RT28xx_EEPROM_READ16(pAd, 0xD4, Power.word); | ||
964 | pAd->TssiMinusBoundaryA[4] = Power.field.Byte0; | ||
965 | pAd->TssiMinusBoundaryA[3] = Power.field.Byte1; | ||
966 | RT28xx_EEPROM_READ16(pAd, 0xD6, Power.word); | ||
967 | pAd->TssiMinusBoundaryA[2] = Power.field.Byte0; | ||
968 | pAd->TssiMinusBoundaryA[1] = Power.field.Byte1; | ||
969 | RT28xx_EEPROM_READ16(pAd, 0xD8, Power.word); | ||
970 | pAd->TssiRefA = Power.field.Byte0; | ||
971 | pAd->TssiPlusBoundaryA[1] = Power.field.Byte1; | ||
972 | RT28xx_EEPROM_READ16(pAd, 0xDA, Power.word); | ||
973 | pAd->TssiPlusBoundaryA[2] = Power.field.Byte0; | ||
974 | pAd->TssiPlusBoundaryA[3] = Power.field.Byte1; | ||
975 | RT28xx_EEPROM_READ16(pAd, 0xDC, Power.word); | ||
976 | pAd->TssiPlusBoundaryA[4] = Power.field.Byte0; | ||
977 | pAd->TxAgcStepA = Power.field.Byte1; | ||
978 | pAd->TxAgcCompensateA = 0; | ||
979 | pAd->TssiMinusBoundaryA[0] = pAd->TssiRefA; | ||
980 | pAd->TssiPlusBoundaryA[0] = pAd->TssiRefA; | ||
981 | |||
982 | /* Disable TxAgc if the based value is not right */ | ||
983 | if (pAd->TssiRefA == 0xff) | ||
984 | pAd->bAutoTxAgcA = FALSE; | ||
985 | |||
986 | DBGPRINT(RT_DEBUG_TRACE, | ||
987 | ("E2PROM: A Tssi[-4 .. +4] = %d %d %d %d - %d -%d %d %d %d, step=%d, tuning=%d\n", | ||
988 | pAd->TssiMinusBoundaryA[4], | ||
989 | pAd->TssiMinusBoundaryA[3], | ||
990 | pAd->TssiMinusBoundaryA[2], | ||
991 | pAd->TssiMinusBoundaryA[1], pAd->TssiRefA, | ||
992 | pAd->TssiPlusBoundaryA[1], pAd->TssiPlusBoundaryA[2], | ||
993 | pAd->TssiPlusBoundaryA[3], pAd->TssiPlusBoundaryA[4], | ||
994 | pAd->TxAgcStepA, pAd->bAutoTxAgcA)); | ||
995 | } | ||
996 | pAd->BbpRssiToDbmDelta = 0x0; | ||
997 | |||
998 | /* Read frequency offset setting for RF */ | ||
999 | RT28xx_EEPROM_READ16(pAd, EEPROM_FREQ_OFFSET, value); | ||
1000 | if ((value & 0x00FF) != 0x00FF) | ||
1001 | pAd->RfFreqOffset = (unsigned long)(value & 0x00FF); | ||
1002 | else | ||
1003 | pAd->RfFreqOffset = 0; | ||
1004 | DBGPRINT(RT_DEBUG_TRACE, | ||
1005 | ("E2PROM: RF FreqOffset=0x%lx \n", pAd->RfFreqOffset)); | ||
1006 | |||
1007 | /*CountryRegion byte offset (38h) */ | ||
1008 | value = pAd->EEPROMDefaultValue[2] >> 8; /* 2.4G band */ | ||
1009 | value2 = pAd->EEPROMDefaultValue[2] & 0x00FF; /* 5G band */ | ||
1010 | |||
1011 | if ((value <= REGION_MAXIMUM_BG_BAND) | ||
1012 | && (value2 <= REGION_MAXIMUM_A_BAND)) { | ||
1013 | pAd->CommonCfg.CountryRegion = ((u8)value) | 0x80; | ||
1014 | pAd->CommonCfg.CountryRegionForABand = ((u8)value2) | 0x80; | ||
1015 | TmpPhy = pAd->CommonCfg.PhyMode; | ||
1016 | pAd->CommonCfg.PhyMode = 0xff; | ||
1017 | RTMPSetPhyMode(pAd, TmpPhy); | ||
1018 | SetCommonHT(pAd); | ||
1019 | } | ||
1020 | /* */ | ||
1021 | /* Get RSSI Offset on EEPROM 0x9Ah & 0x9Ch. */ | ||
1022 | /* The valid value are (-10 ~ 10) */ | ||
1023 | /* */ | ||
1024 | RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET, value); | ||
1025 | pAd->BGRssiOffset0 = value & 0x00ff; | ||
1026 | pAd->BGRssiOffset1 = (value >> 8); | ||
1027 | RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET + 2, value); | ||
1028 | pAd->BGRssiOffset2 = value & 0x00ff; | ||
1029 | pAd->ALNAGain1 = (value >> 8); | ||
1030 | RT28xx_EEPROM_READ16(pAd, EEPROM_LNA_OFFSET, value); | ||
1031 | pAd->BLNAGain = value & 0x00ff; | ||
1032 | pAd->ALNAGain0 = (value >> 8); | ||
1033 | |||
1034 | /* Validate 11b/g RSSI_0 offset. */ | ||
1035 | if ((pAd->BGRssiOffset0 < -10) || (pAd->BGRssiOffset0 > 10)) | ||
1036 | pAd->BGRssiOffset0 = 0; | ||
1037 | |||
1038 | /* Validate 11b/g RSSI_1 offset. */ | ||
1039 | if ((pAd->BGRssiOffset1 < -10) || (pAd->BGRssiOffset1 > 10)) | ||
1040 | pAd->BGRssiOffset1 = 0; | ||
1041 | |||
1042 | /* Validate 11b/g RSSI_2 offset. */ | ||
1043 | if ((pAd->BGRssiOffset2 < -10) || (pAd->BGRssiOffset2 > 10)) | ||
1044 | pAd->BGRssiOffset2 = 0; | ||
1045 | |||
1046 | RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_A_OFFSET, value); | ||
1047 | pAd->ARssiOffset0 = value & 0x00ff; | ||
1048 | pAd->ARssiOffset1 = (value >> 8); | ||
1049 | RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_A_OFFSET + 2), value); | ||
1050 | pAd->ARssiOffset2 = value & 0x00ff; | ||
1051 | pAd->ALNAGain2 = (value >> 8); | ||
1052 | |||
1053 | if (((u8)pAd->ALNAGain1 == 0xFF) || (pAd->ALNAGain1 == 0x00)) | ||
1054 | pAd->ALNAGain1 = pAd->ALNAGain0; | ||
1055 | if (((u8)pAd->ALNAGain2 == 0xFF) || (pAd->ALNAGain2 == 0x00)) | ||
1056 | pAd->ALNAGain2 = pAd->ALNAGain0; | ||
1057 | |||
1058 | /* Validate 11a RSSI_0 offset. */ | ||
1059 | if ((pAd->ARssiOffset0 < -10) || (pAd->ARssiOffset0 > 10)) | ||
1060 | pAd->ARssiOffset0 = 0; | ||
1061 | |||
1062 | /* Validate 11a RSSI_1 offset. */ | ||
1063 | if ((pAd->ARssiOffset1 < -10) || (pAd->ARssiOffset1 > 10)) | ||
1064 | pAd->ARssiOffset1 = 0; | ||
1065 | |||
1066 | /*Validate 11a RSSI_2 offset. */ | ||
1067 | if ((pAd->ARssiOffset2 < -10) || (pAd->ARssiOffset2 > 10)) | ||
1068 | pAd->ARssiOffset2 = 0; | ||
1069 | |||
1070 | #ifdef RT30xx | ||
1071 | /* */ | ||
1072 | /* Get TX mixer gain setting */ | ||
1073 | /* 0xff are invalid value */ | ||
1074 | /* Note: RT30xX default value is 0x00 and will program to RF_R17 only when this value is not zero. */ | ||
1075 | /* RT359X default value is 0x02 */ | ||
1076 | /* */ | ||
1077 | if (IS_RT30xx(pAd) || IS_RT3572(pAd)) { | ||
1078 | RT28xx_EEPROM_READ16(pAd, EEPROM_TXMIXER_GAIN_2_4G, value); | ||
1079 | pAd->TxMixerGain24G = 0; | ||
1080 | value &= 0x00ff; | ||
1081 | if (value != 0xff) { | ||
1082 | value &= 0x07; | ||
1083 | pAd->TxMixerGain24G = (u8)value; | ||
1084 | } | ||
1085 | } | ||
1086 | #endif /* RT30xx // */ | ||
1087 | |||
1088 | /* */ | ||
1089 | /* Get LED Setting. */ | ||
1090 | /* */ | ||
1091 | RT28xx_EEPROM_READ16(pAd, 0x3a, value); | ||
1092 | pAd->LedCntl.word = (value >> 8); | ||
1093 | RT28xx_EEPROM_READ16(pAd, EEPROM_LED1_OFFSET, value); | ||
1094 | pAd->Led1 = value; | ||
1095 | RT28xx_EEPROM_READ16(pAd, EEPROM_LED2_OFFSET, value); | ||
1096 | pAd->Led2 = value; | ||
1097 | RT28xx_EEPROM_READ16(pAd, EEPROM_LED3_OFFSET, value); | ||
1098 | pAd->Led3 = value; | ||
1099 | |||
1100 | RTMPReadTxPwrPerRate(pAd); | ||
1101 | |||
1102 | #ifdef RT30xx | ||
1103 | #ifdef RTMP_EFUSE_SUPPORT | ||
1104 | RtmpEfuseSupportCheck(pAd); | ||
1105 | #endif /* RTMP_EFUSE_SUPPORT // */ | ||
1106 | #endif /* RT30xx // */ | ||
1107 | |||
1108 | DBGPRINT(RT_DEBUG_TRACE, ("<-- NICReadEEPROMParameters\n")); | ||
1109 | } | ||
1110 | |||
1111 | /* | ||
1112 | ======================================================================== | ||
1113 | |||
1114 | Routine Description: | ||
1115 | Set default value from EEPROM | ||
1116 | |||
1117 | Arguments: | ||
1118 | Adapter Pointer to our adapter | ||
1119 | |||
1120 | Return Value: | ||
1121 | None | ||
1122 | |||
1123 | IRQL = PASSIVE_LEVEL | ||
1124 | |||
1125 | Note: | ||
1126 | |||
1127 | ======================================================================== | ||
1128 | */ | ||
1129 | void NICInitAsicFromEEPROM(struct rt_rtmp_adapter *pAd) | ||
1130 | { | ||
1131 | u32 data = 0; | ||
1132 | u8 BBPR1 = 0; | ||
1133 | u16 i; | ||
1134 | /* EEPROM_ANTENNA_STRUC Antenna; */ | ||
1135 | EEPROM_NIC_CONFIG2_STRUC NicConfig2; | ||
1136 | u8 BBPR3 = 0; | ||
1137 | |||
1138 | DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitAsicFromEEPROM\n")); | ||
1139 | for (i = 3; i < NUM_EEPROM_BBP_PARMS; i++) { | ||
1140 | u8 BbpRegIdx, BbpValue; | ||
1141 | |||
1142 | if ((pAd->EEPROMDefaultValue[i] != 0xFFFF) | ||
1143 | && (pAd->EEPROMDefaultValue[i] != 0)) { | ||
1144 | BbpRegIdx = (u8)(pAd->EEPROMDefaultValue[i] >> 8); | ||
1145 | BbpValue = (u8)(pAd->EEPROMDefaultValue[i] & 0xff); | ||
1146 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BbpRegIdx, BbpValue); | ||
1147 | } | ||
1148 | } | ||
1149 | |||
1150 | NicConfig2.word = pAd->EEPROMDefaultValue[1]; | ||
1151 | |||
1152 | { | ||
1153 | if ((NicConfig2.word & 0x00ff) == 0xff) { | ||
1154 | NicConfig2.word &= 0xff00; | ||
1155 | } | ||
1156 | |||
1157 | if ((NicConfig2.word >> 8) == 0xff) { | ||
1158 | NicConfig2.word &= 0x00ff; | ||
1159 | } | ||
1160 | } | ||
1161 | |||
1162 | /* Save the antenna for future use */ | ||
1163 | pAd->NicConfig2.word = NicConfig2.word; | ||
1164 | |||
1165 | #ifdef RT30xx | ||
1166 | /* set default antenna as main */ | ||
1167 | if (pAd->RfIcType == RFIC_3020) | ||
1168 | AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt); | ||
1169 | #endif /* RT30xx // */ | ||
1170 | |||
1171 | /* */ | ||
1172 | /* Send LED Setting to MCU. */ | ||
1173 | /* */ | ||
1174 | if (pAd->LedCntl.word == 0xFF) { | ||
1175 | pAd->LedCntl.word = 0x01; | ||
1176 | pAd->Led1 = 0x5555; | ||
1177 | pAd->Led2 = 0x2221; | ||
1178 | |||
1179 | #ifdef RTMP_MAC_PCI | ||
1180 | pAd->Led3 = 0xA9F8; | ||
1181 | #endif /* RTMP_MAC_PCI // */ | ||
1182 | #ifdef RTMP_MAC_USB | ||
1183 | pAd->Led3 = 0x5627; | ||
1184 | #endif /* RTMP_MAC_USB // */ | ||
1185 | } | ||
1186 | |||
1187 | AsicSendCommandToMcu(pAd, 0x52, 0xff, (u8)pAd->Led1, | ||
1188 | (u8)(pAd->Led1 >> 8)); | ||
1189 | AsicSendCommandToMcu(pAd, 0x53, 0xff, (u8)pAd->Led2, | ||
1190 | (u8)(pAd->Led2 >> 8)); | ||
1191 | AsicSendCommandToMcu(pAd, 0x54, 0xff, (u8)pAd->Led3, | ||
1192 | (u8)(pAd->Led3 >> 8)); | ||
1193 | AsicSendCommandToMcu(pAd, 0x51, 0xff, 0, pAd->LedCntl.field.Polarity); | ||
1194 | |||
1195 | pAd->LedIndicatorStrength = 0xFF; | ||
1196 | RTMPSetSignalLED(pAd, -100); /* Force signal strength Led to be turned off, before link up */ | ||
1197 | |||
1198 | { | ||
1199 | /* Read Hardware controlled Radio state enable bit */ | ||
1200 | if (NicConfig2.field.HardwareRadioControl == 1) { | ||
1201 | pAd->StaCfg.bHardwareRadio = TRUE; | ||
1202 | |||
1203 | /* Read GPIO pin2 as Hardware controlled radio state */ | ||
1204 | RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data); | ||
1205 | if ((data & 0x04) == 0) { | ||
1206 | pAd->StaCfg.bHwRadio = FALSE; | ||
1207 | pAd->StaCfg.bRadio = FALSE; | ||
1208 | /* RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x00001818); */ | ||
1209 | RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); | ||
1210 | } | ||
1211 | } else | ||
1212 | pAd->StaCfg.bHardwareRadio = FALSE; | ||
1213 | |||
1214 | if (pAd->StaCfg.bRadio == FALSE) { | ||
1215 | RTMPSetLED(pAd, LED_RADIO_OFF); | ||
1216 | } else { | ||
1217 | RTMPSetLED(pAd, LED_RADIO_ON); | ||
1218 | #ifdef RTMP_MAC_PCI | ||
1219 | #ifdef RT3090 | ||
1220 | AsicSendCommandToMcu(pAd, 0x30, PowerRadioOffCID, 0xff, | ||
1221 | 0x02); | ||
1222 | AsicCheckCommanOk(pAd, PowerRadioOffCID); | ||
1223 | #endif /* RT3090 // */ | ||
1224 | #ifndef RT3090 | ||
1225 | AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02); | ||
1226 | #endif /* RT3090 // */ | ||
1227 | AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, | ||
1228 | 0x00); | ||
1229 | /* 2-1. wait command ok. */ | ||
1230 | AsicCheckCommanOk(pAd, PowerWakeCID); | ||
1231 | #endif /* RTMP_MAC_PCI // */ | ||
1232 | } | ||
1233 | } | ||
1234 | |||
1235 | #ifdef RTMP_MAC_PCI | ||
1236 | #ifdef RT30xx | ||
1237 | if (IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) { | ||
1238 | struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps; | ||
1239 | if (pChipOps->AsicReverseRfFromSleepMode) | ||
1240 | pChipOps->AsicReverseRfFromSleepMode(pAd); | ||
1241 | } | ||
1242 | /* 3090 MCU Wakeup command needs more time to be stable. */ | ||
1243 | /* Before stable, don't issue other MCU command to prevent from firmware error. */ | ||
1244 | |||
1245 | if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) | ||
1246 | && IS_VERSION_AFTER_F(pAd) | ||
1247 | && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) | ||
1248 | && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) { | ||
1249 | DBGPRINT(RT_DEBUG_TRACE, ("%s, release Mcu Lock\n", __func__)); | ||
1250 | RTMP_SEM_LOCK(&pAd->McuCmdLock); | ||
1251 | pAd->brt30xxBanMcuCmd = FALSE; | ||
1252 | RTMP_SEM_UNLOCK(&pAd->McuCmdLock); | ||
1253 | } | ||
1254 | #endif /* RT30xx // */ | ||
1255 | #endif /* RTMP_MAC_PCI // */ | ||
1256 | |||
1257 | /* Turn off patching for cardbus controller */ | ||
1258 | if (NicConfig2.field.CardbusAcceleration == 1) { | ||
1259 | /* pAd->bTest1 = TRUE; */ | ||
1260 | } | ||
1261 | |||
1262 | if (NicConfig2.field.DynamicTxAgcControl == 1) | ||
1263 | pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = TRUE; | ||
1264 | else | ||
1265 | pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = FALSE; | ||
1266 | /* */ | ||
1267 | /* Since BBP has been progamed, to make sure BBP setting will be */ | ||
1268 | /* upate inside of AsicAntennaSelect, so reset to UNKNOWN_BAND! */ | ||
1269 | /* */ | ||
1270 | pAd->CommonCfg.BandState = UNKNOWN_BAND; | ||
1271 | |||
1272 | RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); | ||
1273 | BBPR3 &= (~0x18); | ||
1274 | if (pAd->Antenna.field.RxPath == 3) { | ||
1275 | BBPR3 |= (0x10); | ||
1276 | } else if (pAd->Antenna.field.RxPath == 2) { | ||
1277 | BBPR3 |= (0x8); | ||
1278 | } else if (pAd->Antenna.field.RxPath == 1) { | ||
1279 | BBPR3 |= (0x0); | ||
1280 | } | ||
1281 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); | ||
1282 | |||
1283 | { | ||
1284 | /* Handle the difference when 1T */ | ||
1285 | RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPR1); | ||
1286 | if (pAd->Antenna.field.TxPath == 1) { | ||
1287 | BBPR1 &= (~0x18); | ||
1288 | } | ||
1289 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPR1); | ||
1290 | |||
1291 | DBGPRINT(RT_DEBUG_TRACE, | ||
1292 | ("Use Hw Radio Control Pin=%d; if used Pin=%d;\n", | ||
1293 | pAd->CommonCfg.bHardwareRadio, | ||
1294 | pAd->CommonCfg.bHardwareRadio)); | ||
1295 | } | ||
1296 | |||
1297 | #ifdef RTMP_MAC_USB | ||
1298 | #ifdef RT30xx | ||
1299 | /* update registers from EEPROM for RT3071 or later(3572/3592). */ | ||
1300 | |||
1301 | if (IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) { | ||
1302 | u8 RegIdx, RegValue; | ||
1303 | u16 value; | ||
1304 | |||
1305 | /* after RT3071, write BBP from EEPROM 0xF0 to 0x102 */ | ||
1306 | for (i = 0xF0; i <= 0x102; i = i + 2) { | ||
1307 | value = 0xFFFF; | ||
1308 | RT28xx_EEPROM_READ16(pAd, i, value); | ||
1309 | if ((value != 0xFFFF) && (value != 0)) { | ||
1310 | RegIdx = (u8)(value >> 8); | ||
1311 | RegValue = (u8)(value & 0xff); | ||
1312 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, RegIdx, | ||
1313 | RegValue); | ||
1314 | DBGPRINT(RT_DEBUG_TRACE, | ||
1315 | ("Update BBP Registers from EEPROM(0x%0x), BBP(0x%x) = 0x%x\n", | ||
1316 | i, RegIdx, RegValue)); | ||
1317 | } | ||
1318 | } | ||
1319 | |||
1320 | /* after RT3071, write RF from EEPROM 0x104 to 0x116 */ | ||
1321 | for (i = 0x104; i <= 0x116; i = i + 2) { | ||
1322 | value = 0xFFFF; | ||
1323 | RT28xx_EEPROM_READ16(pAd, i, value); | ||
1324 | if ((value != 0xFFFF) && (value != 0)) { | ||
1325 | RegIdx = (u8)(value >> 8); | ||
1326 | RegValue = (u8)(value & 0xff); | ||
1327 | RT30xxWriteRFRegister(pAd, RegIdx, RegValue); | ||
1328 | DBGPRINT(RT_DEBUG_TRACE, | ||
1329 | ("Update RF Registers from EEPROM0x%x), BBP(0x%x) = 0x%x\n", | ||
1330 | i, RegIdx, RegValue)); | ||
1331 | } | ||
1332 | } | ||
1333 | } | ||
1334 | #endif /* RT30xx // */ | ||
1335 | #endif /* RTMP_MAC_USB // */ | ||
1336 | |||
1337 | DBGPRINT(RT_DEBUG_TRACE, | ||
1338 | ("TxPath = %d, RxPath = %d, RFIC=%d, Polar+LED mode=%x\n", | ||
1339 | pAd->Antenna.field.TxPath, pAd->Antenna.field.RxPath, | ||
1340 | pAd->RfIcType, pAd->LedCntl.word)); | ||
1341 | DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitAsicFromEEPROM\n")); | ||
1342 | } | ||
1343 | |||
1344 | /* | ||
1345 | ======================================================================== | ||
1346 | |||
1347 | Routine Description: | ||
1348 | Initialize NIC hardware | ||
1349 | |||
1350 | Arguments: | ||
1351 | Adapter Pointer to our adapter | ||
1352 | |||
1353 | Return Value: | ||
1354 | None | ||
1355 | |||
1356 | IRQL = PASSIVE_LEVEL | ||
1357 | |||
1358 | Note: | ||
1359 | |||
1360 | ======================================================================== | ||
1361 | */ | ||
1362 | int NICInitializeAdapter(struct rt_rtmp_adapter *pAd, IN BOOLEAN bHardReset) | ||
1363 | { | ||
1364 | int Status = NDIS_STATUS_SUCCESS; | ||
1365 | WPDMA_GLO_CFG_STRUC GloCfg; | ||
1366 | #ifdef RTMP_MAC_PCI | ||
1367 | u32 Value; | ||
1368 | DELAY_INT_CFG_STRUC IntCfg; | ||
1369 | #endif /* RTMP_MAC_PCI // */ | ||
1370 | /* INT_MASK_CSR_STRUC IntMask; */ | ||
1371 | unsigned long i = 0, j = 0; | ||
1372 | AC_TXOP_CSR0_STRUC csr0; | ||
1373 | |||
1374 | DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitializeAdapter\n")); | ||
1375 | |||
1376 | /* 3. Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits: */ | ||
1377 | retry: | ||
1378 | i = 0; | ||
1379 | do { | ||
1380 | RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); | ||
1381 | if ((GloCfg.field.TxDMABusy == 0) | ||
1382 | && (GloCfg.field.RxDMABusy == 0)) | ||
1383 | break; | ||
1384 | |||
1385 | RTMPusecDelay(1000); | ||
1386 | i++; | ||
1387 | } while (i < 100); | ||
1388 | DBGPRINT(RT_DEBUG_TRACE, | ||
1389 | ("<== DMA offset 0x208 = 0x%x\n", GloCfg.word)); | ||
1390 | GloCfg.word &= 0xff0; | ||
1391 | GloCfg.field.EnTXWriteBackDDONE = 1; | ||
1392 | RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); | ||
1393 | |||
1394 | /* Record HW Beacon offset */ | ||
1395 | pAd->BeaconOffset[0] = HW_BEACON_BASE0; | ||
1396 | pAd->BeaconOffset[1] = HW_BEACON_BASE1; | ||
1397 | pAd->BeaconOffset[2] = HW_BEACON_BASE2; | ||
1398 | pAd->BeaconOffset[3] = HW_BEACON_BASE3; | ||
1399 | pAd->BeaconOffset[4] = HW_BEACON_BASE4; | ||
1400 | pAd->BeaconOffset[5] = HW_BEACON_BASE5; | ||
1401 | pAd->BeaconOffset[6] = HW_BEACON_BASE6; | ||
1402 | pAd->BeaconOffset[7] = HW_BEACON_BASE7; | ||
1403 | |||
1404 | /* */ | ||
1405 | /* write all shared Ring's base address into ASIC */ | ||
1406 | /* */ | ||
1407 | |||
1408 | /* asic simulation sequence put this ahead before loading firmware. */ | ||
1409 | /* pbf hardware reset */ | ||
1410 | #ifdef RTMP_MAC_PCI | ||
1411 | RTMP_IO_WRITE32(pAd, WPDMA_RST_IDX, 0x1003f); /* 0x10000 for reset rx, 0x3f resets all 6 tx rings. */ | ||
1412 | RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0xe1f); | ||
1413 | RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0xe00); | ||
1414 | #endif /* RTMP_MAC_PCI // */ | ||
1415 | |||
1416 | /* Initialze ASIC for TX & Rx operation */ | ||
1417 | if (NICInitializeAsic(pAd, bHardReset) != NDIS_STATUS_SUCCESS) { | ||
1418 | if (j++ == 0) { | ||
1419 | NICLoadFirmware(pAd); | ||
1420 | goto retry; | ||
1421 | } | ||
1422 | return NDIS_STATUS_FAILURE; | ||
1423 | } | ||
1424 | |||
1425 | #ifdef RTMP_MAC_PCI | ||
1426 | /* Write AC_BK base address register */ | ||
1427 | Value = | ||
1428 | RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_BK].Cell[0].AllocPa); | ||
1429 | RTMP_IO_WRITE32(pAd, TX_BASE_PTR1, Value); | ||
1430 | DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR1 : 0x%x\n", Value)); | ||
1431 | |||
1432 | /* Write AC_BE base address register */ | ||
1433 | Value = | ||
1434 | RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_BE].Cell[0].AllocPa); | ||
1435 | RTMP_IO_WRITE32(pAd, TX_BASE_PTR0, Value); | ||
1436 | DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR0 : 0x%x\n", Value)); | ||
1437 | |||
1438 | /* Write AC_VI base address register */ | ||
1439 | Value = | ||
1440 | RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_VI].Cell[0].AllocPa); | ||
1441 | RTMP_IO_WRITE32(pAd, TX_BASE_PTR2, Value); | ||
1442 | DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR2 : 0x%x\n", Value)); | ||
1443 | |||
1444 | /* Write AC_VO base address register */ | ||
1445 | Value = | ||
1446 | RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_VO].Cell[0].AllocPa); | ||
1447 | RTMP_IO_WRITE32(pAd, TX_BASE_PTR3, Value); | ||
1448 | DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR3 : 0x%x\n", Value)); | ||
1449 | |||
1450 | /* Write MGMT_BASE_CSR register */ | ||
1451 | Value = RTMP_GetPhysicalAddressLow(pAd->MgmtRing.Cell[0].AllocPa); | ||
1452 | RTMP_IO_WRITE32(pAd, TX_BASE_PTR5, Value); | ||
1453 | DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR5 : 0x%x\n", Value)); | ||
1454 | |||
1455 | /* Write RX_BASE_CSR register */ | ||
1456 | Value = RTMP_GetPhysicalAddressLow(pAd->RxRing.Cell[0].AllocPa); | ||
1457 | RTMP_IO_WRITE32(pAd, RX_BASE_PTR, Value); | ||
1458 | DBGPRINT(RT_DEBUG_TRACE, ("--> RX_BASE_PTR : 0x%x\n", Value)); | ||
1459 | |||
1460 | /* Init RX Ring index pointer */ | ||
1461 | pAd->RxRing.RxSwReadIdx = 0; | ||
1462 | pAd->RxRing.RxCpuIdx = RX_RING_SIZE - 1; | ||
1463 | RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); | ||
1464 | |||
1465 | /* Init TX rings index pointer */ | ||
1466 | { | ||
1467 | for (i = 0; i < NUM_OF_TX_RING; i++) { | ||
1468 | pAd->TxRing[i].TxSwFreeIdx = 0; | ||
1469 | pAd->TxRing[i].TxCpuIdx = 0; | ||
1470 | RTMP_IO_WRITE32(pAd, (TX_CTX_IDX0 + i * 0x10), | ||
1471 | pAd->TxRing[i].TxCpuIdx); | ||
1472 | } | ||
1473 | } | ||
1474 | |||
1475 | /* init MGMT ring index pointer */ | ||
1476 | pAd->MgmtRing.TxSwFreeIdx = 0; | ||
1477 | pAd->MgmtRing.TxCpuIdx = 0; | ||
1478 | RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx); | ||
1479 | |||
1480 | /* */ | ||
1481 | /* set each Ring's SIZE into ASIC. Descriptor Size is fixed by design. */ | ||
1482 | /* */ | ||
1483 | |||
1484 | /* Write TX_RING_CSR0 register */ | ||
1485 | Value = TX_RING_SIZE; | ||
1486 | RTMP_IO_WRITE32(pAd, TX_MAX_CNT0, Value); | ||
1487 | RTMP_IO_WRITE32(pAd, TX_MAX_CNT1, Value); | ||
1488 | RTMP_IO_WRITE32(pAd, TX_MAX_CNT2, Value); | ||
1489 | RTMP_IO_WRITE32(pAd, TX_MAX_CNT3, Value); | ||
1490 | RTMP_IO_WRITE32(pAd, TX_MAX_CNT4, Value); | ||
1491 | Value = MGMT_RING_SIZE; | ||
1492 | RTMP_IO_WRITE32(pAd, TX_MGMTMAX_CNT, Value); | ||
1493 | |||
1494 | /* Write RX_RING_CSR register */ | ||
1495 | Value = RX_RING_SIZE; | ||
1496 | RTMP_IO_WRITE32(pAd, RX_MAX_CNT, Value); | ||
1497 | #endif /* RTMP_MAC_PCI // */ | ||
1498 | |||
1499 | /* WMM parameter */ | ||
1500 | csr0.word = 0; | ||
1501 | RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); | ||
1502 | if (pAd->CommonCfg.PhyMode == PHY_11B) { | ||
1503 | csr0.field.Ac0Txop = 192; /* AC_VI: 192*32us ~= 6ms */ | ||
1504 | csr0.field.Ac1Txop = 96; /* AC_VO: 96*32us ~= 3ms */ | ||
1505 | } else { | ||
1506 | csr0.field.Ac0Txop = 96; /* AC_VI: 96*32us ~= 3ms */ | ||
1507 | csr0.field.Ac1Txop = 48; /* AC_VO: 48*32us ~= 1.5ms */ | ||
1508 | } | ||
1509 | RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr0.word); | ||
1510 | |||
1511 | #ifdef RTMP_MAC_PCI | ||
1512 | /* 3. Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits: */ | ||
1513 | i = 0; | ||
1514 | do { | ||
1515 | RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); | ||
1516 | if ((GloCfg.field.TxDMABusy == 0) | ||
1517 | && (GloCfg.field.RxDMABusy == 0)) | ||
1518 | break; | ||
1519 | |||
1520 | RTMPusecDelay(1000); | ||
1521 | i++; | ||
1522 | } while (i < 100); | ||
1523 | |||
1524 | GloCfg.word &= 0xff0; | ||
1525 | GloCfg.field.EnTXWriteBackDDONE = 1; | ||
1526 | RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); | ||
1527 | |||
1528 | IntCfg.word = 0; | ||
1529 | RTMP_IO_WRITE32(pAd, DELAY_INT_CFG, IntCfg.word); | ||
1530 | #endif /* RTMP_MAC_PCI // */ | ||
1531 | |||
1532 | /* reset action */ | ||
1533 | /* Load firmware */ | ||
1534 | /* Status = NICLoadFirmware(pAd); */ | ||
1535 | |||
1536 | DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitializeAdapter\n")); | ||
1537 | return Status; | ||
1538 | } | ||
1539 | |||
1540 | /* | ||
1541 | ======================================================================== | ||
1542 | |||
1543 | Routine Description: | ||
1544 | Initialize ASIC | ||
1545 | |||
1546 | Arguments: | ||
1547 | Adapter Pointer to our adapter | ||
1548 | |||
1549 | Return Value: | ||
1550 | None | ||
1551 | |||
1552 | IRQL = PASSIVE_LEVEL | ||
1553 | |||
1554 | Note: | ||
1555 | |||
1556 | ======================================================================== | ||
1557 | */ | ||
1558 | int NICInitializeAsic(struct rt_rtmp_adapter *pAd, IN BOOLEAN bHardReset) | ||
1559 | { | ||
1560 | unsigned long Index = 0; | ||
1561 | u8 R0 = 0xff; | ||
1562 | u32 MacCsr12 = 0, Counter = 0; | ||
1563 | #ifdef RTMP_MAC_USB | ||
1564 | u32 MacCsr0 = 0; | ||
1565 | int Status; | ||
1566 | u8 Value = 0xff; | ||
1567 | #endif /* RTMP_MAC_USB // */ | ||
1568 | #ifdef RT30xx | ||
1569 | u8 bbpreg = 0; | ||
1570 | u8 RFValue = 0; | ||
1571 | #endif /* RT30xx // */ | ||
1572 | u16 KeyIdx; | ||
1573 | int i, apidx; | ||
1574 | |||
1575 | DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitializeAsic\n")); | ||
1576 | |||
1577 | #ifdef RTMP_MAC_PCI | ||
1578 | RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x3); /* To fix driver disable/enable hang issue when radio off */ | ||
1579 | if (bHardReset == TRUE) { | ||
1580 | RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x3); | ||
1581 | } else | ||
1582 | RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1); | ||
1583 | |||
1584 | RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0); | ||
1585 | /* Initialize MAC register to default value */ | ||
1586 | for (Index = 0; Index < NUM_MAC_REG_PARMS; Index++) { | ||
1587 | RTMP_IO_WRITE32(pAd, MACRegTable[Index].Register, | ||
1588 | MACRegTable[Index].Value); | ||
1589 | } | ||
1590 | |||
1591 | { | ||
1592 | for (Index = 0; Index < NUM_STA_MAC_REG_PARMS; Index++) { | ||
1593 | RTMP_IO_WRITE32(pAd, STAMACRegTable[Index].Register, | ||
1594 | STAMACRegTable[Index].Value); | ||
1595 | } | ||
1596 | } | ||
1597 | #endif /* RTMP_MAC_PCI // */ | ||
1598 | #ifdef RTMP_MAC_USB | ||
1599 | /* */ | ||
1600 | /* Make sure MAC gets ready after NICLoadFirmware(). */ | ||
1601 | /* */ | ||
1602 | Index = 0; | ||
1603 | |||
1604 | /*To avoid hang-on issue when interface up in kernel 2.4, */ | ||
1605 | /*we use a local variable "MacCsr0" instead of using "pAd->MACVersion" directly. */ | ||
1606 | do { | ||
1607 | RTMP_IO_READ32(pAd, MAC_CSR0, &MacCsr0); | ||
1608 | |||
1609 | if ((MacCsr0 != 0x00) && (MacCsr0 != 0xFFFFFFFF)) | ||
1610 | break; | ||
1611 | |||
1612 | RTMPusecDelay(10); | ||
1613 | } while (Index++ < 100); | ||
1614 | |||
1615 | pAd->MACVersion = MacCsr0; | ||
1616 | DBGPRINT(RT_DEBUG_TRACE, | ||
1617 | ("MAC_CSR0 [ Ver:Rev=0x%08x]\n", pAd->MACVersion)); | ||
1618 | /* turn on bit13 (set to zero) after rt2860D. This is to solve high-current issue. */ | ||
1619 | RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &MacCsr12); | ||
1620 | MacCsr12 &= (~0x2000); | ||
1621 | RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, MacCsr12); | ||
1622 | |||
1623 | RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x3); | ||
1624 | RTMP_IO_WRITE32(pAd, USB_DMA_CFG, 0x0); | ||
1625 | Status = RTUSBVenderReset(pAd); | ||
1626 | |||
1627 | RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0); | ||
1628 | |||
1629 | /* Initialize MAC register to default value */ | ||
1630 | for (Index = 0; Index < NUM_MAC_REG_PARMS; Index++) { | ||
1631 | #ifdef RT30xx | ||
1632 | if ((MACRegTable[Index].Register == TX_SW_CFG0) | ||
1633 | && (IS_RT3070(pAd) || IS_RT3071(pAd) || IS_RT3572(pAd) | ||
1634 | || IS_RT3090(pAd) || IS_RT3390(pAd))) { | ||
1635 | MACRegTable[Index].Value = 0x00000400; | ||
1636 | } | ||
1637 | #endif /* RT30xx // */ | ||
1638 | RTMP_IO_WRITE32(pAd, (u16)MACRegTable[Index].Register, | ||
1639 | MACRegTable[Index].Value); | ||
1640 | } | ||
1641 | |||
1642 | { | ||
1643 | for (Index = 0; Index < NUM_STA_MAC_REG_PARMS; Index++) { | ||
1644 | RTMP_IO_WRITE32(pAd, | ||
1645 | (u16)STAMACRegTable[Index].Register, | ||
1646 | STAMACRegTable[Index].Value); | ||
1647 | } | ||
1648 | } | ||
1649 | #endif /* RTMP_MAC_USB // */ | ||
1650 | |||
1651 | #ifdef RT30xx | ||
1652 | /* Initialize RT3070 serial MAC registers which is different from RT2870 serial */ | ||
1653 | if (IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) { | ||
1654 | RTMP_IO_WRITE32(pAd, TX_SW_CFG1, 0); | ||
1655 | |||
1656 | /* RT3071 version E has fixed this issue */ | ||
1657 | if ((pAd->MACVersion & 0xffff) < 0x0211) { | ||
1658 | if (pAd->NicConfig2.field.DACTestBit == 1) { | ||
1659 | RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x2C); /* To fix throughput drop drastically */ | ||
1660 | } else { | ||
1661 | RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x0F); /* To fix throughput drop drastically */ | ||
1662 | } | ||
1663 | } else { | ||
1664 | RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x0); | ||
1665 | } | ||
1666 | } else if (IS_RT3070(pAd)) { | ||
1667 | if (((pAd->MACVersion & 0xffff) < 0x0201)) { | ||
1668 | RTMP_IO_WRITE32(pAd, TX_SW_CFG1, 0); | ||
1669 | RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x2C); /* To fix throughput drop drastically */ | ||
1670 | } else { | ||
1671 | RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0); | ||
1672 | } | ||
1673 | } | ||
1674 | #endif /* RT30xx // */ | ||
1675 | |||
1676 | /* */ | ||
1677 | /* Before program BBP, we need to wait BBP/RF get wake up. */ | ||
1678 | /* */ | ||
1679 | Index = 0; | ||
1680 | do { | ||
1681 | RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &MacCsr12); | ||
1682 | |||
1683 | if ((MacCsr12 & 0x03) == 0) /* if BB.RF is stable */ | ||
1684 | break; | ||
1685 | |||
1686 | DBGPRINT(RT_DEBUG_TRACE, | ||
1687 | ("Check MAC_STATUS_CFG = Busy = %x\n", MacCsr12)); | ||
1688 | RTMPusecDelay(1000); | ||
1689 | } while (Index++ < 100); | ||
1690 | |||
1691 | /* The commands to firmware should be after these commands, these commands will init firmware */ | ||
1692 | /* PCI and USB are not the same because PCI driver needs to wait for PCI bus ready */ | ||
1693 | RTMP_IO_WRITE32(pAd, H2M_BBP_AGENT, 0); /* initialize BBP R/W access agent */ | ||
1694 | RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, 0); | ||
1695 | #ifdef RT3090 | ||
1696 | /*2008/11/28:KH add to fix the dead rf frequency offset bug<-- */ | ||
1697 | AsicSendCommandToMcu(pAd, 0x72, 0, 0, 0); | ||
1698 | /*2008/11/28:KH add to fix the dead rf frequency offset bug--> */ | ||
1699 | #endif /* RT3090 // */ | ||
1700 | RTMPusecDelay(1000); | ||
1701 | |||
1702 | /* Read BBP register, make sure BBP is up and running before write new data */ | ||
1703 | Index = 0; | ||
1704 | do { | ||
1705 | RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R0, &R0); | ||
1706 | DBGPRINT(RT_DEBUG_TRACE, ("BBP version = %x\n", R0)); | ||
1707 | } while ((++Index < 20) && ((R0 == 0xff) || (R0 == 0x00))); | ||
1708 | /*ASSERT(Index < 20); //this will cause BSOD on Check-build driver */ | ||
1709 | |||
1710 | if ((R0 == 0xff) || (R0 == 0x00)) | ||
1711 | return NDIS_STATUS_FAILURE; | ||
1712 | |||
1713 | /* Initialize BBP register to default value */ | ||
1714 | for (Index = 0; Index < NUM_BBP_REG_PARMS; Index++) { | ||
1715 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBPRegTable[Index].Register, | ||
1716 | BBPRegTable[Index].Value); | ||
1717 | } | ||
1718 | |||
1719 | #ifdef RTMP_MAC_PCI | ||
1720 | /* TODO: shiang, check MACVersion, currently, rbus-based chip use this. */ | ||
1721 | if (pAd->MACVersion == 0x28720200) { | ||
1722 | /*u8 value; */ | ||
1723 | unsigned long value2; | ||
1724 | |||
1725 | /*disable MLD by Bruce 20080704 */ | ||
1726 | /*BBP_IO_READ8_BY_REG_ID(pAd, BBP_R105, &value); */ | ||
1727 | /*BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R105, value | 4); */ | ||
1728 | |||
1729 | /*Maximum PSDU length from 16K to 32K bytes */ | ||
1730 | RTMP_IO_READ32(pAd, MAX_LEN_CFG, &value2); | ||
1731 | value2 &= ~(0x3 << 12); | ||
1732 | value2 |= (0x2 << 12); | ||
1733 | RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, value2); | ||
1734 | } | ||
1735 | #endif /* RTMP_MAC_PCI // */ | ||
1736 | |||
1737 | /* for rt2860E and after, init BBP_R84 with 0x19. This is for extension channel overlapping IOT. */ | ||
1738 | /* RT3090 should not program BBP R84 to 0x19, otherwise TX will block. */ | ||
1739 | /*3070/71/72,3090,3090A( are included in RT30xx),3572,3390 */ | ||
1740 | if (((pAd->MACVersion & 0xffff) != 0x0101) | ||
1741 | && !(IS_RT30xx(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))) | ||
1742 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R84, 0x19); | ||
1743 | |||
1744 | #ifdef RT30xx | ||
1745 | /* add by johnli, RF power sequence setup */ | ||
1746 | if (IS_RT30xx(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) { /*update for RT3070/71/72/90/91/92,3572,3390. */ | ||
1747 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R79, 0x13); | ||
1748 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R80, 0x05); | ||
1749 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R81, 0x33); | ||
1750 | } | ||
1751 | |||
1752 | if (IS_RT3090(pAd) || IS_RT3390(pAd)) /* RT309x, RT3071/72 */ | ||
1753 | { | ||
1754 | /* enable DC filter */ | ||
1755 | if ((pAd->MACVersion & 0xffff) >= 0x0211) { | ||
1756 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R103, 0xc0); | ||
1757 | } | ||
1758 | /* improve power consumption */ | ||
1759 | RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R138, &bbpreg); | ||
1760 | if (pAd->Antenna.field.TxPath == 1) { | ||
1761 | /* turn off tx DAC_1 */ | ||
1762 | bbpreg = (bbpreg | 0x20); | ||
1763 | } | ||
1764 | |||
1765 | if (pAd->Antenna.field.RxPath == 1) { | ||
1766 | /* turn off tx ADC_1 */ | ||
1767 | bbpreg &= (~0x2); | ||
1768 | } | ||
1769 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R138, bbpreg); | ||
1770 | |||
1771 | /* improve power consumption in RT3071 Ver.E */ | ||
1772 | if ((pAd->MACVersion & 0xffff) >= 0x0211) { | ||
1773 | RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R31, &bbpreg); | ||
1774 | bbpreg &= (~0x3); | ||
1775 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R31, bbpreg); | ||
1776 | } | ||
1777 | } else if (IS_RT3070(pAd)) { | ||
1778 | if ((pAd->MACVersion & 0xffff) >= 0x0201) { | ||
1779 | /* enable DC filter */ | ||
1780 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R103, 0xc0); | ||
1781 | |||
1782 | /* improve power consumption in RT3070 Ver.F */ | ||
1783 | RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R31, &bbpreg); | ||
1784 | bbpreg &= (~0x3); | ||
1785 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R31, bbpreg); | ||
1786 | } | ||
1787 | /* TX_LO1_en, RF R17 register Bit 3 to 0 */ | ||
1788 | RT30xxReadRFRegister(pAd, RF_R17, &RFValue); | ||
1789 | RFValue &= (~0x08); | ||
1790 | /* to fix rx long range issue */ | ||
1791 | if (pAd->NicConfig2.field.ExternalLNAForG == 0) { | ||
1792 | RFValue |= 0x20; | ||
1793 | } | ||
1794 | /* set RF_R17_bit[2:0] equal to EEPROM setting at 0x48h */ | ||
1795 | if (pAd->TxMixerGain24G >= 1) { | ||
1796 | RFValue &= (~0x7); /* clean bit [2:0] */ | ||
1797 | RFValue |= pAd->TxMixerGain24G; | ||
1798 | } | ||
1799 | RT30xxWriteRFRegister(pAd, RF_R17, RFValue); | ||
1800 | } | ||
1801 | /* end johnli */ | ||
1802 | #endif /* RT30xx // */ | ||
1803 | |||
1804 | if (pAd->MACVersion == 0x28600100) { | ||
1805 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16); | ||
1806 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x12); | ||
1807 | } | ||
1808 | |||
1809 | if (pAd->MACVersion >= RALINK_2880E_VERSION && pAd->MACVersion < RALINK_3070_VERSION) /* 3*3 */ | ||
1810 | { | ||
1811 | /* enlarge MAX_LEN_CFG */ | ||
1812 | u32 csr; | ||
1813 | RTMP_IO_READ32(pAd, MAX_LEN_CFG, &csr); | ||
1814 | csr &= 0xFFF; | ||
1815 | csr |= 0x2000; | ||
1816 | RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, csr); | ||
1817 | } | ||
1818 | #ifdef RTMP_MAC_USB | ||
1819 | { | ||
1820 | u8 MAC_Value[] = | ||
1821 | { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0 }; | ||
1822 | |||
1823 | /*Initialize WCID table */ | ||
1824 | Value = 0xff; | ||
1825 | for (Index = 0; Index < 254; Index++) { | ||
1826 | RTUSBMultiWrite(pAd, | ||
1827 | (u16)(MAC_WCID_BASE + Index * 8), | ||
1828 | MAC_Value, 8); | ||
1829 | } | ||
1830 | } | ||
1831 | #endif /* RTMP_MAC_USB // */ | ||
1832 | |||
1833 | /* Add radio off control */ | ||
1834 | { | ||
1835 | if (pAd->StaCfg.bRadio == FALSE) { | ||
1836 | /* RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x00001818); */ | ||
1837 | RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); | ||
1838 | DBGPRINT(RT_DEBUG_TRACE, ("Set Radio Off\n")); | ||
1839 | } | ||
1840 | } | ||
1841 | |||
1842 | /* Clear raw counters */ | ||
1843 | RTMP_IO_READ32(pAd, RX_STA_CNT0, &Counter); | ||
1844 | RTMP_IO_READ32(pAd, RX_STA_CNT1, &Counter); | ||
1845 | RTMP_IO_READ32(pAd, RX_STA_CNT2, &Counter); | ||
1846 | RTMP_IO_READ32(pAd, TX_STA_CNT0, &Counter); | ||
1847 | RTMP_IO_READ32(pAd, TX_STA_CNT1, &Counter); | ||
1848 | RTMP_IO_READ32(pAd, TX_STA_CNT2, &Counter); | ||
1849 | |||
1850 | /* ASIC will keep garbage value after boot */ | ||
1851 | /* Clear all shared key table when initial */ | ||
1852 | /* This routine can be ignored in radio-ON/OFF operation. */ | ||
1853 | if (bHardReset) { | ||
1854 | for (KeyIdx = 0; KeyIdx < 4; KeyIdx++) { | ||
1855 | RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * KeyIdx, | ||
1856 | 0); | ||
1857 | } | ||
1858 | |||
1859 | /* Clear all pairwise key table when initial */ | ||
1860 | for (KeyIdx = 0; KeyIdx < 256; KeyIdx++) { | ||
1861 | RTMP_IO_WRITE32(pAd, | ||
1862 | MAC_WCID_ATTRIBUTE_BASE + | ||
1863 | (KeyIdx * HW_WCID_ATTRI_SIZE), 1); | ||
1864 | } | ||
1865 | } | ||
1866 | /* assert HOST ready bit */ | ||
1867 | /* RTMP_IO_WRITE32(pAd, MAC_CSR1, 0x0); // 2004-09-14 asked by Mark */ | ||
1868 | /* RTMP_IO_WRITE32(pAd, MAC_CSR1, 0x4); */ | ||
1869 | |||
1870 | /* It isn't necessary to clear this space when not hard reset. */ | ||
1871 | if (bHardReset == TRUE) { | ||
1872 | /* clear all on-chip BEACON frame space */ | ||
1873 | for (apidx = 0; apidx < HW_BEACON_MAX_COUNT; apidx++) { | ||
1874 | for (i = 0; i < HW_BEACON_OFFSET >> 2; i += 4) | ||
1875 | RTMP_IO_WRITE32(pAd, | ||
1876 | pAd->BeaconOffset[apidx] + i, | ||
1877 | 0x00); | ||
1878 | } | ||
1879 | } | ||
1880 | #ifdef RTMP_MAC_USB | ||
1881 | AsicDisableSync(pAd); | ||
1882 | /* Clear raw counters */ | ||
1883 | RTMP_IO_READ32(pAd, RX_STA_CNT0, &Counter); | ||
1884 | RTMP_IO_READ32(pAd, RX_STA_CNT1, &Counter); | ||
1885 | RTMP_IO_READ32(pAd, RX_STA_CNT2, &Counter); | ||
1886 | RTMP_IO_READ32(pAd, TX_STA_CNT0, &Counter); | ||
1887 | RTMP_IO_READ32(pAd, TX_STA_CNT1, &Counter); | ||
1888 | RTMP_IO_READ32(pAd, TX_STA_CNT2, &Counter); | ||
1889 | /* Default PCI clock cycle per ms is different as default setting, which is based on PCI. */ | ||
1890 | RTMP_IO_READ32(pAd, USB_CYC_CFG, &Counter); | ||
1891 | Counter &= 0xffffff00; | ||
1892 | Counter |= 0x000001e; | ||
1893 | RTMP_IO_WRITE32(pAd, USB_CYC_CFG, Counter); | ||
1894 | #endif /* RTMP_MAC_USB // */ | ||
1895 | |||
1896 | { | ||
1897 | /* for rt2860E and after, init TXOP_CTRL_CFG with 0x583f. This is for extension channel overlapping IOT. */ | ||
1898 | if ((pAd->MACVersion & 0xffff) != 0x0101) | ||
1899 | RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x583f); | ||
1900 | } | ||
1901 | |||
1902 | DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitializeAsic\n")); | ||
1903 | return NDIS_STATUS_SUCCESS; | ||
1904 | } | ||
1905 | |||
1906 | /* | ||
1907 | ======================================================================== | ||
1908 | |||
1909 | Routine Description: | ||
1910 | Reset NIC Asics | ||
1911 | |||
1912 | Arguments: | ||
1913 | Adapter Pointer to our adapter | ||
1914 | |||
1915 | Return Value: | ||
1916 | None | ||
1917 | |||
1918 | IRQL = PASSIVE_LEVEL | ||
1919 | |||
1920 | Note: | ||
1921 | Reset NIC to initial state AS IS system boot up time. | ||
1922 | |||
1923 | ======================================================================== | ||
1924 | */ | ||
1925 | void NICIssueReset(struct rt_rtmp_adapter *pAd) | ||
1926 | { | ||
1927 | u32 Value = 0; | ||
1928 | DBGPRINT(RT_DEBUG_TRACE, ("--> NICIssueReset\n")); | ||
1929 | |||
1930 | /* Abort Tx, prevent ASIC from writing to Host memory */ | ||
1931 | /*RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x001f0000); */ | ||
1932 | |||
1933 | /* Disable Rx, register value supposed will remain after reset */ | ||
1934 | RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); | ||
1935 | Value &= (0xfffffff3); | ||
1936 | RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); | ||
1937 | |||
1938 | /* Issue reset and clear from reset state */ | ||
1939 | RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x03); /* 2004-09-17 change from 0x01 */ | ||
1940 | RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x00); | ||
1941 | |||
1942 | DBGPRINT(RT_DEBUG_TRACE, ("<-- NICIssueReset\n")); | ||
1943 | } | ||
1944 | |||
1945 | /* | ||
1946 | ======================================================================== | ||
1947 | |||
1948 | Routine Description: | ||
1949 | Check ASIC registers and find any reason the system might hang | ||
1950 | |||
1951 | Arguments: | ||
1952 | Adapter Pointer to our adapter | ||
1953 | |||
1954 | Return Value: | ||
1955 | None | ||
1956 | |||
1957 | IRQL = DISPATCH_LEVEL | ||
1958 | |||
1959 | ======================================================================== | ||
1960 | */ | ||
1961 | BOOLEAN NICCheckForHang(struct rt_rtmp_adapter *pAd) | ||
1962 | { | ||
1963 | return (FALSE); | ||
1964 | } | ||
1965 | |||
1966 | void NICUpdateFifoStaCounters(struct rt_rtmp_adapter *pAd) | ||
1967 | { | ||
1968 | TX_STA_FIFO_STRUC StaFifo; | ||
1969 | struct rt_mac_table_entry *pEntry; | ||
1970 | u8 i = 0; | ||
1971 | u8 pid = 0, wcid = 0; | ||
1972 | char reTry; | ||
1973 | u8 succMCS; | ||
1974 | |||
1975 | do { | ||
1976 | RTMP_IO_READ32(pAd, TX_STA_FIFO, &StaFifo.word); | ||
1977 | |||
1978 | if (StaFifo.field.bValid == 0) | ||
1979 | break; | ||
1980 | |||
1981 | wcid = (u8)StaFifo.field.wcid; | ||
1982 | |||
1983 | /* ignore NoACK and MGMT frame use 0xFF as WCID */ | ||
1984 | if ((StaFifo.field.TxAckRequired == 0) | ||
1985 | || (wcid >= MAX_LEN_OF_MAC_TABLE)) { | ||
1986 | i++; | ||
1987 | continue; | ||
1988 | } | ||
1989 | |||
1990 | /* PID store Tx MCS Rate */ | ||
1991 | pid = (u8)StaFifo.field.PidType; | ||
1992 | |||
1993 | pEntry = &pAd->MacTab.Content[wcid]; | ||
1994 | |||
1995 | pEntry->DebugFIFOCount++; | ||
1996 | |||
1997 | if (StaFifo.field.TxBF) /* 3*3 */ | ||
1998 | pEntry->TxBFCount++; | ||
1999 | |||
2000 | if (!StaFifo.field.TxSuccess) { | ||
2001 | pEntry->FIFOCount++; | ||
2002 | pEntry->OneSecTxFailCount++; | ||
2003 | |||
2004 | if (pEntry->FIFOCount >= 1) { | ||
2005 | DBGPRINT(RT_DEBUG_TRACE, ("#")); | ||
2006 | pEntry->NoBADataCountDown = 64; | ||
2007 | |||
2008 | if (pEntry->PsMode == PWR_ACTIVE) { | ||
2009 | int tid; | ||
2010 | for (tid = 0; tid < NUM_OF_TID; tid++) { | ||
2011 | BAOriSessionTearDown(pAd, | ||
2012 | pEntry-> | ||
2013 | Aid, tid, | ||
2014 | FALSE, | ||
2015 | FALSE); | ||
2016 | } | ||
2017 | |||
2018 | /* Update the continuous transmission counter except PS mode */ | ||
2019 | pEntry->ContinueTxFailCnt++; | ||
2020 | } else { | ||
2021 | /* Clear the FIFOCount when sta in Power Save mode. Basically we assume */ | ||
2022 | /* this tx error happened due to sta just go to sleep. */ | ||
2023 | pEntry->FIFOCount = 0; | ||
2024 | pEntry->ContinueTxFailCnt = 0; | ||
2025 | } | ||
2026 | /*pEntry->FIFOCount = 0; */ | ||
2027 | } | ||
2028 | /*pEntry->bSendBAR = TRUE; */ | ||
2029 | } else { | ||
2030 | if ((pEntry->PsMode != PWR_SAVE) | ||
2031 | && (pEntry->NoBADataCountDown > 0)) { | ||
2032 | pEntry->NoBADataCountDown--; | ||
2033 | if (pEntry->NoBADataCountDown == 0) { | ||
2034 | DBGPRINT(RT_DEBUG_TRACE, ("@\n")); | ||
2035 | } | ||
2036 | } | ||
2037 | |||
2038 | pEntry->FIFOCount = 0; | ||
2039 | pEntry->OneSecTxNoRetryOkCount++; | ||
2040 | /* update NoDataIdleCount when successful send packet to STA. */ | ||
2041 | pEntry->NoDataIdleCount = 0; | ||
2042 | pEntry->ContinueTxFailCnt = 0; | ||
2043 | } | ||
2044 | |||
2045 | succMCS = StaFifo.field.SuccessRate & 0x7F; | ||
2046 | |||
2047 | reTry = pid - succMCS; | ||
2048 | |||
2049 | if (StaFifo.field.TxSuccess) { | ||
2050 | pEntry->TXMCSExpected[pid]++; | ||
2051 | if (pid == succMCS) { | ||
2052 | pEntry->TXMCSSuccessful[pid]++; | ||
2053 | } else { | ||
2054 | pEntry->TXMCSAutoFallBack[pid][succMCS]++; | ||
2055 | } | ||
2056 | } else { | ||
2057 | pEntry->TXMCSFailed[pid]++; | ||
2058 | } | ||
2059 | |||
2060 | if (reTry > 0) { | ||
2061 | if ((pid >= 12) && succMCS <= 7) { | ||
2062 | reTry -= 4; | ||
2063 | } | ||
2064 | pEntry->OneSecTxRetryOkCount += reTry; | ||
2065 | } | ||
2066 | |||
2067 | i++; | ||
2068 | /* ASIC store 16 stack */ | ||
2069 | } while (i < (2 * TX_RING_SIZE)); | ||
2070 | |||
2071 | } | ||
2072 | |||
2073 | /* | ||
2074 | ======================================================================== | ||
2075 | |||
2076 | Routine Description: | ||
2077 | Read statistical counters from hardware registers and record them | ||
2078 | in software variables for later on query | ||
2079 | |||
2080 | Arguments: | ||
2081 | pAd Pointer to our adapter | ||
2082 | |||
2083 | Return Value: | ||
2084 | None | ||
2085 | |||
2086 | IRQL = DISPATCH_LEVEL | ||
2087 | |||
2088 | ======================================================================== | ||
2089 | */ | ||
2090 | void NICUpdateRawCounters(struct rt_rtmp_adapter *pAd) | ||
2091 | { | ||
2092 | u32 OldValue; /*, Value2; */ | ||
2093 | /*unsigned long PageSum, OneSecTransmitCount; */ | ||
2094 | /*unsigned long TxErrorRatio, Retry, Fail; */ | ||
2095 | RX_STA_CNT0_STRUC RxStaCnt0; | ||
2096 | RX_STA_CNT1_STRUC RxStaCnt1; | ||
2097 | RX_STA_CNT2_STRUC RxStaCnt2; | ||
2098 | TX_STA_CNT0_STRUC TxStaCnt0; | ||
2099 | TX_STA_CNT1_STRUC StaTx1; | ||
2100 | TX_STA_CNT2_STRUC StaTx2; | ||
2101 | TX_AGG_CNT_STRUC TxAggCnt; | ||
2102 | TX_AGG_CNT0_STRUC TxAggCnt0; | ||
2103 | TX_AGG_CNT1_STRUC TxAggCnt1; | ||
2104 | TX_AGG_CNT2_STRUC TxAggCnt2; | ||
2105 | TX_AGG_CNT3_STRUC TxAggCnt3; | ||
2106 | TX_AGG_CNT4_STRUC TxAggCnt4; | ||
2107 | TX_AGG_CNT5_STRUC TxAggCnt5; | ||
2108 | TX_AGG_CNT6_STRUC TxAggCnt6; | ||
2109 | TX_AGG_CNT7_STRUC TxAggCnt7; | ||
2110 | struct rt_counter_ralink *pRalinkCounters; | ||
2111 | |||
2112 | pRalinkCounters = &pAd->RalinkCounters; | ||
2113 | |||
2114 | RTMP_IO_READ32(pAd, RX_STA_CNT0, &RxStaCnt0.word); | ||
2115 | RTMP_IO_READ32(pAd, RX_STA_CNT2, &RxStaCnt2.word); | ||
2116 | |||
2117 | { | ||
2118 | RTMP_IO_READ32(pAd, RX_STA_CNT1, &RxStaCnt1.word); | ||
2119 | /* Update RX PLCP error counter */ | ||
2120 | pAd->PrivateInfo.PhyRxErrCnt += RxStaCnt1.field.PlcpErr; | ||
2121 | /* Update False CCA counter */ | ||
2122 | pAd->RalinkCounters.OneSecFalseCCACnt += | ||
2123 | RxStaCnt1.field.FalseCca; | ||
2124 | } | ||
2125 | |||
2126 | /* Update FCS counters */ | ||
2127 | OldValue = pAd->WlanCounters.FCSErrorCount.u.LowPart; | ||
2128 | pAd->WlanCounters.FCSErrorCount.u.LowPart += (RxStaCnt0.field.CrcErr); /* >> 7); */ | ||
2129 | if (pAd->WlanCounters.FCSErrorCount.u.LowPart < OldValue) | ||
2130 | pAd->WlanCounters.FCSErrorCount.u.HighPart++; | ||
2131 | |||
2132 | /* Add FCS error count to private counters */ | ||
2133 | pRalinkCounters->OneSecRxFcsErrCnt += RxStaCnt0.field.CrcErr; | ||
2134 | OldValue = pRalinkCounters->RealFcsErrCount.u.LowPart; | ||
2135 | pRalinkCounters->RealFcsErrCount.u.LowPart += RxStaCnt0.field.CrcErr; | ||
2136 | if (pRalinkCounters->RealFcsErrCount.u.LowPart < OldValue) | ||
2137 | pRalinkCounters->RealFcsErrCount.u.HighPart++; | ||
2138 | |||
2139 | /* Update Duplicate Rcv check */ | ||
2140 | pRalinkCounters->DuplicateRcv += RxStaCnt2.field.RxDupliCount; | ||
2141 | pAd->WlanCounters.FrameDuplicateCount.u.LowPart += | ||
2142 | RxStaCnt2.field.RxDupliCount; | ||
2143 | /* Update RX Overflow counter */ | ||
2144 | pAd->Counters8023.RxNoBuffer += (RxStaCnt2.field.RxFifoOverflowCount); | ||
2145 | |||
2146 | /*pAd->RalinkCounters.RxCount = 0; */ | ||
2147 | #ifdef RTMP_MAC_USB | ||
2148 | if (pRalinkCounters->RxCount != pAd->watchDogRxCnt) { | ||
2149 | pAd->watchDogRxCnt = pRalinkCounters->RxCount; | ||
2150 | pAd->watchDogRxOverFlowCnt = 0; | ||
2151 | } else { | ||
2152 | if (RxStaCnt2.field.RxFifoOverflowCount) | ||
2153 | pAd->watchDogRxOverFlowCnt++; | ||
2154 | else | ||
2155 | pAd->watchDogRxOverFlowCnt = 0; | ||
2156 | } | ||
2157 | #endif /* RTMP_MAC_USB // */ | ||
2158 | |||
2159 | /*if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED) || */ | ||
2160 | /* (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED) && (pAd->MacTab.Size != 1))) */ | ||
2161 | if (!pAd->bUpdateBcnCntDone) { | ||
2162 | /* Update BEACON sent count */ | ||
2163 | RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word); | ||
2164 | RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word); | ||
2165 | RTMP_IO_READ32(pAd, TX_STA_CNT2, &StaTx2.word); | ||
2166 | pRalinkCounters->OneSecBeaconSentCnt += | ||
2167 | TxStaCnt0.field.TxBeaconCount; | ||
2168 | pRalinkCounters->OneSecTxRetryOkCount += | ||
2169 | StaTx1.field.TxRetransmit; | ||
2170 | pRalinkCounters->OneSecTxNoRetryOkCount += | ||
2171 | StaTx1.field.TxSuccess; | ||
2172 | pRalinkCounters->OneSecTxFailCount += | ||
2173 | TxStaCnt0.field.TxFailCount; | ||
2174 | pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += | ||
2175 | StaTx1.field.TxSuccess; | ||
2176 | pAd->WlanCounters.RetryCount.u.LowPart += | ||
2177 | StaTx1.field.TxRetransmit; | ||
2178 | pAd->WlanCounters.FailedCount.u.LowPart += | ||
2179 | TxStaCnt0.field.TxFailCount; | ||
2180 | } | ||
2181 | |||
2182 | /*if (pAd->bStaFifoTest == TRUE) */ | ||
2183 | { | ||
2184 | RTMP_IO_READ32(pAd, TX_AGG_CNT, &TxAggCnt.word); | ||
2185 | RTMP_IO_READ32(pAd, TX_AGG_CNT0, &TxAggCnt0.word); | ||
2186 | RTMP_IO_READ32(pAd, TX_AGG_CNT1, &TxAggCnt1.word); | ||
2187 | RTMP_IO_READ32(pAd, TX_AGG_CNT2, &TxAggCnt2.word); | ||
2188 | RTMP_IO_READ32(pAd, TX_AGG_CNT3, &TxAggCnt3.word); | ||
2189 | RTMP_IO_READ32(pAd, TX_AGG_CNT4, &TxAggCnt4.word); | ||
2190 | RTMP_IO_READ32(pAd, TX_AGG_CNT5, &TxAggCnt5.word); | ||
2191 | RTMP_IO_READ32(pAd, TX_AGG_CNT6, &TxAggCnt6.word); | ||
2192 | RTMP_IO_READ32(pAd, TX_AGG_CNT7, &TxAggCnt7.word); | ||
2193 | pRalinkCounters->TxAggCount += TxAggCnt.field.AggTxCount; | ||
2194 | pRalinkCounters->TxNonAggCount += TxAggCnt.field.NonAggTxCount; | ||
2195 | pRalinkCounters->TxAgg1MPDUCount += | ||
2196 | TxAggCnt0.field.AggSize1Count; | ||
2197 | pRalinkCounters->TxAgg2MPDUCount += | ||
2198 | TxAggCnt0.field.AggSize2Count; | ||
2199 | |||
2200 | pRalinkCounters->TxAgg3MPDUCount += | ||
2201 | TxAggCnt1.field.AggSize3Count; | ||
2202 | pRalinkCounters->TxAgg4MPDUCount += | ||
2203 | TxAggCnt1.field.AggSize4Count; | ||
2204 | pRalinkCounters->TxAgg5MPDUCount += | ||
2205 | TxAggCnt2.field.AggSize5Count; | ||
2206 | pRalinkCounters->TxAgg6MPDUCount += | ||
2207 | TxAggCnt2.field.AggSize6Count; | ||
2208 | |||
2209 | pRalinkCounters->TxAgg7MPDUCount += | ||
2210 | TxAggCnt3.field.AggSize7Count; | ||
2211 | pRalinkCounters->TxAgg8MPDUCount += | ||
2212 | TxAggCnt3.field.AggSize8Count; | ||
2213 | pRalinkCounters->TxAgg9MPDUCount += | ||
2214 | TxAggCnt4.field.AggSize9Count; | ||
2215 | pRalinkCounters->TxAgg10MPDUCount += | ||
2216 | TxAggCnt4.field.AggSize10Count; | ||
2217 | |||
2218 | pRalinkCounters->TxAgg11MPDUCount += | ||
2219 | TxAggCnt5.field.AggSize11Count; | ||
2220 | pRalinkCounters->TxAgg12MPDUCount += | ||
2221 | TxAggCnt5.field.AggSize12Count; | ||
2222 | pRalinkCounters->TxAgg13MPDUCount += | ||
2223 | TxAggCnt6.field.AggSize13Count; | ||
2224 | pRalinkCounters->TxAgg14MPDUCount += | ||
2225 | TxAggCnt6.field.AggSize14Count; | ||
2226 | |||
2227 | pRalinkCounters->TxAgg15MPDUCount += | ||
2228 | TxAggCnt7.field.AggSize15Count; | ||
2229 | pRalinkCounters->TxAgg16MPDUCount += | ||
2230 | TxAggCnt7.field.AggSize16Count; | ||
2231 | |||
2232 | /* Calculate the transmitted A-MPDU count */ | ||
2233 | pRalinkCounters->TransmittedAMPDUCount.u.LowPart += | ||
2234 | TxAggCnt0.field.AggSize1Count; | ||
2235 | pRalinkCounters->TransmittedAMPDUCount.u.LowPart += | ||
2236 | (TxAggCnt0.field.AggSize2Count / 2); | ||
2237 | |||
2238 | pRalinkCounters->TransmittedAMPDUCount.u.LowPart += | ||
2239 | (TxAggCnt1.field.AggSize3Count / 3); | ||
2240 | pRalinkCounters->TransmittedAMPDUCount.u.LowPart += | ||
2241 | (TxAggCnt1.field.AggSize4Count / 4); | ||
2242 | |||
2243 | pRalinkCounters->TransmittedAMPDUCount.u.LowPart += | ||
2244 | (TxAggCnt2.field.AggSize5Count / 5); | ||
2245 | pRalinkCounters->TransmittedAMPDUCount.u.LowPart += | ||
2246 | (TxAggCnt2.field.AggSize6Count / 6); | ||
2247 | |||
2248 | pRalinkCounters->TransmittedAMPDUCount.u.LowPart += | ||
2249 | (TxAggCnt3.field.AggSize7Count / 7); | ||
2250 | pRalinkCounters->TransmittedAMPDUCount.u.LowPart += | ||
2251 | (TxAggCnt3.field.AggSize8Count / 8); | ||
2252 | |||
2253 | pRalinkCounters->TransmittedAMPDUCount.u.LowPart += | ||
2254 | (TxAggCnt4.field.AggSize9Count / 9); | ||
2255 | pRalinkCounters->TransmittedAMPDUCount.u.LowPart += | ||
2256 | (TxAggCnt4.field.AggSize10Count / 10); | ||
2257 | |||
2258 | pRalinkCounters->TransmittedAMPDUCount.u.LowPart += | ||
2259 | (TxAggCnt5.field.AggSize11Count / 11); | ||
2260 | pRalinkCounters->TransmittedAMPDUCount.u.LowPart += | ||
2261 | (TxAggCnt5.field.AggSize12Count / 12); | ||
2262 | |||
2263 | pRalinkCounters->TransmittedAMPDUCount.u.LowPart += | ||
2264 | (TxAggCnt6.field.AggSize13Count / 13); | ||
2265 | pRalinkCounters->TransmittedAMPDUCount.u.LowPart += | ||
2266 | (TxAggCnt6.field.AggSize14Count / 14); | ||
2267 | |||
2268 | pRalinkCounters->TransmittedAMPDUCount.u.LowPart += | ||
2269 | (TxAggCnt7.field.AggSize15Count / 15); | ||
2270 | pRalinkCounters->TransmittedAMPDUCount.u.LowPart += | ||
2271 | (TxAggCnt7.field.AggSize16Count / 16); | ||
2272 | } | ||
2273 | |||
2274 | } | ||
2275 | |||
2276 | /* | ||
2277 | ======================================================================== | ||
2278 | |||
2279 | Routine Description: | ||
2280 | Reset NIC from error | ||
2281 | |||
2282 | Arguments: | ||
2283 | Adapter Pointer to our adapter | ||
2284 | |||
2285 | Return Value: | ||
2286 | None | ||
2287 | |||
2288 | IRQL = PASSIVE_LEVEL | ||
2289 | |||
2290 | Note: | ||
2291 | Reset NIC from error state | ||
2292 | |||
2293 | ======================================================================== | ||
2294 | */ | ||
2295 | void NICResetFromError(struct rt_rtmp_adapter *pAd) | ||
2296 | { | ||
2297 | /* Reset BBP (according to alex, reset ASIC will force reset BBP */ | ||
2298 | /* Therefore, skip the reset BBP */ | ||
2299 | /* RTMP_IO_WRITE32(pAd, MAC_CSR1, 0x2); */ | ||
2300 | |||
2301 | RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1); | ||
2302 | /* Remove ASIC from reset state */ | ||
2303 | RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0); | ||
2304 | |||
2305 | NICInitializeAdapter(pAd, FALSE); | ||
2306 | NICInitAsicFromEEPROM(pAd); | ||
2307 | |||
2308 | /* Switch to current channel, since during reset process, the connection should remains on. */ | ||
2309 | AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); | ||
2310 | AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); | ||
2311 | } | ||
2312 | |||
2313 | int NICLoadFirmware(struct rt_rtmp_adapter *pAd) | ||
2314 | { | ||
2315 | int status = NDIS_STATUS_SUCCESS; | ||
2316 | if (pAd->chipOps.loadFirmware) | ||
2317 | status = pAd->chipOps.loadFirmware(pAd); | ||
2318 | |||
2319 | return status; | ||
2320 | } | ||
2321 | |||
2322 | /* | ||
2323 | ======================================================================== | ||
2324 | |||
2325 | Routine Description: | ||
2326 | erase 8051 firmware image in MAC ASIC | ||
2327 | |||
2328 | Arguments: | ||
2329 | Adapter Pointer to our adapter | ||
2330 | |||
2331 | IRQL = PASSIVE_LEVEL | ||
2332 | |||
2333 | ======================================================================== | ||
2334 | */ | ||
2335 | void NICEraseFirmware(struct rt_rtmp_adapter *pAd) | ||
2336 | { | ||
2337 | if (pAd->chipOps.eraseFirmware) | ||
2338 | pAd->chipOps.eraseFirmware(pAd); | ||
2339 | |||
2340 | } /* End of NICEraseFirmware */ | ||
2341 | |||
2342 | /* | ||
2343 | ======================================================================== | ||
2344 | |||
2345 | Routine Description: | ||
2346 | Load Tx rate switching parameters | ||
2347 | |||
2348 | Arguments: | ||
2349 | Adapter Pointer to our adapter | ||
2350 | |||
2351 | Return Value: | ||
2352 | NDIS_STATUS_SUCCESS firmware image load ok | ||
2353 | NDIS_STATUS_FAILURE image not found | ||
2354 | |||
2355 | IRQL = PASSIVE_LEVEL | ||
2356 | |||
2357 | Rate Table Format: | ||
2358 | 1. (B0: Valid Item number) (B1:Initial item from zero) | ||
2359 | 2. Item Number(Dec) Mode(Hex) Current MCS(Dec) TrainUp(Dec) TrainDown(Dec) | ||
2360 | |||
2361 | ======================================================================== | ||
2362 | */ | ||
2363 | int NICLoadRateSwitchingParams(struct rt_rtmp_adapter *pAd) | ||
2364 | { | ||
2365 | return NDIS_STATUS_SUCCESS; | ||
2366 | } | ||
2367 | |||
2368 | /* | ||
2369 | ======================================================================== | ||
2370 | |||
2371 | Routine Description: | ||
2372 | Compare two memory block | ||
2373 | |||
2374 | Arguments: | ||
2375 | pSrc1 Pointer to first memory address | ||
2376 | pSrc2 Pointer to second memory address | ||
2377 | |||
2378 | Return Value: | ||
2379 | 0: memory is equal | ||
2380 | 1: pSrc1 memory is larger | ||
2381 | 2: pSrc2 memory is larger | ||
2382 | |||
2383 | IRQL = DISPATCH_LEVEL | ||
2384 | |||
2385 | Note: | ||
2386 | |||
2387 | ======================================================================== | ||
2388 | */ | ||
2389 | unsigned long RTMPCompareMemory(void *pSrc1, void *pSrc2, unsigned long Length) | ||
2390 | { | ||
2391 | u8 *pMem1; | ||
2392 | u8 *pMem2; | ||
2393 | unsigned long Index = 0; | ||
2394 | |||
2395 | pMem1 = (u8 *)pSrc1; | ||
2396 | pMem2 = (u8 *)pSrc2; | ||
2397 | |||
2398 | for (Index = 0; Index < Length; Index++) { | ||
2399 | if (pMem1[Index] > pMem2[Index]) | ||
2400 | return (1); | ||
2401 | else if (pMem1[Index] < pMem2[Index]) | ||
2402 | return (2); | ||
2403 | } | ||
2404 | |||
2405 | /* Equal */ | ||
2406 | return (0); | ||
2407 | } | ||
2408 | |||
2409 | /* | ||
2410 | ======================================================================== | ||
2411 | |||
2412 | Routine Description: | ||
2413 | Zero out memory block | ||
2414 | |||
2415 | Arguments: | ||
2416 | pSrc1 Pointer to memory address | ||
2417 | Length Size | ||
2418 | |||
2419 | Return Value: | ||
2420 | None | ||
2421 | |||
2422 | IRQL = PASSIVE_LEVEL | ||
2423 | IRQL = DISPATCH_LEVEL | ||
2424 | |||
2425 | Note: | ||
2426 | |||
2427 | ======================================================================== | ||
2428 | */ | ||
2429 | void RTMPZeroMemory(void *pSrc, unsigned long Length) | ||
2430 | { | ||
2431 | u8 *pMem; | ||
2432 | unsigned long Index = 0; | ||
2433 | |||
2434 | pMem = (u8 *)pSrc; | ||
2435 | |||
2436 | for (Index = 0; Index < Length; Index++) { | ||
2437 | pMem[Index] = 0x00; | ||
2438 | } | ||
2439 | } | ||
2440 | |||
2441 | /* | ||
2442 | ======================================================================== | ||
2443 | |||
2444 | Routine Description: | ||
2445 | Copy data from memory block 1 to memory block 2 | ||
2446 | |||
2447 | Arguments: | ||
2448 | pDest Pointer to destination memory address | ||
2449 | pSrc Pointer to source memory address | ||
2450 | Length Copy size | ||
2451 | |||
2452 | Return Value: | ||
2453 | None | ||
2454 | |||
2455 | IRQL = PASSIVE_LEVEL | ||
2456 | IRQL = DISPATCH_LEVEL | ||
2457 | |||
2458 | Note: | ||
2459 | |||
2460 | ======================================================================== | ||
2461 | */ | ||
2462 | void RTMPMoveMemory(void *pDest, void *pSrc, unsigned long Length) | ||
2463 | { | ||
2464 | u8 *pMem1; | ||
2465 | u8 *pMem2; | ||
2466 | u32 Index; | ||
2467 | |||
2468 | ASSERT((Length == 0) || (pDest && pSrc)); | ||
2469 | |||
2470 | pMem1 = (u8 *)pDest; | ||
2471 | pMem2 = (u8 *)pSrc; | ||
2472 | |||
2473 | for (Index = 0; Index < Length; Index++) { | ||
2474 | pMem1[Index] = pMem2[Index]; | ||
2475 | } | ||
2476 | } | ||
2477 | |||
2478 | /* | ||
2479 | ======================================================================== | ||
2480 | |||
2481 | Routine Description: | ||
2482 | Initialize port configuration structure | ||
2483 | |||
2484 | Arguments: | ||
2485 | Adapter Pointer to our adapter | ||
2486 | |||
2487 | Return Value: | ||
2488 | None | ||
2489 | |||
2490 | IRQL = PASSIVE_LEVEL | ||
2491 | |||
2492 | Note: | ||
2493 | |||
2494 | ======================================================================== | ||
2495 | */ | ||
2496 | void UserCfgInit(struct rt_rtmp_adapter *pAd) | ||
2497 | { | ||
2498 | u32 key_index, bss_index; | ||
2499 | |||
2500 | DBGPRINT(RT_DEBUG_TRACE, ("--> UserCfgInit\n")); | ||
2501 | |||
2502 | /* */ | ||
2503 | /* part I. initialize common configuration */ | ||
2504 | /* */ | ||
2505 | #ifdef RTMP_MAC_USB | ||
2506 | pAd->BulkOutReq = 0; | ||
2507 | |||
2508 | pAd->BulkOutComplete = 0; | ||
2509 | pAd->BulkOutCompleteOther = 0; | ||
2510 | pAd->BulkOutCompleteCancel = 0; | ||
2511 | pAd->BulkInReq = 0; | ||
2512 | pAd->BulkInComplete = 0; | ||
2513 | pAd->BulkInCompleteFail = 0; | ||
2514 | |||
2515 | /*pAd->QuickTimerP = 100; */ | ||
2516 | /*pAd->TurnAggrBulkInCount = 0; */ | ||
2517 | pAd->bUsbTxBulkAggre = 0; | ||
2518 | |||
2519 | /* init as unused value to ensure driver will set to MCU once. */ | ||
2520 | pAd->LedIndicatorStrength = 0xFF; | ||
2521 | |||
2522 | pAd->CommonCfg.MaxPktOneTxBulk = 2; | ||
2523 | pAd->CommonCfg.TxBulkFactor = 1; | ||
2524 | pAd->CommonCfg.RxBulkFactor = 1; | ||
2525 | |||
2526 | pAd->CommonCfg.TxPower = 100; /*mW */ | ||
2527 | |||
2528 | NdisZeroMemory(&pAd->CommonCfg.IOTestParm, | ||
2529 | sizeof(pAd->CommonCfg.IOTestParm)); | ||
2530 | #endif /* RTMP_MAC_USB // */ | ||
2531 | |||
2532 | for (key_index = 0; key_index < SHARE_KEY_NUM; key_index++) { | ||
2533 | for (bss_index = 0; bss_index < MAX_MBSSID_NUM; bss_index++) { | ||
2534 | pAd->SharedKey[bss_index][key_index].KeyLen = 0; | ||
2535 | pAd->SharedKey[bss_index][key_index].CipherAlg = | ||
2536 | CIPHER_NONE; | ||
2537 | } | ||
2538 | } | ||
2539 | |||
2540 | pAd->EepromAccess = FALSE; | ||
2541 | |||
2542 | pAd->Antenna.word = 0; | ||
2543 | pAd->CommonCfg.BBPCurrentBW = BW_20; | ||
2544 | |||
2545 | pAd->LedCntl.word = 0; | ||
2546 | #ifdef RTMP_MAC_PCI | ||
2547 | pAd->LedIndicatorStrength = 0; | ||
2548 | pAd->RLnkCtrlOffset = 0; | ||
2549 | pAd->HostLnkCtrlOffset = 0; | ||
2550 | pAd->StaCfg.PSControl.field.EnableNewPS = TRUE; | ||
2551 | pAd->CheckDmaBusyCount = 0; | ||
2552 | #endif /* RTMP_MAC_PCI // */ | ||
2553 | |||
2554 | pAd->bAutoTxAgcA = FALSE; /* Default is OFF */ | ||
2555 | pAd->bAutoTxAgcG = FALSE; /* Default is OFF */ | ||
2556 | pAd->RfIcType = RFIC_2820; | ||
2557 | |||
2558 | /* Init timer for reset complete event */ | ||
2559 | pAd->CommonCfg.CentralChannel = 1; | ||
2560 | pAd->bForcePrintTX = FALSE; | ||
2561 | pAd->bForcePrintRX = FALSE; | ||
2562 | pAd->bStaFifoTest = FALSE; | ||
2563 | pAd->bProtectionTest = FALSE; | ||
2564 | pAd->CommonCfg.Dsifs = 10; /* in units of usec */ | ||
2565 | pAd->CommonCfg.TxPower = 100; /*mW */ | ||
2566 | pAd->CommonCfg.TxPowerPercentage = 0xffffffff; /* AUTO */ | ||
2567 | pAd->CommonCfg.TxPowerDefault = 0xffffffff; /* AUTO */ | ||
2568 | pAd->CommonCfg.TxPreamble = Rt802_11PreambleAuto; /* use Long preamble on TX by defaut */ | ||
2569 | pAd->CommonCfg.bUseZeroToDisableFragment = FALSE; | ||
2570 | pAd->CommonCfg.RtsThreshold = 2347; | ||
2571 | pAd->CommonCfg.FragmentThreshold = 2346; | ||
2572 | pAd->CommonCfg.UseBGProtection = 0; /* 0: AUTO */ | ||
2573 | pAd->CommonCfg.bEnableTxBurst = TRUE; /*0; */ | ||
2574 | pAd->CommonCfg.PhyMode = 0xff; /* unknown */ | ||
2575 | pAd->CommonCfg.BandState = UNKNOWN_BAND; | ||
2576 | pAd->CommonCfg.RadarDetect.CSPeriod = 10; | ||
2577 | pAd->CommonCfg.RadarDetect.CSCount = 0; | ||
2578 | pAd->CommonCfg.RadarDetect.RDMode = RD_NORMAL_MODE; | ||
2579 | |||
2580 | pAd->CommonCfg.RadarDetect.ChMovingTime = 65; | ||
2581 | pAd->CommonCfg.RadarDetect.LongPulseRadarTh = 3; | ||
2582 | pAd->CommonCfg.bAPSDCapable = FALSE; | ||
2583 | pAd->CommonCfg.bNeedSendTriggerFrame = FALSE; | ||
2584 | pAd->CommonCfg.TriggerTimerCount = 0; | ||
2585 | pAd->CommonCfg.bAPSDForcePowerSave = FALSE; | ||
2586 | pAd->CommonCfg.bCountryFlag = FALSE; | ||
2587 | pAd->CommonCfg.TxStream = 0; | ||
2588 | pAd->CommonCfg.RxStream = 0; | ||
2589 | |||
2590 | NdisZeroMemory(&pAd->BeaconTxWI, sizeof(pAd->BeaconTxWI)); | ||
2591 | |||
2592 | NdisZeroMemory(&pAd->CommonCfg.HtCapability, | ||
2593 | sizeof(pAd->CommonCfg.HtCapability)); | ||
2594 | pAd->HTCEnable = FALSE; | ||
2595 | pAd->bBroadComHT = FALSE; | ||
2596 | pAd->CommonCfg.bRdg = FALSE; | ||
2597 | |||
2598 | NdisZeroMemory(&pAd->CommonCfg.AddHTInfo, | ||
2599 | sizeof(pAd->CommonCfg.AddHTInfo)); | ||
2600 | pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_ENABLE; | ||
2601 | pAd->CommonCfg.BACapability.field.MpduDensity = 0; | ||
2602 | pAd->CommonCfg.BACapability.field.Policy = IMMED_BA; | ||
2603 | pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64; /*32; */ | ||
2604 | pAd->CommonCfg.BACapability.field.TxBAWinLimit = 64; /*32; */ | ||
2605 | DBGPRINT(RT_DEBUG_TRACE, | ||
2606 | ("--> UserCfgInit. BACapability = 0x%x\n", | ||
2607 | pAd->CommonCfg.BACapability.word)); | ||
2608 | |||
2609 | pAd->CommonCfg.BACapability.field.AutoBA = FALSE; | ||
2610 | BATableInit(pAd, &pAd->BATable); | ||
2611 | |||
2612 | pAd->CommonCfg.bExtChannelSwitchAnnouncement = 1; | ||
2613 | pAd->CommonCfg.bHTProtect = 1; | ||
2614 | pAd->CommonCfg.bMIMOPSEnable = TRUE; | ||
2615 | /*2008/11/05:KH add to support Antenna power-saving of AP<-- */ | ||
2616 | pAd->CommonCfg.bGreenAPEnable = FALSE; | ||
2617 | /*2008/11/05:KH add to support Antenna power-saving of AP--> */ | ||
2618 | pAd->CommonCfg.bBADecline = FALSE; | ||
2619 | pAd->CommonCfg.bDisableReordering = FALSE; | ||
2620 | |||
2621 | if (pAd->MACVersion == 0x28720200) { | ||
2622 | pAd->CommonCfg.TxBASize = 13; /*by Jerry recommend */ | ||
2623 | } else { | ||
2624 | pAd->CommonCfg.TxBASize = 7; | ||
2625 | } | ||
2626 | |||
2627 | pAd->CommonCfg.REGBACapability.word = pAd->CommonCfg.BACapability.word; | ||
2628 | |||
2629 | /*pAd->CommonCfg.HTPhyMode.field.BW = BW_20; */ | ||
2630 | /*pAd->CommonCfg.HTPhyMode.field.MCS = MCS_AUTO; */ | ||
2631 | /*pAd->CommonCfg.HTPhyMode.field.ShortGI = GI_800; */ | ||
2632 | /*pAd->CommonCfg.HTPhyMode.field.STBC = STBC_NONE; */ | ||
2633 | pAd->CommonCfg.TxRate = RATE_6; | ||
2634 | |||
2635 | pAd->CommonCfg.MlmeTransmit.field.MCS = MCS_RATE_6; | ||
2636 | pAd->CommonCfg.MlmeTransmit.field.BW = BW_20; | ||
2637 | pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; | ||
2638 | |||
2639 | pAd->CommonCfg.BeaconPeriod = 100; /* in mSec */ | ||
2640 | |||
2641 | /* */ | ||
2642 | /* part II. initialize STA specific configuration */ | ||
2643 | /* */ | ||
2644 | { | ||
2645 | RX_FILTER_SET_FLAG(pAd, fRX_FILTER_ACCEPT_DIRECT); | ||
2646 | RX_FILTER_CLEAR_FLAG(pAd, fRX_FILTER_ACCEPT_MULTICAST); | ||
2647 | RX_FILTER_SET_FLAG(pAd, fRX_FILTER_ACCEPT_BROADCAST); | ||
2648 | RX_FILTER_SET_FLAG(pAd, fRX_FILTER_ACCEPT_ALL_MULTICAST); | ||
2649 | |||
2650 | pAd->StaCfg.Psm = PWR_ACTIVE; | ||
2651 | |||
2652 | pAd->StaCfg.OrigWepStatus = Ndis802_11EncryptionDisabled; | ||
2653 | pAd->StaCfg.PairCipher = Ndis802_11EncryptionDisabled; | ||
2654 | pAd->StaCfg.GroupCipher = Ndis802_11EncryptionDisabled; | ||
2655 | pAd->StaCfg.bMixCipher = FALSE; | ||
2656 | pAd->StaCfg.DefaultKeyId = 0; | ||
2657 | |||
2658 | /* 802.1x port control */ | ||
2659 | pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP; | ||
2660 | pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; | ||
2661 | pAd->StaCfg.LastMicErrorTime = 0; | ||
2662 | pAd->StaCfg.MicErrCnt = 0; | ||
2663 | pAd->StaCfg.bBlockAssoc = FALSE; | ||
2664 | pAd->StaCfg.WpaState = SS_NOTUSE; | ||
2665 | |||
2666 | pAd->CommonCfg.NdisRadioStateOff = FALSE; /* New to support microsoft disable radio with OID command */ | ||
2667 | |||
2668 | pAd->StaCfg.RssiTrigger = 0; | ||
2669 | NdisZeroMemory(&pAd->StaCfg.RssiSample, sizeof(struct rt_rssi_sample)); | ||
2670 | pAd->StaCfg.RssiTriggerMode = | ||
2671 | RSSI_TRIGGERED_UPON_BELOW_THRESHOLD; | ||
2672 | pAd->StaCfg.AtimWin = 0; | ||
2673 | pAd->StaCfg.DefaultListenCount = 3; /*default listen count; */ | ||
2674 | pAd->StaCfg.BssType = BSS_INFRA; /* BSS_INFRA or BSS_ADHOC or BSS_MONITOR */ | ||
2675 | pAd->StaCfg.bScanReqIsFromWebUI = FALSE; | ||
2676 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); | ||
2677 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WAKEUP_NOW); | ||
2678 | |||
2679 | pAd->StaCfg.bAutoTxRateSwitch = TRUE; | ||
2680 | pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; | ||
2681 | } | ||
2682 | |||
2683 | #ifdef PCIE_PS_SUPPORT | ||
2684 | pAd->brt30xxBanMcuCmd = FALSE; | ||
2685 | pAd->b3090ESpecialChip = FALSE; | ||
2686 | /*KH Debug:the following must be removed */ | ||
2687 | pAd->StaCfg.PSControl.field.rt30xxPowerMode = 3; | ||
2688 | pAd->StaCfg.PSControl.field.rt30xxForceASPMTest = 0; | ||
2689 | pAd->StaCfg.PSControl.field.rt30xxFollowHostASPM = 1; | ||
2690 | #endif /* PCIE_PS_SUPPORT // */ | ||
2691 | |||
2692 | /* global variables mXXXX used in MAC protocol state machines */ | ||
2693 | OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM); | ||
2694 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON); | ||
2695 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON); | ||
2696 | |||
2697 | /* PHY specification */ | ||
2698 | pAd->CommonCfg.PhyMode = PHY_11BG_MIXED; /* default PHY mode */ | ||
2699 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); /* CCK use long preamble */ | ||
2700 | |||
2701 | { | ||
2702 | /* user desired power mode */ | ||
2703 | pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeCAM; | ||
2704 | pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeCAM; | ||
2705 | pAd->StaCfg.bWindowsACCAMEnable = FALSE; | ||
2706 | |||
2707 | RTMPInitTimer(pAd, &pAd->StaCfg.StaQuickResponeForRateUpTimer, | ||
2708 | GET_TIMER_FUNCTION(StaQuickResponeForRateUpExec), | ||
2709 | pAd, FALSE); | ||
2710 | pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE; | ||
2711 | |||
2712 | /* Patch for Ndtest */ | ||
2713 | pAd->StaCfg.ScanCnt = 0; | ||
2714 | |||
2715 | pAd->StaCfg.bHwRadio = TRUE; /* Default Hardware Radio status is On */ | ||
2716 | pAd->StaCfg.bSwRadio = TRUE; /* Default Software Radio status is On */ | ||
2717 | pAd->StaCfg.bRadio = TRUE; /* bHwRadio && bSwRadio */ | ||
2718 | pAd->StaCfg.bHardwareRadio = FALSE; /* Default is OFF */ | ||
2719 | pAd->StaCfg.bShowHiddenSSID = FALSE; /* Default no show */ | ||
2720 | |||
2721 | /* Nitro mode control */ | ||
2722 | pAd->StaCfg.bAutoReconnect = TRUE; | ||
2723 | |||
2724 | /* Save the init time as last scan time, the system should do scan after 2 seconds. */ | ||
2725 | /* This patch is for driver wake up from standby mode, system will do scan right away. */ | ||
2726 | NdisGetSystemUpTime(&pAd->StaCfg.LastScanTime); | ||
2727 | if (pAd->StaCfg.LastScanTime > 10 * OS_HZ) | ||
2728 | pAd->StaCfg.LastScanTime -= (10 * OS_HZ); | ||
2729 | |||
2730 | NdisZeroMemory(pAd->nickname, IW_ESSID_MAX_SIZE + 1); | ||
2731 | #ifdef RTMP_MAC_PCI | ||
2732 | sprintf((char *)pAd->nickname, "RT2860STA"); | ||
2733 | #endif /* RTMP_MAC_PCI // */ | ||
2734 | #ifdef RTMP_MAC_USB | ||
2735 | sprintf((char *)pAd->nickname, "RT2870STA"); | ||
2736 | #endif /* RTMP_MAC_USB // */ | ||
2737 | RTMPInitTimer(pAd, &pAd->StaCfg.WpaDisassocAndBlockAssocTimer, | ||
2738 | GET_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc), | ||
2739 | pAd, FALSE); | ||
2740 | pAd->StaCfg.IEEE8021X = FALSE; | ||
2741 | pAd->StaCfg.IEEE8021x_required_keys = FALSE; | ||
2742 | pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE; | ||
2743 | pAd->StaCfg.bRSN_IE_FromWpaSupplicant = FALSE; | ||
2744 | pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE; | ||
2745 | |||
2746 | NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8); | ||
2747 | |||
2748 | pAd->StaCfg.bAutoConnectByBssid = FALSE; | ||
2749 | pAd->StaCfg.BeaconLostTime = BEACON_LOST_TIME; | ||
2750 | NdisZeroMemory(pAd->StaCfg.WpaPassPhrase, 64); | ||
2751 | pAd->StaCfg.WpaPassPhraseLen = 0; | ||
2752 | pAd->StaCfg.bAutoRoaming = FALSE; | ||
2753 | pAd->StaCfg.bForceTxBurst = FALSE; | ||
2754 | } | ||
2755 | |||
2756 | /* Default for extra information is not valid */ | ||
2757 | pAd->ExtraInfo = EXTRA_INFO_CLEAR; | ||
2758 | |||
2759 | /* Default Config change flag */ | ||
2760 | pAd->bConfigChanged = FALSE; | ||
2761 | |||
2762 | /* */ | ||
2763 | /* part III. AP configurations */ | ||
2764 | /* */ | ||
2765 | |||
2766 | /* */ | ||
2767 | /* part IV. others */ | ||
2768 | /* */ | ||
2769 | /* dynamic BBP R66:sensibity tuning to overcome background noise */ | ||
2770 | pAd->BbpTuning.bEnable = TRUE; | ||
2771 | pAd->BbpTuning.FalseCcaLowerThreshold = 100; | ||
2772 | pAd->BbpTuning.FalseCcaUpperThreshold = 512; | ||
2773 | pAd->BbpTuning.R66Delta = 4; | ||
2774 | pAd->Mlme.bEnableAutoAntennaCheck = TRUE; | ||
2775 | |||
2776 | /* */ | ||
2777 | /* Also initial R66CurrentValue, RTUSBResumeMsduTransmission might use this value. */ | ||
2778 | /* if not initial this value, the default value will be 0. */ | ||
2779 | /* */ | ||
2780 | pAd->BbpTuning.R66CurrentValue = 0x38; | ||
2781 | |||
2782 | pAd->Bbp94 = BBPR94_DEFAULT; | ||
2783 | pAd->BbpForCCK = FALSE; | ||
2784 | |||
2785 | /* Default is FALSE for test bit 1 */ | ||
2786 | /*pAd->bTest1 = FALSE; */ | ||
2787 | |||
2788 | /* initialize MAC table and allocate spin lock */ | ||
2789 | NdisZeroMemory(&pAd->MacTab, sizeof(struct rt_mac_table)); | ||
2790 | InitializeQueueHeader(&pAd->MacTab.McastPsQueue); | ||
2791 | NdisAllocateSpinLock(&pAd->MacTabLock); | ||
2792 | |||
2793 | /*RTMPInitTimer(pAd, &pAd->RECBATimer, RECBATimerTimeout, pAd, TRUE); */ | ||
2794 | /*RTMPSetTimer(&pAd->RECBATimer, REORDER_EXEC_INTV); */ | ||
2795 | |||
2796 | pAd->CommonCfg.bWiFiTest = FALSE; | ||
2797 | #ifdef RTMP_MAC_PCI | ||
2798 | pAd->bPCIclkOff = FALSE; | ||
2799 | #endif /* RTMP_MAC_PCI // */ | ||
2800 | |||
2801 | RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); | ||
2802 | DBGPRINT(RT_DEBUG_TRACE, ("<-- UserCfgInit\n")); | ||
2803 | } | ||
2804 | |||
2805 | /* IRQL = PASSIVE_LEVEL */ | ||
2806 | /* */ | ||
2807 | /* FUNCTION: AtoH(char *, u8 *, int) */ | ||
2808 | /* */ | ||
2809 | /* PURPOSE: Converts ascii string to network order hex */ | ||
2810 | /* */ | ||
2811 | /* PARAMETERS: */ | ||
2812 | /* src - pointer to input ascii string */ | ||
2813 | /* dest - pointer to output hex */ | ||
2814 | /* destlen - size of dest */ | ||
2815 | /* */ | ||
2816 | /* COMMENTS: */ | ||
2817 | /* */ | ||
2818 | /* 2 ascii bytes make a hex byte so must put 1st ascii byte of pair */ | ||
2819 | /* into upper nibble and 2nd ascii byte of pair into lower nibble. */ | ||
2820 | /* */ | ||
2821 | /* IRQL = PASSIVE_LEVEL */ | ||
2822 | |||
2823 | void AtoH(char *src, u8 *dest, int destlen) | ||
2824 | { | ||
2825 | char *srcptr; | ||
2826 | u8 *destTemp; | ||
2827 | |||
2828 | srcptr = src; | ||
2829 | destTemp = (u8 *)dest; | ||
2830 | |||
2831 | while (destlen--) { | ||
2832 | *destTemp = hex_to_bin(*srcptr++) << 4; /* Put 1st ascii byte in upper nibble. */ | ||
2833 | *destTemp += hex_to_bin(*srcptr++); /* Add 2nd ascii byte to above. */ | ||
2834 | destTemp++; | ||
2835 | } | ||
2836 | } | ||
2837 | |||
2838 | /*+++Mark by shiang, not use now, need to remove after confirm */ | ||
2839 | /*---Mark by shiang, not use now, need to remove after confirm */ | ||
2840 | |||
2841 | /* | ||
2842 | ======================================================================== | ||
2843 | |||
2844 | Routine Description: | ||
2845 | Init timer objects | ||
2846 | |||
2847 | Arguments: | ||
2848 | pAd Pointer to our adapter | ||
2849 | pTimer Timer structure | ||
2850 | pTimerFunc Function to execute when timer expired | ||
2851 | Repeat Ture for period timer | ||
2852 | |||
2853 | Return Value: | ||
2854 | None | ||
2855 | |||
2856 | Note: | ||
2857 | |||
2858 | ======================================================================== | ||
2859 | */ | ||
2860 | void RTMPInitTimer(struct rt_rtmp_adapter *pAd, | ||
2861 | struct rt_ralink_timer *pTimer, | ||
2862 | void *pTimerFunc, void *pData, IN BOOLEAN Repeat) | ||
2863 | { | ||
2864 | /* */ | ||
2865 | /* Set Valid to TRUE for later used. */ | ||
2866 | /* It will crash if we cancel a timer or set a timer */ | ||
2867 | /* that we haven't initialize before. */ | ||
2868 | /* */ | ||
2869 | pTimer->Valid = TRUE; | ||
2870 | |||
2871 | pTimer->PeriodicType = Repeat; | ||
2872 | pTimer->State = FALSE; | ||
2873 | pTimer->cookie = (unsigned long)pData; | ||
2874 | |||
2875 | #ifdef RTMP_TIMER_TASK_SUPPORT | ||
2876 | pTimer->pAd = pAd; | ||
2877 | #endif /* RTMP_TIMER_TASK_SUPPORT // */ | ||
2878 | |||
2879 | RTMP_OS_Init_Timer(pAd, &pTimer->TimerObj, pTimerFunc, (void *)pTimer); | ||
2880 | } | ||
2881 | |||
2882 | /* | ||
2883 | ======================================================================== | ||
2884 | |||
2885 | Routine Description: | ||
2886 | Init timer objects | ||
2887 | |||
2888 | Arguments: | ||
2889 | pTimer Timer structure | ||
2890 | Value Timer value in milliseconds | ||
2891 | |||
2892 | Return Value: | ||
2893 | None | ||
2894 | |||
2895 | Note: | ||
2896 | To use this routine, must call RTMPInitTimer before. | ||
2897 | |||
2898 | ======================================================================== | ||
2899 | */ | ||
2900 | void RTMPSetTimer(struct rt_ralink_timer *pTimer, unsigned long Value) | ||
2901 | { | ||
2902 | if (pTimer->Valid) { | ||
2903 | pTimer->TimerValue = Value; | ||
2904 | pTimer->State = FALSE; | ||
2905 | if (pTimer->PeriodicType == TRUE) { | ||
2906 | pTimer->Repeat = TRUE; | ||
2907 | RTMP_SetPeriodicTimer(&pTimer->TimerObj, Value); | ||
2908 | } else { | ||
2909 | pTimer->Repeat = FALSE; | ||
2910 | RTMP_OS_Add_Timer(&pTimer->TimerObj, Value); | ||
2911 | } | ||
2912 | } else { | ||
2913 | DBGPRINT_ERR("RTMPSetTimer failed, Timer hasn't been initialize!\n"); | ||
2914 | } | ||
2915 | } | ||
2916 | |||
2917 | /* | ||
2918 | ======================================================================== | ||
2919 | |||
2920 | Routine Description: | ||
2921 | Init timer objects | ||
2922 | |||
2923 | Arguments: | ||
2924 | pTimer Timer structure | ||
2925 | Value Timer value in milliseconds | ||
2926 | |||
2927 | Return Value: | ||
2928 | None | ||
2929 | |||
2930 | Note: | ||
2931 | To use this routine, must call RTMPInitTimer before. | ||
2932 | |||
2933 | ======================================================================== | ||
2934 | */ | ||
2935 | void RTMPModTimer(struct rt_ralink_timer *pTimer, unsigned long Value) | ||
2936 | { | ||
2937 | BOOLEAN Cancel; | ||
2938 | |||
2939 | if (pTimer->Valid) { | ||
2940 | pTimer->TimerValue = Value; | ||
2941 | pTimer->State = FALSE; | ||
2942 | if (pTimer->PeriodicType == TRUE) { | ||
2943 | RTMPCancelTimer(pTimer, &Cancel); | ||
2944 | RTMPSetTimer(pTimer, Value); | ||
2945 | } else { | ||
2946 | RTMP_OS_Mod_Timer(&pTimer->TimerObj, Value); | ||
2947 | } | ||
2948 | } else { | ||
2949 | DBGPRINT_ERR("RTMPModTimer failed, Timer hasn't been initialize!\n"); | ||
2950 | } | ||
2951 | } | ||
2952 | |||
2953 | /* | ||
2954 | ======================================================================== | ||
2955 | |||
2956 | Routine Description: | ||
2957 | Cancel timer objects | ||
2958 | |||
2959 | Arguments: | ||
2960 | Adapter Pointer to our adapter | ||
2961 | |||
2962 | Return Value: | ||
2963 | None | ||
2964 | |||
2965 | IRQL = PASSIVE_LEVEL | ||
2966 | IRQL = DISPATCH_LEVEL | ||
2967 | |||
2968 | Note: | ||
2969 | 1.) To use this routine, must call RTMPInitTimer before. | ||
2970 | 2.) Reset NIC to initial state AS IS system boot up time. | ||
2971 | |||
2972 | ======================================================================== | ||
2973 | */ | ||
2974 | void RTMPCancelTimer(struct rt_ralink_timer *pTimer, OUT BOOLEAN * pCancelled) | ||
2975 | { | ||
2976 | if (pTimer->Valid) { | ||
2977 | if (pTimer->State == FALSE) | ||
2978 | pTimer->Repeat = FALSE; | ||
2979 | |||
2980 | RTMP_OS_Del_Timer(&pTimer->TimerObj, pCancelled); | ||
2981 | |||
2982 | if (*pCancelled == TRUE) | ||
2983 | pTimer->State = TRUE; | ||
2984 | |||
2985 | #ifdef RTMP_TIMER_TASK_SUPPORT | ||
2986 | /* We need to go-through the TimerQ to findout this timer handler and remove it if */ | ||
2987 | /* it's still waiting for execution. */ | ||
2988 | RtmpTimerQRemove(pTimer->pAd, pTimer); | ||
2989 | #endif /* RTMP_TIMER_TASK_SUPPORT // */ | ||
2990 | } else { | ||
2991 | DBGPRINT_ERR("RTMPCancelTimer failed, Timer hasn't been initialize!\n"); | ||
2992 | } | ||
2993 | } | ||
2994 | |||
2995 | /* | ||
2996 | ======================================================================== | ||
2997 | |||
2998 | Routine Description: | ||
2999 | Set LED Status | ||
3000 | |||
3001 | Arguments: | ||
3002 | pAd Pointer to our adapter | ||
3003 | Status LED Status | ||
3004 | |||
3005 | Return Value: | ||
3006 | None | ||
3007 | |||
3008 | IRQL = PASSIVE_LEVEL | ||
3009 | IRQL = DISPATCH_LEVEL | ||
3010 | |||
3011 | Note: | ||
3012 | |||
3013 | ======================================================================== | ||
3014 | */ | ||
3015 | void RTMPSetLED(struct rt_rtmp_adapter *pAd, u8 Status) | ||
3016 | { | ||
3017 | /*unsigned long data; */ | ||
3018 | u8 HighByte = 0; | ||
3019 | u8 LowByte; | ||
3020 | |||
3021 | LowByte = pAd->LedCntl.field.LedMode & 0x7f; | ||
3022 | switch (Status) { | ||
3023 | case LED_LINK_DOWN: | ||
3024 | HighByte = 0x20; | ||
3025 | AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); | ||
3026 | pAd->LedIndicatorStrength = 0; | ||
3027 | break; | ||
3028 | case LED_LINK_UP: | ||
3029 | if (pAd->CommonCfg.Channel > 14) | ||
3030 | HighByte = 0xa0; | ||
3031 | else | ||
3032 | HighByte = 0x60; | ||
3033 | AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); | ||
3034 | break; | ||
3035 | case LED_RADIO_ON: | ||
3036 | HighByte = 0x20; | ||
3037 | AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); | ||
3038 | break; | ||
3039 | case LED_HALT: | ||
3040 | LowByte = 0; /* Driver sets MAC register and MAC controls LED */ | ||
3041 | case LED_RADIO_OFF: | ||
3042 | HighByte = 0; | ||
3043 | AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); | ||
3044 | break; | ||
3045 | case LED_WPS: | ||
3046 | HighByte = 0x10; | ||
3047 | AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); | ||
3048 | break; | ||
3049 | case LED_ON_SITE_SURVEY: | ||
3050 | HighByte = 0x08; | ||
3051 | AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); | ||
3052 | break; | ||
3053 | case LED_POWER_UP: | ||
3054 | HighByte = 0x04; | ||
3055 | AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); | ||
3056 | break; | ||
3057 | default: | ||
3058 | DBGPRINT(RT_DEBUG_WARN, | ||
3059 | ("RTMPSetLED::Unknown Status %d\n", Status)); | ||
3060 | break; | ||
3061 | } | ||
3062 | |||
3063 | /* */ | ||
3064 | /* Keep LED status for LED SiteSurvey mode. */ | ||
3065 | /* After SiteSurvey, we will set the LED mode to previous status. */ | ||
3066 | /* */ | ||
3067 | if ((Status != LED_ON_SITE_SURVEY) && (Status != LED_POWER_UP)) | ||
3068 | pAd->LedStatus = Status; | ||
3069 | |||
3070 | DBGPRINT(RT_DEBUG_TRACE, | ||
3071 | ("RTMPSetLED::Mode=%d,HighByte=0x%02x,LowByte=0x%02x\n", | ||
3072 | pAd->LedCntl.field.LedMode, HighByte, LowByte)); | ||
3073 | } | ||
3074 | |||
3075 | /* | ||
3076 | ======================================================================== | ||
3077 | |||
3078 | Routine Description: | ||
3079 | Set LED Signal Strength | ||
3080 | |||
3081 | Arguments: | ||
3082 | pAd Pointer to our adapter | ||
3083 | Dbm Signal Strength | ||
3084 | |||
3085 | Return Value: | ||
3086 | None | ||
3087 | |||
3088 | IRQL = PASSIVE_LEVEL | ||
3089 | |||
3090 | Note: | ||
3091 | Can be run on any IRQL level. | ||
3092 | |||
3093 | According to Microsoft Zero Config Wireless Signal Strength definition as belows. | ||
3094 | <= -90 No Signal | ||
3095 | <= -81 Very Low | ||
3096 | <= -71 Low | ||
3097 | <= -67 Good | ||
3098 | <= -57 Very Good | ||
3099 | > -57 Excellent | ||
3100 | ======================================================================== | ||
3101 | */ | ||
3102 | void RTMPSetSignalLED(struct rt_rtmp_adapter *pAd, IN NDIS_802_11_RSSI Dbm) | ||
3103 | { | ||
3104 | u8 nLed = 0; | ||
3105 | |||
3106 | if (pAd->LedCntl.field.LedMode == LED_MODE_SIGNAL_STREGTH) { | ||
3107 | if (Dbm <= -90) | ||
3108 | nLed = 0; | ||
3109 | else if (Dbm <= -81) | ||
3110 | nLed = 1; | ||
3111 | else if (Dbm <= -71) | ||
3112 | nLed = 3; | ||
3113 | else if (Dbm <= -67) | ||
3114 | nLed = 7; | ||
3115 | else if (Dbm <= -57) | ||
3116 | nLed = 15; | ||
3117 | else | ||
3118 | nLed = 31; | ||
3119 | |||
3120 | /* */ | ||
3121 | /* Update Signal Strength to firmware if changed. */ | ||
3122 | /* */ | ||
3123 | if (pAd->LedIndicatorStrength != nLed) { | ||
3124 | AsicSendCommandToMcu(pAd, 0x51, 0xff, nLed, | ||
3125 | pAd->LedCntl.field.Polarity); | ||
3126 | pAd->LedIndicatorStrength = nLed; | ||
3127 | } | ||
3128 | } | ||
3129 | } | ||
3130 | |||
3131 | /* | ||
3132 | ======================================================================== | ||
3133 | |||
3134 | Routine Description: | ||
3135 | Enable RX | ||
3136 | |||
3137 | Arguments: | ||
3138 | pAd Pointer to our adapter | ||
3139 | |||
3140 | Return Value: | ||
3141 | None | ||
3142 | |||
3143 | IRQL <= DISPATCH_LEVEL | ||
3144 | |||
3145 | Note: | ||
3146 | Before Enable RX, make sure you have enabled Interrupt. | ||
3147 | ======================================================================== | ||
3148 | */ | ||
3149 | void RTMPEnableRxTx(struct rt_rtmp_adapter *pAd) | ||
3150 | { | ||
3151 | /* WPDMA_GLO_CFG_STRUC GloCfg; */ | ||
3152 | /* unsigned long i = 0; */ | ||
3153 | u32 rx_filter_flag; | ||
3154 | |||
3155 | DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPEnableRxTx\n")); | ||
3156 | |||
3157 | /* Enable Rx DMA. */ | ||
3158 | RT28XXDMAEnable(pAd); | ||
3159 | |||
3160 | /* enable RX of MAC block */ | ||
3161 | if (pAd->OpMode == OPMODE_AP) { | ||
3162 | rx_filter_flag = APNORMAL; | ||
3163 | |||
3164 | RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, rx_filter_flag); /* enable RX of DMA block */ | ||
3165 | } else { | ||
3166 | if (pAd->CommonCfg.PSPXlink) | ||
3167 | rx_filter_flag = PSPXLINK; | ||
3168 | else | ||
3169 | rx_filter_flag = STANORMAL; /* Station not drop control frame will fail WiFi Certification. */ | ||
3170 | RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, rx_filter_flag); | ||
3171 | } | ||
3172 | |||
3173 | RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc); | ||
3174 | DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPEnableRxTx\n")); | ||
3175 | } | ||
3176 | |||
3177 | /*+++Add by shiang, move from os/linux/rt_main_dev.c */ | ||
3178 | void CfgInitHook(struct rt_rtmp_adapter *pAd) | ||
3179 | { | ||
3180 | pAd->bBroadComHT = TRUE; | ||
3181 | } | ||
3182 | |||
3183 | int rt28xx_init(struct rt_rtmp_adapter *pAd, | ||
3184 | char *pDefaultMac, char *pHostName) | ||
3185 | { | ||
3186 | u32 index; | ||
3187 | u8 TmpPhy; | ||
3188 | int Status; | ||
3189 | u32 MacCsr0 = 0; | ||
3190 | |||
3191 | #ifdef RTMP_MAC_PCI | ||
3192 | { | ||
3193 | /* If dirver doesn't wake up firmware here, */ | ||
3194 | /* NICLoadFirmware will hang forever when interface is up again. */ | ||
3195 | /* RT2860 PCI */ | ||
3196 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) && | ||
3197 | OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) { | ||
3198 | AUTO_WAKEUP_STRUC AutoWakeupCfg; | ||
3199 | AsicForceWakeup(pAd, TRUE); | ||
3200 | AutoWakeupCfg.word = 0; | ||
3201 | RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, | ||
3202 | AutoWakeupCfg.word); | ||
3203 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); | ||
3204 | } | ||
3205 | } | ||
3206 | #endif /* RTMP_MAC_PCI // */ | ||
3207 | |||
3208 | /* reset Adapter flags */ | ||
3209 | RTMP_CLEAR_FLAGS(pAd); | ||
3210 | |||
3211 | /* Init BssTab & ChannelInfo tabbles for auto channel select. */ | ||
3212 | |||
3213 | /* Allocate BA Reordering memory */ | ||
3214 | ba_reordering_resource_init(pAd, MAX_REORDERING_MPDU_NUM); | ||
3215 | |||
3216 | /* Make sure MAC gets ready. */ | ||
3217 | index = 0; | ||
3218 | do { | ||
3219 | RTMP_IO_READ32(pAd, MAC_CSR0, &MacCsr0); | ||
3220 | pAd->MACVersion = MacCsr0; | ||
3221 | |||
3222 | if ((pAd->MACVersion != 0x00) | ||
3223 | && (pAd->MACVersion != 0xFFFFFFFF)) | ||
3224 | break; | ||
3225 | |||
3226 | RTMPusecDelay(10); | ||
3227 | } while (index++ < 100); | ||
3228 | DBGPRINT(RT_DEBUG_TRACE, | ||
3229 | ("MAC_CSR0 [ Ver:Rev=0x%08x]\n", pAd->MACVersion)); | ||
3230 | |||
3231 | #ifdef RTMP_MAC_PCI | ||
3232 | #ifdef PCIE_PS_SUPPORT | ||
3233 | /*Iverson patch PCIE L1 issue to make sure that driver can be read,write ,BBP and RF register at pcie L.1 level */ | ||
3234 | if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) | ||
3235 | && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) { | ||
3236 | RTMP_IO_READ32(pAd, AUX_CTRL, &MacCsr0); | ||
3237 | MacCsr0 |= 0x402; | ||
3238 | RTMP_IO_WRITE32(pAd, AUX_CTRL, MacCsr0); | ||
3239 | DBGPRINT(RT_DEBUG_TRACE, ("AUX_CTRL = 0x%x\n", MacCsr0)); | ||
3240 | } | ||
3241 | #endif /* PCIE_PS_SUPPORT // */ | ||
3242 | |||
3243 | /* To fix driver disable/enable hang issue when radio off */ | ||
3244 | RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x2); | ||
3245 | #endif /* RTMP_MAC_PCI // */ | ||
3246 | |||
3247 | /* Disable DMA */ | ||
3248 | RT28XXDMADisable(pAd); | ||
3249 | |||
3250 | /* Load 8051 firmware */ | ||
3251 | Status = NICLoadFirmware(pAd); | ||
3252 | if (Status != NDIS_STATUS_SUCCESS) { | ||
3253 | DBGPRINT_ERR("NICLoadFirmware failed, Status[=0x%08x]\n", Status); | ||
3254 | goto err1; | ||
3255 | } | ||
3256 | |||
3257 | NICLoadRateSwitchingParams(pAd); | ||
3258 | |||
3259 | /* Disable interrupts here which is as soon as possible */ | ||
3260 | /* This statement should never be true. We might consider to remove it later */ | ||
3261 | #ifdef RTMP_MAC_PCI | ||
3262 | if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) { | ||
3263 | RTMP_ASIC_INTERRUPT_DISABLE(pAd); | ||
3264 | } | ||
3265 | #endif /* RTMP_MAC_PCI // */ | ||
3266 | |||
3267 | Status = RTMPAllocTxRxRingMemory(pAd); | ||
3268 | if (Status != NDIS_STATUS_SUCCESS) { | ||
3269 | DBGPRINT_ERR("RTMPAllocDMAMemory failed, Status[=0x%08x]\n", Status); | ||
3270 | goto err1; | ||
3271 | } | ||
3272 | |||
3273 | RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); | ||
3274 | |||
3275 | /* initialize MLME */ | ||
3276 | /* */ | ||
3277 | |||
3278 | Status = RtmpMgmtTaskInit(pAd); | ||
3279 | if (Status != NDIS_STATUS_SUCCESS) | ||
3280 | goto err2; | ||
3281 | |||
3282 | Status = MlmeInit(pAd); | ||
3283 | if (Status != NDIS_STATUS_SUCCESS) { | ||
3284 | DBGPRINT_ERR("MlmeInit failed, Status[=0x%08x]\n", Status); | ||
3285 | goto err2; | ||
3286 | } | ||
3287 | /* Initialize pAd->StaCfg, pAd->ApCfg, pAd->CommonCfg to manufacture default */ | ||
3288 | /* */ | ||
3289 | UserCfgInit(pAd); | ||
3290 | Status = RtmpNetTaskInit(pAd); | ||
3291 | if (Status != NDIS_STATUS_SUCCESS) | ||
3292 | goto err3; | ||
3293 | |||
3294 | /* COPY_MAC_ADDR(pAd->ApCfg.MBSSID[apidx].Bssid, netif->hwaddr); */ | ||
3295 | /* pAd->bForcePrintTX = TRUE; */ | ||
3296 | |||
3297 | CfgInitHook(pAd); | ||
3298 | |||
3299 | NdisAllocateSpinLock(&pAd->MacTabLock); | ||
3300 | |||
3301 | MeasureReqTabInit(pAd); | ||
3302 | TpcReqTabInit(pAd); | ||
3303 | |||
3304 | /* */ | ||
3305 | /* Init the hardware, we need to init asic before read registry, otherwise mac register will be reset */ | ||
3306 | /* */ | ||
3307 | Status = NICInitializeAdapter(pAd, TRUE); | ||
3308 | if (Status != NDIS_STATUS_SUCCESS) { | ||
3309 | DBGPRINT_ERR("NICInitializeAdapter failed, Status[=0x%08x]\n", Status); | ||
3310 | if (Status != NDIS_STATUS_SUCCESS) | ||
3311 | goto err3; | ||
3312 | } | ||
3313 | |||
3314 | DBGPRINT(RT_DEBUG_OFF, ("1. Phy Mode = %d\n", pAd->CommonCfg.PhyMode)); | ||
3315 | |||
3316 | #ifdef RTMP_MAC_USB | ||
3317 | pAd->CommonCfg.bMultipleIRP = FALSE; | ||
3318 | |||
3319 | if (pAd->CommonCfg.bMultipleIRP) | ||
3320 | pAd->CommonCfg.NumOfBulkInIRP = RX_RING_SIZE; | ||
3321 | else | ||
3322 | pAd->CommonCfg.NumOfBulkInIRP = 1; | ||
3323 | #endif /* RTMP_MAC_USB // */ | ||
3324 | |||
3325 | /*Init Ba Capability parameters. */ | ||
3326 | /* RT28XX_BA_INIT(pAd); */ | ||
3327 | pAd->CommonCfg.DesiredHtPhy.MpduDensity = | ||
3328 | (u8)pAd->CommonCfg.BACapability.field.MpduDensity; | ||
3329 | pAd->CommonCfg.DesiredHtPhy.AmsduEnable = | ||
3330 | (u16)pAd->CommonCfg.BACapability.field.AmsduEnable; | ||
3331 | pAd->CommonCfg.DesiredHtPhy.AmsduSize = | ||
3332 | (u16)pAd->CommonCfg.BACapability.field.AmsduSize; | ||
3333 | pAd->CommonCfg.DesiredHtPhy.MimoPs = | ||
3334 | (u16)pAd->CommonCfg.BACapability.field.MMPSmode; | ||
3335 | /* UPdata to HT IE */ | ||
3336 | pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs = | ||
3337 | (u16)pAd->CommonCfg.BACapability.field.MMPSmode; | ||
3338 | pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize = | ||
3339 | (u16)pAd->CommonCfg.BACapability.field.AmsduSize; | ||
3340 | pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity = | ||
3341 | (u8)pAd->CommonCfg.BACapability.field.MpduDensity; | ||
3342 | |||
3343 | /* after reading Registry, we now know if in AP mode or STA mode */ | ||
3344 | |||
3345 | /* Load 8051 firmware; crash when FW image not existent */ | ||
3346 | /* Status = NICLoadFirmware(pAd); */ | ||
3347 | /* if (Status != NDIS_STATUS_SUCCESS) */ | ||
3348 | /* break; */ | ||
3349 | |||
3350 | DBGPRINT(RT_DEBUG_OFF, ("2. Phy Mode = %d\n", pAd->CommonCfg.PhyMode)); | ||
3351 | |||
3352 | /* We should read EEPROM for all cases. rt2860b */ | ||
3353 | NICReadEEPROMParameters(pAd, (u8 *)pDefaultMac); | ||
3354 | |||
3355 | DBGPRINT(RT_DEBUG_OFF, ("3. Phy Mode = %d\n", pAd->CommonCfg.PhyMode)); | ||
3356 | |||
3357 | NICInitAsicFromEEPROM(pAd); /*rt2860b */ | ||
3358 | |||
3359 | /* Set PHY to appropriate mode */ | ||
3360 | TmpPhy = pAd->CommonCfg.PhyMode; | ||
3361 | pAd->CommonCfg.PhyMode = 0xff; | ||
3362 | RTMPSetPhyMode(pAd, TmpPhy); | ||
3363 | SetCommonHT(pAd); | ||
3364 | |||
3365 | /* No valid channels. */ | ||
3366 | if (pAd->ChannelListNum == 0) { | ||
3367 | DBGPRINT(RT_DEBUG_ERROR, | ||
3368 | ("Wrong configuration. No valid channel found. Check \"ContryCode\" and \"ChannelGeography\" setting.\n")); | ||
3369 | goto err4; | ||
3370 | } | ||
3371 | |||
3372 | DBGPRINT(RT_DEBUG_OFF, | ||
3373 | ("MCS Set = %02x %02x %02x %02x %02x\n", | ||
3374 | pAd->CommonCfg.HtCapability.MCSSet[0], | ||
3375 | pAd->CommonCfg.HtCapability.MCSSet[1], | ||
3376 | pAd->CommonCfg.HtCapability.MCSSet[2], | ||
3377 | pAd->CommonCfg.HtCapability.MCSSet[3], | ||
3378 | pAd->CommonCfg.HtCapability.MCSSet[4])); | ||
3379 | |||
3380 | #ifdef RTMP_RF_RW_SUPPORT | ||
3381 | /*Init RT30xx RFRegisters after read RFIC type from EEPROM */ | ||
3382 | NICInitRFRegisters(pAd); | ||
3383 | #endif /* RTMP_RF_RW_SUPPORT // */ | ||
3384 | |||
3385 | /* APInitialize(pAd); */ | ||
3386 | |||
3387 | /* */ | ||
3388 | /* Initialize RF register to default value */ | ||
3389 | /* */ | ||
3390 | AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); | ||
3391 | AsicLockChannel(pAd, pAd->CommonCfg.Channel); | ||
3392 | |||
3393 | /* 8051 firmware require the signal during booting time. */ | ||
3394 | /*2008/11/28:KH marked the following codes to patch Frequency offset bug */ | ||
3395 | /*AsicSendCommandToMcu(pAd, 0x72, 0xFF, 0x00, 0x00); */ | ||
3396 | |||
3397 | if (pAd && (Status != NDIS_STATUS_SUCCESS)) { | ||
3398 | /* */ | ||
3399 | /* Undo everything if it failed */ | ||
3400 | /* */ | ||
3401 | if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { | ||
3402 | /* NdisMDeregisterInterrupt(&pAd->Interrupt); */ | ||
3403 | RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); | ||
3404 | } | ||
3405 | /* RTMPFreeAdapter(pAd); // we will free it in disconnect() */ | ||
3406 | } else if (pAd) { | ||
3407 | /* Microsoft HCT require driver send a disconnect event after driver initialization. */ | ||
3408 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); | ||
3409 | /* pAd->IndicateMediaState = NdisMediaStateDisconnected; */ | ||
3410 | RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE); | ||
3411 | |||
3412 | DBGPRINT(RT_DEBUG_TRACE, | ||
3413 | ("NDIS_STATUS_MEDIA_DISCONNECT Event B!\n")); | ||
3414 | |||
3415 | #ifdef RTMP_MAC_USB | ||
3416 | RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS); | ||
3417 | RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS); | ||
3418 | |||
3419 | /* */ | ||
3420 | /* Support multiple BulkIn IRP, */ | ||
3421 | /* the value on pAd->CommonCfg.NumOfBulkInIRP may be large than 1. */ | ||
3422 | /* */ | ||
3423 | for (index = 0; index < pAd->CommonCfg.NumOfBulkInIRP; index++) { | ||
3424 | RTUSBBulkReceive(pAd); | ||
3425 | DBGPRINT(RT_DEBUG_TRACE, ("RTUSBBulkReceive!\n")); | ||
3426 | } | ||
3427 | #endif /* RTMP_MAC_USB // */ | ||
3428 | } /* end of else */ | ||
3429 | |||
3430 | /* Set up the Mac address */ | ||
3431 | RtmpOSNetDevAddrSet(pAd->net_dev, &pAd->CurrentAddress[0]); | ||
3432 | |||
3433 | DBGPRINT_S(Status, ("<==== rt28xx_init, Status=%x\n", Status)); | ||
3434 | |||
3435 | return TRUE; | ||
3436 | |||
3437 | err4: | ||
3438 | err3: | ||
3439 | MlmeHalt(pAd); | ||
3440 | err2: | ||
3441 | RTMPFreeTxRxRingMemory(pAd); | ||
3442 | err1: | ||
3443 | |||
3444 | os_free_mem(pAd, pAd->mpdu_blk_pool.mem); /* free BA pool */ | ||
3445 | |||
3446 | /* shall not set priv to NULL here because the priv didn't been free yet. */ | ||
3447 | /*net_dev->ml_priv = 0; */ | ||
3448 | #ifdef ST | ||
3449 | err0: | ||
3450 | #endif /* ST // */ | ||
3451 | |||
3452 | DBGPRINT(RT_DEBUG_ERROR, ("rt28xx Initialized fail!\n")); | ||
3453 | return FALSE; | ||
3454 | } | ||
3455 | |||
3456 | /*---Add by shiang, move from os/linux/rt_main_dev.c */ | ||
3457 | |||
3458 | static int RtmpChipOpsRegister(struct rt_rtmp_adapter *pAd, int infType) | ||
3459 | { | ||
3460 | struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps; | ||
3461 | int status; | ||
3462 | |||
3463 | memset(pChipOps, 0, sizeof(struct rt_rtmp_chip_op)); | ||
3464 | |||
3465 | /* set eeprom related hook functions */ | ||
3466 | status = RtmpChipOpsEepromHook(pAd, infType); | ||
3467 | |||
3468 | /* set mcu related hook functions */ | ||
3469 | switch (infType) { | ||
3470 | #ifdef RTMP_PCI_SUPPORT | ||
3471 | case RTMP_DEV_INF_PCI: | ||
3472 | pChipOps->loadFirmware = RtmpAsicLoadFirmware; | ||
3473 | pChipOps->eraseFirmware = RtmpAsicEraseFirmware; | ||
3474 | pChipOps->sendCommandToMcu = RtmpAsicSendCommandToMcu; | ||
3475 | break; | ||
3476 | #endif /* RTMP_PCI_SUPPORT // */ | ||
3477 | #ifdef RTMP_USB_SUPPORT | ||
3478 | case RTMP_DEV_INF_USB: | ||
3479 | pChipOps->loadFirmware = RtmpAsicLoadFirmware; | ||
3480 | pChipOps->sendCommandToMcu = RtmpAsicSendCommandToMcu; | ||
3481 | break; | ||
3482 | #endif /* RTMP_USB_SUPPORT // */ | ||
3483 | default: | ||
3484 | break; | ||
3485 | } | ||
3486 | |||
3487 | return status; | ||
3488 | } | ||
3489 | |||
3490 | int RtmpRaDevCtrlInit(struct rt_rtmp_adapter *pAd, IN RTMP_INF_TYPE infType) | ||
3491 | { | ||
3492 | /*void *handle; */ | ||
3493 | |||
3494 | /* Assign the interface type. We need use it when do register/EEPROM access. */ | ||
3495 | pAd->infType = infType; | ||
3496 | |||
3497 | pAd->OpMode = OPMODE_STA; | ||
3498 | DBGPRINT(RT_DEBUG_TRACE, | ||
3499 | ("STA Driver version-%s\n", STA_DRIVER_VERSION)); | ||
3500 | |||
3501 | #ifdef RTMP_MAC_USB | ||
3502 | sema_init(&(pAd->UsbVendorReq_semaphore), 1); | ||
3503 | os_alloc_mem(pAd, (u8 **) & pAd->UsbVendorReqBuf, | ||
3504 | MAX_PARAM_BUFFER_SIZE - 1); | ||
3505 | if (pAd->UsbVendorReqBuf == NULL) { | ||
3506 | DBGPRINT(RT_DEBUG_ERROR, | ||
3507 | ("Allocate vendor request temp buffer failed!\n")); | ||
3508 | return FALSE; | ||
3509 | } | ||
3510 | #endif /* RTMP_MAC_USB // */ | ||
3511 | |||
3512 | RtmpChipOpsRegister(pAd, infType); | ||
3513 | |||
3514 | return 0; | ||
3515 | } | ||
3516 | |||
3517 | BOOLEAN RtmpRaDevCtrlExit(struct rt_rtmp_adapter *pAd) | ||
3518 | { | ||
3519 | |||
3520 | RTMPFreeAdapter(pAd); | ||
3521 | |||
3522 | return TRUE; | ||
3523 | } | ||
3524 | |||
3525 | /* not yet support MBSS */ | ||
3526 | struct net_device *get_netdev_from_bssid(struct rt_rtmp_adapter *pAd, u8 FromWhichBSSID) | ||
3527 | { | ||
3528 | struct net_device *dev_p = NULL; | ||
3529 | |||
3530 | { | ||
3531 | dev_p = pAd->net_dev; | ||
3532 | } | ||
3533 | |||
3534 | ASSERT(dev_p); | ||
3535 | return dev_p; /* return one of MBSS */ | ||
3536 | } | ||
diff --git a/drivers/staging/rt2860/common/rtmp_mcu.c b/drivers/staging/rt2860/common/rtmp_mcu.c deleted file mode 100644 index 80fa4160ed6..00000000000 --- a/drivers/staging/rt2860/common/rtmp_mcu.c +++ /dev/null | |||
@@ -1,336 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | |||
27 | Module Name: | ||
28 | rtmp_mcu.c | ||
29 | |||
30 | Abstract: | ||
31 | Miniport generic portion header file | ||
32 | |||
33 | Revision History: | ||
34 | Who When What | ||
35 | -------- ---------- ---------------------------------------------- | ||
36 | */ | ||
37 | |||
38 | #include "../rt_config.h" | ||
39 | |||
40 | #include <linux/crc-ccitt.h> | ||
41 | #include <linux/firmware.h> | ||
42 | |||
43 | #ifdef RTMP_MAC_USB | ||
44 | |||
45 | #define FIRMWAREIMAGE_LENGTH 0x1000 | ||
46 | |||
47 | #define FIRMWARE_2870_MIN_VERSION 12 | ||
48 | #define FIRMWARE_2870_FILENAME "rt2870.bin" | ||
49 | MODULE_FIRMWARE(FIRMWARE_2870_FILENAME); | ||
50 | |||
51 | #define FIRMWARE_3070_MIN_VERSION 17 | ||
52 | #define FIRMWARE_3070_FILENAME "rt3070.bin" | ||
53 | MODULE_FIRMWARE(FIRMWARE_3070_FILENAME); | ||
54 | |||
55 | #define FIRMWARE_3071_MIN_VERSION 17 | ||
56 | #define FIRMWARE_3071_FILENAME "rt3071.bin" /* for RT3071/RT3072 */ | ||
57 | MODULE_FIRMWARE(FIRMWARE_3071_FILENAME); | ||
58 | |||
59 | #else /* RTMP_MAC_PCI */ | ||
60 | |||
61 | #define FIRMWAREIMAGE_LENGTH 0x2000 | ||
62 | |||
63 | #define FIRMWARE_2860_MIN_VERSION 11 | ||
64 | #define FIRMWARE_2860_FILENAME "rt2860.bin" | ||
65 | MODULE_FIRMWARE(FIRMWARE_2860_FILENAME); | ||
66 | |||
67 | #define FIRMWARE_3090_MIN_VERSION 19 | ||
68 | #define FIRMWARE_3090_FILENAME "rt3090.bin" /* for RT3090/RT3390 */ | ||
69 | MODULE_FIRMWARE(FIRMWARE_3090_FILENAME); | ||
70 | |||
71 | #endif | ||
72 | |||
73 | /* | ||
74 | ======================================================================== | ||
75 | |||
76 | Routine Description: | ||
77 | erase 8051 firmware image in MAC ASIC | ||
78 | |||
79 | Arguments: | ||
80 | Adapter Pointer to our adapter | ||
81 | |||
82 | IRQL = PASSIVE_LEVEL | ||
83 | |||
84 | ======================================================================== | ||
85 | */ | ||
86 | int RtmpAsicEraseFirmware(struct rt_rtmp_adapter *pAd) | ||
87 | { | ||
88 | unsigned long i; | ||
89 | |||
90 | for (i = 0; i < MAX_FIRMWARE_IMAGE_SIZE; i += 4) | ||
91 | RTMP_IO_WRITE32(pAd, FIRMWARE_IMAGE_BASE + i, 0); | ||
92 | |||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | static const struct firmware *rtmp_get_firmware(struct rt_rtmp_adapter *adapter) | ||
97 | { | ||
98 | const char *name; | ||
99 | const struct firmware *fw = NULL; | ||
100 | u8 min_version; | ||
101 | struct device *dev; | ||
102 | int err; | ||
103 | |||
104 | if (adapter->firmware) | ||
105 | return adapter->firmware; | ||
106 | |||
107 | #ifdef RTMP_MAC_USB | ||
108 | if (IS_RT3071(adapter)) { | ||
109 | name = FIRMWARE_3071_FILENAME; | ||
110 | min_version = FIRMWARE_3071_MIN_VERSION; | ||
111 | } else if (IS_RT3070(adapter)) { | ||
112 | name = FIRMWARE_3070_FILENAME; | ||
113 | min_version = FIRMWARE_3070_MIN_VERSION; | ||
114 | } else { | ||
115 | name = FIRMWARE_2870_FILENAME; | ||
116 | min_version = FIRMWARE_2870_MIN_VERSION; | ||
117 | } | ||
118 | dev = &((struct os_cookie *)adapter->OS_Cookie)->pUsb_Dev->dev; | ||
119 | #else /* RTMP_MAC_PCI */ | ||
120 | if (IS_RT3090(adapter) || IS_RT3390(adapter)) { | ||
121 | name = FIRMWARE_3090_FILENAME; | ||
122 | min_version = FIRMWARE_3090_MIN_VERSION; | ||
123 | } else { | ||
124 | name = FIRMWARE_2860_FILENAME; | ||
125 | min_version = FIRMWARE_2860_MIN_VERSION; | ||
126 | } | ||
127 | dev = &((struct os_cookie *)adapter->OS_Cookie)->pci_dev->dev; | ||
128 | #endif | ||
129 | |||
130 | err = request_firmware(&fw, name, dev); | ||
131 | if (err) { | ||
132 | dev_err(dev, "firmware file %s request failed (%d)\n", | ||
133 | name, err); | ||
134 | return NULL; | ||
135 | } | ||
136 | |||
137 | if (fw->size < FIRMWAREIMAGE_LENGTH) { | ||
138 | dev_err(dev, "firmware file %s size is invalid\n", name); | ||
139 | goto invalid; | ||
140 | } | ||
141 | |||
142 | /* is it new enough? */ | ||
143 | adapter->FirmwareVersion = fw->data[FIRMWAREIMAGE_LENGTH - 3]; | ||
144 | if (adapter->FirmwareVersion < min_version) { | ||
145 | dev_err(dev, | ||
146 | "firmware file %s is too old;" | ||
147 | " driver requires v%d or later\n", | ||
148 | name, min_version); | ||
149 | goto invalid; | ||
150 | } | ||
151 | |||
152 | /* is the internal CRC correct? */ | ||
153 | if (crc_ccitt(0xffff, fw->data, FIRMWAREIMAGE_LENGTH - 2) != | ||
154 | (fw->data[FIRMWAREIMAGE_LENGTH - 2] | | ||
155 | (fw->data[FIRMWAREIMAGE_LENGTH - 1] << 8))) { | ||
156 | dev_err(dev, "firmware file %s failed internal CRC\n", name); | ||
157 | goto invalid; | ||
158 | } | ||
159 | |||
160 | adapter->firmware = fw; | ||
161 | return fw; | ||
162 | |||
163 | invalid: | ||
164 | release_firmware(fw); | ||
165 | return NULL; | ||
166 | } | ||
167 | |||
168 | /* | ||
169 | ======================================================================== | ||
170 | |||
171 | Routine Description: | ||
172 | Load 8051 firmware file into MAC ASIC | ||
173 | |||
174 | Arguments: | ||
175 | Adapter Pointer to our adapter | ||
176 | |||
177 | Return Value: | ||
178 | NDIS_STATUS_SUCCESS firmware image load ok | ||
179 | NDIS_STATUS_FAILURE image not found | ||
180 | |||
181 | IRQL = PASSIVE_LEVEL | ||
182 | |||
183 | ======================================================================== | ||
184 | */ | ||
185 | int RtmpAsicLoadFirmware(struct rt_rtmp_adapter *pAd) | ||
186 | { | ||
187 | const struct firmware *fw; | ||
188 | int Status = NDIS_STATUS_SUCCESS; | ||
189 | unsigned long Index; | ||
190 | u32 MacReg = 0; | ||
191 | |||
192 | fw = rtmp_get_firmware(pAd); | ||
193 | if (!fw) | ||
194 | return NDIS_STATUS_FAILURE; | ||
195 | |||
196 | RTMP_WRITE_FIRMWARE(pAd, fw->data, FIRMWAREIMAGE_LENGTH); | ||
197 | |||
198 | /* check if MCU is ready */ | ||
199 | Index = 0; | ||
200 | do { | ||
201 | RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &MacReg); | ||
202 | |||
203 | if (MacReg & 0x80) | ||
204 | break; | ||
205 | |||
206 | RTMPusecDelay(1000); | ||
207 | } while (Index++ < 1000); | ||
208 | |||
209 | if (Index > 1000) { | ||
210 | DBGPRINT(RT_DEBUG_ERROR, | ||
211 | ("NICLoadFirmware: MCU is not ready\n")); | ||
212 | Status = NDIS_STATUS_FAILURE; | ||
213 | } | ||
214 | |||
215 | DBGPRINT(RT_DEBUG_TRACE, ("<=== %s (status=%d)\n", __func__, Status)); | ||
216 | |||
217 | return Status; | ||
218 | } | ||
219 | |||
220 | int RtmpAsicSendCommandToMcu(struct rt_rtmp_adapter *pAd, | ||
221 | u8 Command, | ||
222 | u8 Token, u8 Arg0, u8 Arg1) | ||
223 | { | ||
224 | HOST_CMD_CSR_STRUC H2MCmd; | ||
225 | H2M_MAILBOX_STRUC H2MMailbox; | ||
226 | unsigned long i = 0; | ||
227 | |||
228 | #ifdef PCIE_PS_SUPPORT | ||
229 | /* 3090F power solution 3 has hw limitation that needs to ban all mcu command */ | ||
230 | /* when firmware is in radio state. For other chip doesn't have this limitation. */ | ||
231 | if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) | ||
232 | && IS_VERSION_AFTER_F(pAd)) && IS_VERSION_AFTER_F(pAd) | ||
233 | && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) | ||
234 | && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) { | ||
235 | RTMP_SEM_LOCK(&pAd->McuCmdLock); | ||
236 | if ((pAd->brt30xxBanMcuCmd == TRUE) | ||
237 | && (Command != WAKE_MCU_CMD) && (Command != RFOFF_MCU_CMD)) { | ||
238 | RTMP_SEM_UNLOCK(&pAd->McuCmdLock); | ||
239 | DBGPRINT(RT_DEBUG_TRACE, | ||
240 | (" Ban Mcu Cmd %x in sleep mode\n", Command)); | ||
241 | return FALSE; | ||
242 | } else if ((Command == SLEEP_MCU_CMD) | ||
243 | || (Command == RFOFF_MCU_CMD)) { | ||
244 | pAd->brt30xxBanMcuCmd = TRUE; | ||
245 | } else if (Command != WAKE_MCU_CMD) { | ||
246 | pAd->brt30xxBanMcuCmd = FALSE; | ||
247 | } | ||
248 | |||
249 | RTMP_SEM_UNLOCK(&pAd->McuCmdLock); | ||
250 | |||
251 | } | ||
252 | if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) | ||
253 | && IS_VERSION_AFTER_F(pAd)) && IS_VERSION_AFTER_F(pAd) | ||
254 | && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) | ||
255 | && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) | ||
256 | && (Command == WAKE_MCU_CMD)) { | ||
257 | |||
258 | do { | ||
259 | RTMP_IO_FORCE_READ32(pAd, H2M_MAILBOX_CSR, | ||
260 | &H2MMailbox.word); | ||
261 | if (H2MMailbox.field.Owner == 0) | ||
262 | break; | ||
263 | |||
264 | RTMPusecDelay(2); | ||
265 | DBGPRINT(RT_DEBUG_INFO, | ||
266 | ("AsicSendCommanToMcu::Mail box is busy\n")); | ||
267 | } while (i++ < 100); | ||
268 | |||
269 | if (i > 100) { | ||
270 | DBGPRINT_ERR("H2M_MAILBOX still hold by MCU. command fail\n"); | ||
271 | return FALSE; | ||
272 | } | ||
273 | |||
274 | H2MMailbox.field.Owner = 1; /* pass ownership to MCU */ | ||
275 | H2MMailbox.field.CmdToken = Token; | ||
276 | H2MMailbox.field.HighByte = Arg1; | ||
277 | H2MMailbox.field.LowByte = Arg0; | ||
278 | RTMP_IO_FORCE_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word); | ||
279 | |||
280 | H2MCmd.word = 0; | ||
281 | H2MCmd.field.HostCommand = Command; | ||
282 | RTMP_IO_FORCE_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word); | ||
283 | |||
284 | } else | ||
285 | #endif /* PCIE_PS_SUPPORT // */ | ||
286 | { | ||
287 | do { | ||
288 | RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word); | ||
289 | if (H2MMailbox.field.Owner == 0) | ||
290 | break; | ||
291 | |||
292 | RTMPusecDelay(2); | ||
293 | } while (i++ < 100); | ||
294 | |||
295 | if (i > 100) { | ||
296 | #ifdef RTMP_MAC_PCI | ||
297 | #endif /* RTMP_MAC_PCI // */ | ||
298 | { | ||
299 | DBGPRINT_ERR("H2M_MAILBOX still hold by MCU. command fail\n"); | ||
300 | } | ||
301 | return FALSE; | ||
302 | } | ||
303 | #ifdef RTMP_MAC_PCI | ||
304 | #endif /* RTMP_MAC_PCI // */ | ||
305 | |||
306 | H2MMailbox.field.Owner = 1; /* pass ownership to MCU */ | ||
307 | H2MMailbox.field.CmdToken = Token; | ||
308 | H2MMailbox.field.HighByte = Arg1; | ||
309 | H2MMailbox.field.LowByte = Arg0; | ||
310 | RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word); | ||
311 | |||
312 | H2MCmd.word = 0; | ||
313 | H2MCmd.field.HostCommand = Command; | ||
314 | RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word); | ||
315 | |||
316 | if (Command != 0x80) { | ||
317 | } | ||
318 | } | ||
319 | #ifdef PCIE_PS_SUPPORT | ||
320 | /* 3090 MCU Wakeup command needs more time to be stable. */ | ||
321 | /* Before stable, don't issue other MCU command to prevent from firmware error. */ | ||
322 | if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) | ||
323 | && IS_VERSION_AFTER_F(pAd)) && IS_VERSION_AFTER_F(pAd) | ||
324 | && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3) | ||
325 | && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE) | ||
326 | && (Command == WAKE_MCU_CMD)) { | ||
327 | RTMPusecDelay(2000); | ||
328 | /*Put this is after RF programming. */ | ||
329 | /*NdisAcquireSpinLock(&pAd->McuCmdLock); */ | ||
330 | /*pAd->brt30xxBanMcuCmd = FALSE; */ | ||
331 | /*NdisReleaseSpinLock(&pAd->McuCmdLock); */ | ||
332 | } | ||
333 | #endif /* PCIE_PS_SUPPORT // */ | ||
334 | |||
335 | return TRUE; | ||
336 | } | ||
diff --git a/drivers/staging/rt2860/common/rtmp_timer.c b/drivers/staging/rt2860/common/rtmp_timer.c deleted file mode 100644 index ab520909490..00000000000 --- a/drivers/staging/rt2860/common/rtmp_timer.c +++ /dev/null | |||
@@ -1,302 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | |||
27 | Module Name: | ||
28 | rtmp_timer.c | ||
29 | |||
30 | Abstract: | ||
31 | task for timer handling | ||
32 | |||
33 | Revision History: | ||
34 | Who When What | ||
35 | -------- ---------- ---------------------------------------------- | ||
36 | Name Date Modification logs | ||
37 | Shiang Tu 08-28-2008 init version | ||
38 | |||
39 | */ | ||
40 | |||
41 | #include "../rt_config.h" | ||
42 | |||
43 | BUILD_TIMER_FUNCTION(MlmePeriodicExec); | ||
44 | /*BUILD_TIMER_FUNCTION(MlmeRssiReportExec); */ | ||
45 | BUILD_TIMER_FUNCTION(AsicRxAntEvalTimeout); | ||
46 | BUILD_TIMER_FUNCTION(APSDPeriodicExec); | ||
47 | BUILD_TIMER_FUNCTION(AsicRfTuningExec); | ||
48 | #ifdef RTMP_MAC_USB | ||
49 | BUILD_TIMER_FUNCTION(BeaconUpdateExec); | ||
50 | #endif /* RTMP_MAC_USB // */ | ||
51 | |||
52 | BUILD_TIMER_FUNCTION(BeaconTimeout); | ||
53 | BUILD_TIMER_FUNCTION(ScanTimeout); | ||
54 | BUILD_TIMER_FUNCTION(AuthTimeout); | ||
55 | BUILD_TIMER_FUNCTION(AssocTimeout); | ||
56 | BUILD_TIMER_FUNCTION(ReassocTimeout); | ||
57 | BUILD_TIMER_FUNCTION(DisassocTimeout); | ||
58 | BUILD_TIMER_FUNCTION(LinkDownExec); | ||
59 | BUILD_TIMER_FUNCTION(StaQuickResponeForRateUpExec); | ||
60 | BUILD_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc); | ||
61 | #ifdef RTMP_MAC_PCI | ||
62 | BUILD_TIMER_FUNCTION(PsPollWakeExec); | ||
63 | BUILD_TIMER_FUNCTION(RadioOnExec); | ||
64 | #endif /* RTMP_MAC_PCI // */ | ||
65 | #ifdef RTMP_MAC_USB | ||
66 | BUILD_TIMER_FUNCTION(RtmpUsbStaAsicForceWakeupTimeout); | ||
67 | #endif /* RTMP_MAC_USB // */ | ||
68 | |||
69 | #if defined(AP_LED) || defined(STA_LED) | ||
70 | extern void LedCtrlMain(void *SystemSpecific1, | ||
71 | void *FunctionContext, | ||
72 | void *SystemSpecific2, void *SystemSpecific3); | ||
73 | BUILD_TIMER_FUNCTION(LedCtrlMain); | ||
74 | #endif | ||
75 | |||
76 | #ifdef RTMP_TIMER_TASK_SUPPORT | ||
77 | static void RtmpTimerQHandle(struct rt_rtmp_adapter *pAd) | ||
78 | { | ||
79 | #ifndef KTHREAD_SUPPORT | ||
80 | int status; | ||
81 | #endif | ||
82 | struct rt_ralink_timer *pTimer; | ||
83 | struct rt_rtmp_timer_task_entry *pEntry; | ||
84 | unsigned long irqFlag; | ||
85 | struct rt_rtmp_os_task *pTask; | ||
86 | |||
87 | pTask = &pAd->timerTask; | ||
88 | while (!pTask->task_killed) { | ||
89 | pTimer = NULL; | ||
90 | |||
91 | #ifdef KTHREAD_SUPPORT | ||
92 | RTMP_WAIT_EVENT_INTERRUPTIBLE(pAd, pTask); | ||
93 | #else | ||
94 | RTMP_SEM_EVENT_WAIT(&(pTask->taskSema), status); | ||
95 | #endif | ||
96 | |||
97 | if (pAd->TimerQ.status == RTMP_TASK_STAT_STOPED) | ||
98 | break; | ||
99 | |||
100 | /* event happened. */ | ||
101 | while (pAd->TimerQ.pQHead) { | ||
102 | RTMP_INT_LOCK(&pAd->TimerQLock, irqFlag); | ||
103 | pEntry = pAd->TimerQ.pQHead; | ||
104 | if (pEntry) { | ||
105 | pTimer = pEntry->pRaTimer; | ||
106 | |||
107 | /* update pQHead */ | ||
108 | pAd->TimerQ.pQHead = pEntry->pNext; | ||
109 | if (pEntry == pAd->TimerQ.pQTail) | ||
110 | pAd->TimerQ.pQTail = NULL; | ||
111 | |||
112 | /* return this queue entry to timerQFreeList. */ | ||
113 | pEntry->pNext = pAd->TimerQ.pQPollFreeList; | ||
114 | pAd->TimerQ.pQPollFreeList = pEntry; | ||
115 | } | ||
116 | RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlag); | ||
117 | |||
118 | if (pTimer) { | ||
119 | if ((pTimer->handle != NULL) | ||
120 | && (!pAd->PM_FlgSuspend)) | ||
121 | pTimer->handle(NULL, | ||
122 | (void *)pTimer->cookie, | ||
123 | NULL, pTimer); | ||
124 | if ((pTimer->Repeat) | ||
125 | && (pTimer->State == FALSE)) | ||
126 | RTMP_OS_Add_Timer(&pTimer->TimerObj, | ||
127 | pTimer->TimerValue); | ||
128 | } | ||
129 | } | ||
130 | |||
131 | #ifndef KTHREAD_SUPPORT | ||
132 | if (status != 0) { | ||
133 | pAd->TimerQ.status = RTMP_TASK_STAT_STOPED; | ||
134 | RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); | ||
135 | break; | ||
136 | } | ||
137 | #endif | ||
138 | } | ||
139 | } | ||
140 | |||
141 | int RtmpTimerQThread(IN void *Context) | ||
142 | { | ||
143 | struct rt_rtmp_os_task *pTask; | ||
144 | struct rt_rtmp_adapter *pAd; | ||
145 | |||
146 | pTask = Context; | ||
147 | pAd = pTask->priv; | ||
148 | |||
149 | RtmpOSTaskCustomize(pTask); | ||
150 | |||
151 | RtmpTimerQHandle(pAd); | ||
152 | |||
153 | DBGPRINT(RT_DEBUG_TRACE, ("<---%s\n", __func__)); | ||
154 | #ifndef KTHREAD_SUPPORT | ||
155 | pTask->taskPID = THREAD_PID_INIT_VALUE; | ||
156 | #endif | ||
157 | /* notify the exit routine that we're actually exiting now | ||
158 | * | ||
159 | * complete()/wait_for_completion() is similar to up()/down(), | ||
160 | * except that complete() is safe in the case where the structure | ||
161 | * is getting deleted in a parallel mode of execution (i.e. just | ||
162 | * after the down() -- that's necessary for the thread-shutdown | ||
163 | * case. | ||
164 | * | ||
165 | * complete_and_exit() goes even further than this -- it is safe in | ||
166 | * the case that the thread of the caller is going away (not just | ||
167 | * the structure) -- this is necessary for the module-remove case. | ||
168 | * This is important in preemption kernels, which transfer the flow | ||
169 | * of execution immediately upon a complete(). | ||
170 | */ | ||
171 | RtmpOSTaskNotifyToExit(pTask); | ||
172 | |||
173 | return 0; | ||
174 | |||
175 | } | ||
176 | |||
177 | struct rt_rtmp_timer_task_entry *RtmpTimerQInsert(struct rt_rtmp_adapter *pAd, | ||
178 | struct rt_ralink_timer *pTimer) | ||
179 | { | ||
180 | struct rt_rtmp_timer_task_entry *pQNode = NULL, *pQTail; | ||
181 | unsigned long irqFlags; | ||
182 | struct rt_rtmp_os_task *pTask = &pAd->timerTask; | ||
183 | |||
184 | RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags); | ||
185 | if (pAd->TimerQ.status & RTMP_TASK_CAN_DO_INSERT) { | ||
186 | if (pAd->TimerQ.pQPollFreeList) { | ||
187 | pQNode = pAd->TimerQ.pQPollFreeList; | ||
188 | pAd->TimerQ.pQPollFreeList = pQNode->pNext; | ||
189 | |||
190 | pQNode->pRaTimer = pTimer; | ||
191 | pQNode->pNext = NULL; | ||
192 | |||
193 | pQTail = pAd->TimerQ.pQTail; | ||
194 | if (pAd->TimerQ.pQTail != NULL) | ||
195 | pQTail->pNext = pQNode; | ||
196 | pAd->TimerQ.pQTail = pQNode; | ||
197 | if (pAd->TimerQ.pQHead == NULL) | ||
198 | pAd->TimerQ.pQHead = pQNode; | ||
199 | } | ||
200 | } | ||
201 | RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags); | ||
202 | |||
203 | if (pQNode) { | ||
204 | #ifdef KTHREAD_SUPPORT | ||
205 | WAKE_UP(pTask); | ||
206 | #else | ||
207 | RTMP_SEM_EVENT_UP(&pTask->taskSema); | ||
208 | #endif | ||
209 | } | ||
210 | |||
211 | return pQNode; | ||
212 | } | ||
213 | |||
214 | BOOLEAN RtmpTimerQRemove(struct rt_rtmp_adapter *pAd, struct rt_ralink_timer *pTimer) | ||
215 | { | ||
216 | struct rt_rtmp_timer_task_entry *pNode, *pPrev = NULL; | ||
217 | unsigned long irqFlags; | ||
218 | |||
219 | RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags); | ||
220 | if (pAd->TimerQ.status >= RTMP_TASK_STAT_INITED) { | ||
221 | pNode = pAd->TimerQ.pQHead; | ||
222 | while (pNode) { | ||
223 | if (pNode->pRaTimer == pTimer) | ||
224 | break; | ||
225 | pPrev = pNode; | ||
226 | pNode = pNode->pNext; | ||
227 | } | ||
228 | |||
229 | /* Now move it to freeList queue. */ | ||
230 | if (pNode) { | ||
231 | if (pNode == pAd->TimerQ.pQHead) | ||
232 | pAd->TimerQ.pQHead = pNode->pNext; | ||
233 | if (pNode == pAd->TimerQ.pQTail) | ||
234 | pAd->TimerQ.pQTail = pPrev; | ||
235 | if (pPrev != NULL) | ||
236 | pPrev->pNext = pNode->pNext; | ||
237 | |||
238 | /* return this queue entry to timerQFreeList. */ | ||
239 | pNode->pNext = pAd->TimerQ.pQPollFreeList; | ||
240 | pAd->TimerQ.pQPollFreeList = pNode; | ||
241 | } | ||
242 | } | ||
243 | RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags); | ||
244 | |||
245 | return TRUE; | ||
246 | } | ||
247 | |||
248 | void RtmpTimerQExit(struct rt_rtmp_adapter *pAd) | ||
249 | { | ||
250 | struct rt_rtmp_timer_task_entry *pTimerQ; | ||
251 | unsigned long irqFlags; | ||
252 | |||
253 | RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags); | ||
254 | while (pAd->TimerQ.pQHead) { | ||
255 | pTimerQ = pAd->TimerQ.pQHead; | ||
256 | pAd->TimerQ.pQHead = pTimerQ->pNext; | ||
257 | /* remove the timeQ */ | ||
258 | } | ||
259 | pAd->TimerQ.pQPollFreeList = NULL; | ||
260 | os_free_mem(pAd, pAd->TimerQ.pTimerQPoll); | ||
261 | pAd->TimerQ.pQTail = NULL; | ||
262 | pAd->TimerQ.pQHead = NULL; | ||
263 | #ifndef KTHREAD_SUPPORT | ||
264 | pAd->TimerQ.status = RTMP_TASK_STAT_STOPED; | ||
265 | #endif | ||
266 | RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags); | ||
267 | |||
268 | } | ||
269 | |||
270 | void RtmpTimerQInit(struct rt_rtmp_adapter *pAd) | ||
271 | { | ||
272 | int i; | ||
273 | struct rt_rtmp_timer_task_entry *pQNode, *pEntry; | ||
274 | unsigned long irqFlags; | ||
275 | |||
276 | NdisAllocateSpinLock(&pAd->TimerQLock); | ||
277 | |||
278 | NdisZeroMemory(&pAd->TimerQ, sizeof(pAd->TimerQ)); | ||
279 | |||
280 | os_alloc_mem(pAd, &pAd->TimerQ.pTimerQPoll, | ||
281 | sizeof(struct rt_rtmp_timer_task_entry) * TIMER_QUEUE_SIZE_MAX); | ||
282 | if (pAd->TimerQ.pTimerQPoll) { | ||
283 | pEntry = NULL; | ||
284 | pQNode = (struct rt_rtmp_timer_task_entry *)pAd->TimerQ.pTimerQPoll; | ||
285 | NdisZeroMemory(pAd->TimerQ.pTimerQPoll, | ||
286 | sizeof(struct rt_rtmp_timer_task_entry) * | ||
287 | TIMER_QUEUE_SIZE_MAX); | ||
288 | |||
289 | RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags); | ||
290 | for (i = 0; i < TIMER_QUEUE_SIZE_MAX; i++) { | ||
291 | pQNode->pNext = pEntry; | ||
292 | pEntry = pQNode; | ||
293 | pQNode++; | ||
294 | } | ||
295 | pAd->TimerQ.pQPollFreeList = pEntry; | ||
296 | pAd->TimerQ.pQHead = NULL; | ||
297 | pAd->TimerQ.pQTail = NULL; | ||
298 | pAd->TimerQ.status = RTMP_TASK_STAT_INITED; | ||
299 | RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags); | ||
300 | } | ||
301 | } | ||
302 | #endif /* RTMP_TIMER_TASK_SUPPORT // */ | ||
diff --git a/drivers/staging/rt2860/common/spectrum.c b/drivers/staging/rt2860/common/spectrum.c deleted file mode 100644 index ceb622df12d..00000000000 --- a/drivers/staging/rt2860/common/spectrum.c +++ /dev/null | |||
@@ -1,2205 +0,0 @@ | |||
1 | /* | ||
2 | ************************************************************************* | ||
3 | * Ralink Tech Inc. | ||
4 | * 5F., No.36, Taiyuan St., Jhubei City, | ||
5 | * Hsinchu County 302, | ||
6 | * Taiwan, R.O.C. | ||
7 | * | ||
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the * | ||
22 | * Free Software Foundation, Inc., * | ||
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
24 | * * | ||
25 | ************************************************************************* | ||
26 | |||
27 | Module Name: | ||
28 | action.c | ||
29 | |||
30 | Abstract: | ||
31 | Handle association related requests either from WSTA or from local MLME | ||
32 | |||
33 | Revision History: | ||
34 | Who When What | ||
35 | --------- ---------- ---------------------------------------------- | ||
36 | Fonchi Wu 2008 created for 802.11h | ||
37 | */ | ||
38 | |||
39 | #include "../rt_config.h" | ||
40 | #include "action.h" | ||
41 | |||
42 | /* The regulatory information in the USA (US) */ | ||
43 | struct rt_dot11_regulatory_information USARegulatoryInfo[] = { | ||
44 | /* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */ | ||
45 | {0, {0, 0, {0} | ||
46 | } | ||
47 | } | ||
48 | , /* Invlid entry */ | ||
49 | {1, {4, 16, {36, 40, 44, 48} | ||
50 | } | ||
51 | } | ||
52 | , | ||
53 | {2, {4, 23, {52, 56, 60, 64} | ||
54 | } | ||
55 | } | ||
56 | , | ||
57 | {3, {4, 29, {149, 153, 157, 161} | ||
58 | } | ||
59 | } | ||
60 | , | ||
61 | {4, {11, 23, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140} | ||
62 | } | ||
63 | } | ||
64 | , | ||
65 | {5, {5, 30, {149, 153, 157, 161, 165} | ||
66 | } | ||
67 | } | ||
68 | , | ||
69 | {6, {10, 14, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} | ||
70 | } | ||
71 | } | ||
72 | , | ||
73 | {7, {10, 27, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} | ||
74 | } | ||
75 | } | ||
76 | , | ||
77 | {8, {5, 17, {11, 13, 15, 17, 19} | ||
78 | } | ||
79 | } | ||
80 | , | ||
81 | {9, {5, 30, {11, 13, 15, 17, 19} | ||
82 | } | ||
83 | } | ||
84 | , | ||
85 | {10, {2, 20, {21, 25} | ||
86 | } | ||
87 | } | ||
88 | , | ||
89 | {11, {2, 33, {21, 25} | ||
90 | } | ||
91 | } | ||
92 | , | ||
93 | {12, {11, 30, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} | ||
94 | } | ||
95 | } | ||
96 | }; | ||
97 | |||
98 | #define USA_REGULATORY_INFO_SIZE (sizeof(USARegulatoryInfo) / sizeof(struct rt_dot11_regulatory_information)) | ||
99 | |||
100 | /* The regulatory information in Europe */ | ||
101 | struct rt_dot11_regulatory_information EuropeRegulatoryInfo[] = { | ||
102 | /* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */ | ||
103 | {0, {0, 0, {0} | ||
104 | } | ||
105 | } | ||
106 | , /* Invalid entry */ | ||
107 | {1, {4, 20, {36, 40, 44, 48} | ||
108 | } | ||
109 | } | ||
110 | , | ||
111 | {2, {4, 20, {52, 56, 60, 64} | ||
112 | } | ||
113 | } | ||
114 | , | ||
115 | {3, {11, 30, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140} | ||
116 | } | ||
117 | } | ||
118 | , | ||
119 | {4, {13, 20, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} | ||
120 | } | ||
121 | } | ||
122 | }; | ||
123 | |||
124 | #define EU_REGULATORY_INFO_SIZE (sizeof(EuropeRegulatoryInfo) / sizeof(struct rt_dot11_regulatory_information)) | ||
125 | |||
126 | /* The regulatory information in Japan */ | ||
127 | struct rt_dot11_regulatory_information JapanRegulatoryInfo[] = { | ||
128 | /* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */ | ||
129 | {0, {0, 0, {0} | ||
130 | } | ||
131 | } | ||
132 | , /* Invalid entry */ | ||
133 | {1, {4, 22, {34, 38, 42, 46} | ||
134 | } | ||
135 | } | ||
136 | , | ||
137 | {2, {3, 24, {8, 12, 16} | ||
138 | } | ||
139 | } | ||
140 | , | ||
141 | {3, {3, 24, {8, 12, 16} | ||
142 | } | ||
143 | } | ||
144 | , | ||
145 | {4, {3, 24, {8, 12, 16} | ||
146 | } | ||
147 | } | ||
148 | , | ||
149 | {5, {3, 24, {8, 12, 16} | ||
150 | } | ||
151 | } | ||
152 | , | ||
153 | {6, {3, 22, {8, 12, 16} | ||
154 | } | ||
155 | } | ||
156 | , | ||
157 | {7, {4, 24, {184, 188, 192, 196} | ||
158 | } | ||
159 | } | ||
160 | , | ||
161 | {8, {4, 24, {184, 188, 192, 196} | ||
162 | } | ||
163 | } | ||
164 | , | ||
165 | {9, {4, 24, {184, 188, 192, 196} | ||
166 | } | ||
167 | } | ||
168 | , | ||
169 | {10, {4, 24, {184, 188, 192, 196} | ||
170 | } | ||
171 | } | ||
172 | , | ||
173 | {11, {4, 22, {184, 188, 192, 196} | ||
174 | } | ||
175 | } | ||
176 | , | ||
177 | {12, {4, 24, {7, 8, 9, 11} | ||
178 | } | ||
179 | } | ||
180 | , | ||
181 | {13, {4, 24, {7, 8, 9, 11} | ||
182 | } | ||
183 | } | ||
184 | , | ||
185 | {14, {4, 24, {7, 8, 9, 11} | ||
186 | } | ||
187 | } | ||
188 | , | ||
189 | {15, {4, 24, {7, 8, 9, 11} | ||
190 | } | ||
191 | } | ||
192 | , | ||
193 | {16, {6, 24, {183, 184, 185, 187, 188, 189} | ||
194 | } | ||
195 | } | ||
196 | , | ||
197 | {17, {6, 24, {183, 184, 185, 187, 188, 189} | ||
198 | } | ||
199 | } | ||
200 | , | ||
201 | {18, {6, 24, {183, 184, 185, 187, 188, 189} | ||
202 | } | ||
203 | } | ||
204 | , | ||
205 | {19, {6, 24, {183, 184, 185, 187, 188, 189} | ||
206 | } | ||
207 | } | ||
208 | , | ||
209 | {20, {6, 17, {183, 184, 185, 187, 188, 189} | ||
210 | } | ||
211 | } | ||
212 | , | ||
213 | {21, {6, 24, {6, 7, 8, 9, 10, 11} | ||
214 | } | ||
215 | } | ||
216 | , | ||
217 | {22, {6, 24, {6, 7, 8, 9, 10, 11} | ||
218 | } | ||
219 | } | ||
220 | , | ||
221 | {23, {6, 24, {6, 7, 8, 9, 10, 11} | ||
222 | } | ||
223 | } | ||
224 | , | ||
225 | {24, {6, 24, {6, 7, 8, 9, 10, 11} | ||
226 | } | ||
227 | } | ||
228 | , | ||
229 | {25, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189} | ||
230 | } | ||
231 | } | ||
232 | , | ||
233 | {26, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189} | ||
234 | } | ||
235 | } | ||
236 | , | ||
237 | {27, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189} | ||
238 | } | ||
239 | } | ||
240 | , | ||
241 | {28, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189} | ||
242 | } | ||
243 | } | ||
244 | , | ||
245 | {29, {8, 17, {182, 183, 184, 185, 186, 187, 188, 189} | ||
246 | } | ||
247 | } | ||
248 | , | ||
249 | {30, {13, 23, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} | ||
250 | } | ||
251 | } | ||
252 | , | ||
253 | {31, {1, 23, {14} | ||
254 | } | ||
255 | } | ||
256 | , | ||
257 | {32, {4, 22, {52, 56, 60, 64} | ||
258 | } | ||
259 | } | ||
260 | }; | ||
261 | |||
262 | #define JP_REGULATORY_INFO_SIZE (sizeof(JapanRegulatoryInfo) / sizeof(struct rt_dot11_regulatory_information)) | ||
263 | |||
264 | char RTMP_GetTxPwr(struct rt_rtmp_adapter *pAd, IN HTTRANSMIT_SETTING HTTxMode) | ||
265 | { | ||
266 | struct tx_pwr_cfg { | ||
267 | u8 Mode; | ||
268 | u8 MCS; | ||
269 | u16 req; | ||
270 | u8 shift; | ||
271 | u32 BitMask; | ||
272 | }; | ||
273 | |||
274 | u32 Value; | ||
275 | int Idx; | ||
276 | u8 PhyMode; | ||
277 | char CurTxPwr; | ||
278 | u8 TxPwrRef = 0; | ||
279 | char DaltaPwr; | ||
280 | unsigned long TxPwr[5]; | ||
281 | |||
282 | struct tx_pwr_cfg TxPwrCfg[] = { | ||
283 | {MODE_CCK, 0, 0, 4, 0x000000f0}, | ||
284 | {MODE_CCK, 1, 0, 0, 0x0000000f}, | ||
285 | {MODE_CCK, 2, 0, 12, 0x0000f000}, | ||
286 | {MODE_CCK, 3, 0, 8, 0x00000f00}, | ||
287 | |||
288 | {MODE_OFDM, 0, 0, 20, 0x00f00000}, | ||
289 | {MODE_OFDM, 1, 0, 16, 0x000f0000}, | ||
290 | {MODE_OFDM, 2, 0, 28, 0xf0000000}, | ||
291 | {MODE_OFDM, 3, 0, 24, 0x0f000000}, | ||
292 | {MODE_OFDM, 4, 1, 4, 0x000000f0}, | ||
293 | {MODE_OFDM, 5, 1, 0, 0x0000000f}, | ||
294 | {MODE_OFDM, 6, 1, 12, 0x0000f000}, | ||
295 | {MODE_OFDM, 7, 1, 8, 0x00000f00} | ||
296 | , {MODE_HTMIX, 0, 1, 20, 0x00f00000}, | ||
297 | {MODE_HTMIX, 1, 1, 16, 0x000f0000}, | ||
298 | {MODE_HTMIX, 2, 1, 28, 0xf0000000}, | ||
299 | {MODE_HTMIX, 3, 1, 24, 0x0f000000}, | ||
300 | {MODE_HTMIX, 4, 2, 4, 0x000000f0}, | ||
301 | {MODE_HTMIX, 5, 2, 0, 0x0000000f}, | ||
302 | {MODE_HTMIX, 6, 2, 12, 0x0000f000}, | ||
303 | {MODE_HTMIX, 7, 2, 8, 0x00000f00}, | ||
304 | {MODE_HTMIX, 8, 2, 20, 0x00f00000}, | ||
305 | {MODE_HTMIX, 9, 2, 16, 0x000f0000}, | ||
306 | {MODE_HTMIX, 10, 2, 28, 0xf0000000}, | ||
307 | {MODE_HTMIX, 11, 2, 24, 0x0f000000}, | ||
308 | {MODE_HTMIX, 12, 3, 4, 0x000000f0}, | ||
309 | {MODE_HTMIX, 13, 3, 0, 0x0000000f}, | ||
310 | {MODE_HTMIX, 14, 3, 12, 0x0000f000}, | ||
311 | {MODE_HTMIX, 15, 3, 8, 0x00000f00} | ||
312 | }; | ||
313 | #define MAX_TXPWR_TAB_SIZE (sizeof(TxPwrCfg) / sizeof(struct tx_pwr_cfg)) | ||
314 | |||
315 | CurTxPwr = 19; | ||
316 | |||
317 | /* check Tx Power setting from UI. */ | ||
318 | if (pAd->CommonCfg.TxPowerPercentage > 90) ; | ||
319 | else if (pAd->CommonCfg.TxPowerPercentage > 60) /* reduce Pwr for 1 dB. */ | ||
320 | CurTxPwr -= 1; | ||
321 | else if (pAd->CommonCfg.TxPowerPercentage > 30) /* reduce Pwr for 3 dB. */ | ||
322 | CurTxPwr -= 3; | ||
323 | else if (pAd->CommonCfg.TxPowerPercentage > 15) /* reduce Pwr for 6 dB. */ | ||
324 | CurTxPwr -= 6; | ||
325 | else if (pAd->CommonCfg.TxPowerPercentage > 9) /* reduce Pwr for 9 dB. */ | ||
326 | CurTxPwr -= 9; | ||
327 | else /* reduce Pwr for 12 dB. */ | ||
328 | CurTxPwr -= 12; | ||
329 | |||
330 | if (pAd->CommonCfg.BBPCurrentBW == BW_40) { | ||
331 | if (pAd->CommonCfg.CentralChannel > 14) { | ||
332 | TxPwr[0] = pAd->Tx40MPwrCfgABand[0]; | ||
333 | TxPwr[1] = pAd->Tx40MPwrCfgABand[1]; | ||
334 | TxPwr[2] = pAd->Tx40MPwrCfgABand[2]; | ||
335 | TxPwr[3] = pAd->Tx40MPwrCfgABand[3]; | ||
336 | TxPwr[4] = pAd->Tx40MPwrCfgABand[4]; | ||
337 | } else { | ||
338 | TxPwr[0] = pAd->Tx40MPwrCfgGBand[0]; | ||
339 | TxPwr[1] = pAd->Tx40MPwrCfgGBand[1]; | ||
340 | TxPwr[2] = pAd->Tx40MPwrCfgGBand[2]; | ||
341 | TxPwr[3] = pAd->Tx40MPwrCfgGBand[3]; | ||
342 | TxPwr[4] = pAd->Tx40MPwrCfgGBand[4]; | ||
343 | } | ||
344 | } else { | ||
345 | if (pAd->CommonCfg.Channel > 14) { | ||
346 | TxPwr[0] = pAd->Tx20MPwrCfgABand[0]; | ||
347 | TxPwr[1] = pAd->Tx20MPwrCfgABand[1]; | ||
348 | TxPwr[2] = pAd->Tx20MPwrCfgABand[2]; | ||
349 | TxPwr[3] = pAd->Tx20MPwrCfgABand[3]; | ||
350 | TxPwr[4] = pAd->Tx20MPwrCfgABand[4]; | ||
351 | } else { | ||
352 | TxPwr[0] = pAd->Tx20MPwrCfgGBand[0]; | ||
353 | TxPwr[1] = pAd->Tx20MPwrCfgGBand[1]; | ||
354 | TxPwr[2] = pAd->Tx20MPwrCfgGBand[2]; | ||
355 | TxPwr[3] = pAd->Tx20MPwrCfgGBand[3]; | ||
356 | TxPwr[4] = pAd->Tx20MPwrCfgGBand[4]; | ||
357 | } | ||
358 | } | ||
359 | |||
360 | switch (HTTxMode.field.MODE) { | ||
361 | case MODE_CCK: | ||
362 | case MODE_OFDM: | ||
363 | Value = TxPwr[1]; | ||
364 | TxPwrRef = (Value & 0x00000f00) >> 8; | ||
365 | |||
366 | break; | ||
367 | |||
368 | case MODE_HTMIX: | ||
369 | case MODE_HTGREENFIELD: | ||
370 | if (pAd->CommonCfg.TxStream == 1) { | ||
371 | Value = TxPwr[2]; | ||
372 | TxPwrRef = (Value & 0x00000f00) >> 8; | ||
373 | } else if (pAd->CommonCfg.TxStream == 2) { | ||
374 | Value = TxPwr[3]; | ||
375 | TxPwrRef = (Value & 0x00000f00) >> 8; | ||
376 | } | ||
377 | break; | ||
378 | } | ||
379 | |||
380 | PhyMode = (HTTxMode.field.MODE == MODE_HTGREENFIELD) | ||
381 | ? MODE_HTMIX : HTTxMode.field.MODE; | ||
382 | |||
383 | for (Idx = 0; Idx < MAX_TXPWR_TAB_SIZE; Idx++) { | ||
384 | if ((TxPwrCfg[Idx].Mode == PhyMode) | ||
385 | && (TxPwrCfg[Idx].MCS == HTTxMode.field.MCS)) { | ||
386 | Value = TxPwr[TxPwrCfg[Idx].req]; | ||
387 | DaltaPwr = | ||
388 | TxPwrRef - (char)((Value & TxPwrCfg[Idx].BitMask) | ||
389 | >> TxPwrCfg[Idx].shift); | ||
390 | CurTxPwr -= DaltaPwr; | ||
391 | break; | ||
392 | } | ||
393 | } | ||
394 | |||
395 | return CurTxPwr; | ||
396 | } | ||
397 | |||
398 | void MeasureReqTabInit(struct rt_rtmp_adapter *pAd) | ||
399 | { | ||
400 | NdisAllocateSpinLock(&pAd->CommonCfg.MeasureReqTabLock); | ||
401 | |||
402 | pAd->CommonCfg.pMeasureReqTab = | ||
403 | kmalloc(sizeof(struct rt_measure_req_tab), GFP_ATOMIC); | ||
404 | if (pAd->CommonCfg.pMeasureReqTab) | ||
405 | NdisZeroMemory(pAd->CommonCfg.pMeasureReqTab, | ||
406 | sizeof(struct rt_measure_req_tab)); | ||
407 | else | ||
408 | DBGPRINT(RT_DEBUG_ERROR, | ||
409 | ("%s Fail to alloc memory for pAd->CommonCfg.pMeasureReqTab.\n", | ||
410 | __func__)); | ||
411 | |||
412 | return; | ||
413 | } | ||
414 | |||
415 | void MeasureReqTabExit(struct rt_rtmp_adapter *pAd) | ||
416 | { | ||
417 | NdisFreeSpinLock(&pAd->CommonCfg.MeasureReqTabLock); | ||
418 | |||
419 | kfree(pAd->CommonCfg.pMeasureReqTab); | ||
420 | pAd->CommonCfg.pMeasureReqTab = NULL; | ||
421 | |||
422 | return; | ||
423 | } | ||
424 | |||
425 | struct rt_measure_req_entry *MeasureReqLookUp(struct rt_rtmp_adapter *pAd, u8 DialogToken) | ||
426 | { | ||
427 | u32 HashIdx; | ||
428 | struct rt_measure_req_tab *pTab = pAd->CommonCfg.pMeasureReqTab; | ||
429 | struct rt_measure_req_entry *pEntry = NULL; | ||
430 | struct rt_measure_req_entry *pPrevEntry = NULL; | ||
431 | |||
432 | if (pTab == NULL) { | ||
433 | DBGPRINT(RT_DEBUG_ERROR, | ||
434 | ("%s: pMeasureReqTab doesn't exist.\n", __func__)); | ||
435 | return NULL; | ||
436 | } | ||
437 | |||
438 | RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock); | ||
439 | |||
440 | HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken); | ||
441 | pEntry = pTab->Hash[HashIdx]; | ||
442 | |||
443 | while (pEntry) { | ||
444 | if (pEntry->DialogToken == DialogToken) | ||
445 | break; | ||
446 | else { | ||
447 | pPrevEntry = pEntry; | ||
448 | pEntry = pEntry->pNext; | ||
449 | } | ||
450 | } | ||
451 | |||
452 | RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock); | ||
453 | |||
454 | return pEntry; | ||
455 | } | ||
456 | |||
457 | struct rt_measure_req_entry *MeasureReqInsert(struct rt_rtmp_adapter *pAd, u8 DialogToken) | ||
458 | { | ||
459 | int i; | ||
460 | unsigned long HashIdx; | ||
461 | struct rt_measure_req_tab *pTab = pAd->CommonCfg.pMeasureReqTab; | ||
462 | struct rt_measure_req_entry *pEntry = NULL, *pCurrEntry; | ||
463 | unsigned long Now; | ||
464 | |||
465 | if (pTab == NULL) { | ||
466 | DBGPRINT(RT_DEBUG_ERROR, | ||
467 | ("%s: pMeasureReqTab doesn't exist.\n", __func__)); | ||
468 | return NULL; | ||
469 | } | ||
470 | |||
471 | pEntry = MeasureReqLookUp(pAd, DialogToken); | ||
472 | if (pEntry == NULL) { | ||
473 | RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock); | ||
474 | for (i = 0; i < MAX_MEASURE_REQ_TAB_SIZE; i++) { | ||
475 | NdisGetSystemUpTime(&Now); | ||
476 | pEntry = &pTab->Content[i]; | ||
477 | |||
478 | if ((pEntry->Valid == TRUE) | ||
479 | && RTMP_TIME_AFTER((unsigned long)Now, | ||
480 | (unsigned long)(pEntry-> | ||
481 | lastTime + | ||
482 | MQ_REQ_AGE_OUT))) | ||
483 | { | ||
484 | struct rt_measure_req_entry *pPrevEntry = NULL; | ||
485 | unsigned long HashIdx = | ||
486 | MQ_DIALOGTOKEN_HASH_INDEX(pEntry-> | ||
487 | DialogToken); | ||
488 | struct rt_measure_req_entry *pProbeEntry = | ||
489 | pTab->Hash[HashIdx]; | ||
490 | |||
491 | /* update Hash list */ | ||
492 | do { | ||
493 | if (pProbeEntry == pEntry) { | ||
494 | if (pPrevEntry == NULL) { | ||
495 | pTab->Hash[HashIdx] = | ||
496 | pEntry->pNext; | ||
497 | } else { | ||
498 | pPrevEntry->pNext = | ||
499 | pEntry->pNext; | ||
500 | } | ||
501 | break; | ||
502 | } | ||
503 | |||
504 | pPrevEntry = pProbeEntry; | ||
505 | pProbeEntry = pProbeEntry->pNext; | ||
506 | } while (pProbeEntry); | ||
507 | |||
508 | NdisZeroMemory(pEntry, | ||
509 | sizeof(struct rt_measure_req_entry)); | ||
510 | pTab->Size--; | ||
511 | |||
512 | break; | ||
513 | } | ||
514 | |||
515 | if (pEntry->Valid == FALSE) | ||
516 | break; | ||
517 | } | ||
518 | |||
519 | if (i < MAX_MEASURE_REQ_TAB_SIZE) { | ||
520 | NdisGetSystemUpTime(&Now); | ||
521 | pEntry->lastTime = Now; | ||
522 | pEntry->Valid = TRUE; | ||
523 | pEntry->DialogToken = DialogToken; | ||
524 | pTab->Size++; | ||
525 | } else { | ||
526 | pEntry = NULL; | ||
527 | DBGPRINT(RT_DEBUG_ERROR, | ||
528 | ("%s: pMeasureReqTab tab full.\n", __func__)); | ||
529 | } | ||
530 | |||
531 | /* add this Neighbor entry into HASH table */ | ||
532 | if (pEntry) { | ||
533 | HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken); | ||
534 | if (pTab->Hash[HashIdx] == NULL) { | ||
535 | pTab->Hash[HashIdx] = pEntry; | ||
536 | } else { | ||
537 | pCurrEntry = pTab->Hash[HashIdx]; | ||
538 | while (pCurrEntry->pNext != NULL) | ||
539 | pCurrEntry = pCurrEntry->pNext; | ||
540 | pCurrEntry->pNext = pEntry; | ||
541 | } | ||
542 | } | ||
543 | |||
544 | RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock); | ||
545 | } | ||
546 | |||
547 | return pEntry; | ||
548 | } | ||
549 | |||
550 | void MeasureReqDelete(struct rt_rtmp_adapter *pAd, u8 DialogToken) | ||
551 | { | ||
552 | struct rt_measure_req_tab *pTab = pAd->CommonCfg.pMeasureReqTab; | ||
553 | struct rt_measure_req_entry *pEntry = NULL; | ||
554 | |||
555 | if (pTab == NULL) { | ||
556 | DBGPRINT(RT_DEBUG_ERROR, | ||
557 | ("%s: pMeasureReqTab doesn't exist.\n", __func__)); | ||
558 | return; | ||
559 | } | ||
560 | /* if empty, return */ | ||
561 | if (pTab->Size == 0) { | ||
562 | DBGPRINT(RT_DEBUG_ERROR, ("pMeasureReqTab empty.\n")); | ||
563 | return; | ||
564 | } | ||
565 | |||
566 | pEntry = MeasureReqLookUp(pAd, DialogToken); | ||
567 | if (pEntry != NULL) { | ||
568 | struct rt_measure_req_entry *pPrevEntry = NULL; | ||
569 | unsigned long HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken); | ||
570 | struct rt_measure_req_entry *pProbeEntry = pTab->Hash[HashIdx]; | ||
571 | |||
572 | RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock); | ||
573 | /* update Hash list */ | ||
574 | do { | ||
575 | if (pProbeEntry == pEntry) { | ||
576 | if (pPrevEntry == NULL) { | ||
577 | pTab->Hash[HashIdx] = pEntry->pNext; | ||
578 | } else { | ||
579 | pPrevEntry->pNext = pEntry->pNext; | ||
580 | } | ||
581 | break; | ||
582 | } | ||
583 | |||
584 | pPrevEntry = pProbeEntry; | ||
585 | pProbeEntry = pProbeEntry->pNext; | ||
586 | } while (pProbeEntry); | ||
587 | |||
588 | NdisZeroMemory(pEntry, sizeof(struct rt_measure_req_entry)); | ||
589 | pTab->Size--; | ||
590 | |||
591 | RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock); | ||
592 | } | ||
593 | |||
594 | return; | ||
595 | } | ||
596 | |||
597 | void TpcReqTabInit(struct rt_rtmp_adapter *pAd) | ||
598 | { | ||
599 | NdisAllocateSpinLock(&pAd->CommonCfg.TpcReqTabLock); | ||
600 | |||
601 | pAd->CommonCfg.pTpcReqTab = kmalloc(sizeof(struct rt_tpc_req_tab), GFP_ATOMIC); | ||
602 | if (pAd->CommonCfg.pTpcReqTab) | ||
603 | NdisZeroMemory(pAd->CommonCfg.pTpcReqTab, sizeof(struct rt_tpc_req_tab)); | ||
604 | else | ||
605 | DBGPRINT(RT_DEBUG_ERROR, | ||
606 | ("%s Fail to alloc memory for pAd->CommonCfg.pTpcReqTab.\n", | ||
607 | __func__)); | ||
608 | |||
609 | return; | ||
610 | } | ||
611 | |||
612 | void TpcReqTabExit(struct rt_rtmp_adapter *pAd) | ||
613 | { | ||
614 | NdisFreeSpinLock(&pAd->CommonCfg.TpcReqTabLock); | ||
615 | |||
616 | kfree(pAd->CommonCfg.pTpcReqTab); | ||
617 | pAd->CommonCfg.pTpcReqTab = NULL; | ||
618 | |||
619 | return; | ||
620 | } | ||
621 | |||
622 | static struct rt_tpc_req_entry *TpcReqLookUp(struct rt_rtmp_adapter *pAd, u8 DialogToken) | ||
623 | { | ||
624 | u32 HashIdx; | ||
625 | struct rt_tpc_req_tab *pTab = pAd->CommonCfg.pTpcReqTab; | ||
626 | struct rt_tpc_req_entry *pEntry = NULL; | ||
627 | struct rt_tpc_req_entry *pPrevEntry = NULL; | ||
628 | |||
629 | if (pTab == NULL) { | ||
630 | DBGPRINT(RT_DEBUG_ERROR, | ||
631 | ("%s: pTpcReqTab doesn't exist.\n", __func__)); | ||
632 | return NULL; | ||
633 | } | ||
634 | |||
635 | RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock); | ||
636 | |||
637 | HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken); | ||
638 | pEntry = pTab->Hash[HashIdx]; | ||
639 | |||
640 | while (pEntry) { | ||
641 | if (pEntry->DialogToken == DialogToken) | ||
642 | break; | ||
643 | else { | ||
644 | pPrevEntry = pEntry; | ||
645 | pEntry = pEntry->pNext; | ||
646 | } | ||
647 | } | ||
648 | |||
649 | RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock); | ||
650 | |||
651 | return pEntry; | ||
652 | } | ||
653 | |||
654 | static struct rt_tpc_req_entry *TpcReqInsert(struct rt_rtmp_adapter *pAd, u8 DialogToken) | ||
655 | { | ||
656 | int i; | ||
657 | unsigned long HashIdx; | ||
658 | struct rt_tpc_req_tab *pTab = pAd->CommonCfg.pTpcReqTab; | ||
659 | struct rt_tpc_req_entry *pEntry = NULL, *pCurrEntry; | ||
660 | unsigned long Now; | ||
661 | |||
662 | if (pTab == NULL) { | ||
663 | DBGPRINT(RT_DEBUG_ERROR, | ||
664 | ("%s: pTpcReqTab doesn't exist.\n", __func__)); | ||
665 | return NULL; | ||
666 | } | ||
667 | |||
668 | pEntry = TpcReqLookUp(pAd, DialogToken); | ||
669 | if (pEntry == NULL) { | ||
670 | RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock); | ||
671 | for (i = 0; i < MAX_TPC_REQ_TAB_SIZE; i++) { | ||
672 | NdisGetSystemUpTime(&Now); | ||
673 | pEntry = &pTab->Content[i]; | ||
674 | |||
675 | if ((pEntry->Valid == TRUE) | ||
676 | && RTMP_TIME_AFTER((unsigned long)Now, | ||
677 | (unsigned long)(pEntry-> | ||
678 | lastTime + | ||
679 | TPC_REQ_AGE_OUT))) | ||
680 | { | ||
681 | struct rt_tpc_req_entry *pPrevEntry = NULL; | ||
682 | unsigned long HashIdx = | ||
683 | TPC_DIALOGTOKEN_HASH_INDEX(pEntry-> | ||
684 | DialogToken); | ||
685 | struct rt_tpc_req_entry *pProbeEntry = | ||
686 | pTab->Hash[HashIdx]; | ||
687 | |||
688 | /* update Hash list */ | ||
689 | do { | ||
690 | if (pProbeEntry == pEntry) { | ||
691 | if (pPrevEntry == NULL) { | ||
692 | pTab->Hash[HashIdx] = | ||
693 | pEntry->pNext; | ||
694 | } else { | ||
695 | pPrevEntry->pNext = | ||
696 | pEntry->pNext; | ||
697 | } | ||
698 | break; | ||
699 | } | ||
700 | |||
701 | pPrevEntry = pProbeEntry; | ||
702 | pProbeEntry = pProbeEntry->pNext; | ||
703 | } while (pProbeEntry); | ||
704 | |||
705 | NdisZeroMemory(pEntry, sizeof(struct rt_tpc_req_entry)); | ||
706 | pTab->Size--; | ||
707 | |||
708 | break; | ||
709 | } | ||
710 | |||
711 | if (pEntry->Valid == FALSE) | ||
712 | break; | ||
713 | } | ||
714 | |||
715 | if (i < MAX_TPC_REQ_TAB_SIZE) { | ||
716 | NdisGetSystemUpTime(&Now); | ||
717 | pEntry->lastTime = Now; | ||
718 | pEntry->Valid = TRUE; | ||
719 | pEntry->DialogToken = DialogToken; | ||
720 | pTab->Size++; | ||
721 | } else { | ||
722 | pEntry = NULL; | ||
723 | DBGPRINT(RT_DEBUG_ERROR, | ||
724 | ("%s: pTpcReqTab tab full.\n", __func__)); | ||
725 | } | ||
726 | |||
727 | /* add this Neighbor entry into HASH table */ | ||
728 | if (pEntry) { | ||
729 | HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken); | ||
730 | if (pTab->Hash[HashIdx] == NULL) { | ||
731 | pTab->Hash[HashIdx] = pEntry; | ||
732 | } else { | ||
733 | pCurrEntry = pTab->Hash[HashIdx]; | ||
734 | while (pCurrEntry->pNext != NULL) | ||
735 | pCurrEntry = pCurrEntry->pNext; | ||
736 | pCurrEntry->pNext = pEntry; | ||
737 | } | ||
738 | } | ||
739 | |||
740 | RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock); | ||
741 | } | ||
742 | |||
743 | return pEntry; | ||
744 | } | ||
745 | |||
746 | static void TpcReqDelete(struct rt_rtmp_adapter *pAd, u8 DialogToken) | ||
747 | { | ||
748 | struct rt_tpc_req_tab *pTab = pAd->CommonCfg.pTpcReqTab; | ||
749 | struct rt_tpc_req_entry *pEntry = NULL; | ||
750 | |||
751 | if (pTab == NULL) { | ||
752 | DBGPRINT(RT_DEBUG_ERROR, | ||
753 | ("%s: pTpcReqTab doesn't exist.\n", __func__)); | ||
754 | return; | ||
755 | } | ||
756 | /* if empty, return */ | ||
757 | if (pTab->Size == 0) { | ||
758 | DBGPRINT(RT_DEBUG_ERROR, ("pTpcReqTab empty.\n")); | ||
759 | return; | ||
760 | } | ||
761 | |||
762 | pEntry = TpcReqLookUp(pAd, DialogToken); | ||
763 | if (pEntry != NULL) { | ||
764 | struct rt_tpc_req_entry *pPrevEntry = NULL; | ||
765 | unsigned long HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken); | ||
766 | struct rt_tpc_req_entry *pProbeEntry = pTab->Hash[HashIdx]; | ||
767 | |||
768 | RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock); | ||
769 | /* update Hash list */ | ||
770 | do { | ||
771 | if (pProbeEntry == pEntry) { | ||
772 | if (pPrevEntry == NULL) { | ||
773 | pTab->Hash[HashIdx] = pEntry->pNext; | ||
774 | } else { | ||
775 | pPrevEntry->pNext = pEntry->pNext; | ||
776 | } | ||
777 | break; | ||
778 | } | ||
779 | |||
780 | pPrevEntry = pProbeEntry; | ||
781 | pProbeEntry = pProbeEntry->pNext; | ||
782 | } while (pProbeEntry); | ||
783 | |||
784 | NdisZeroMemory(pEntry, sizeof(struct rt_tpc_req_entry)); | ||
785 | pTab->Size--; | ||
786 | |||
787 | RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock); | ||
788 | } | ||
789 | |||
790 | return; | ||
791 | } | ||
792 | |||
793 | /* | ||
794 | ========================================================================== | ||
795 | Description: | ||
796 | Get Current TimeS tamp. | ||
797 | |||
798 | Parametrs: | ||
799 | |||
800 | Return : Current Time Stamp. | ||
801 | ========================================================================== | ||
802 | */ | ||
803 | static u64 GetCurrentTimeStamp(struct rt_rtmp_adapter *pAd) | ||
804 | { | ||
805 | /* get current time stamp. */ | ||
806 | return 0; | ||
807 | } | ||
808 | |||
809 | /* | ||
810 | ========================================================================== | ||
811 | Description: | ||
812 | Get Current Transmit Power. | ||
813 | |||
814 | Parametrs: | ||
815 | |||
816 | Return : Current Time Stamp. | ||
817 | ========================================================================== | ||
818 | */ | ||
819 | static u8 GetCurTxPwr(struct rt_rtmp_adapter *pAd, u8 Wcid) | ||
820 | { | ||
821 | return 16; /* 16 dBm */ | ||
822 | } | ||
823 | |||
824 | /* | ||
825 | ========================================================================== | ||
826 | Description: | ||
827 | Get Current Transmit Power. | ||
828 | |||
829 | Parametrs: | ||
830 | |||
831 | Return : Current Time Stamp. | ||
832 | ========================================================================== | ||
833 | */ | ||
834 | void InsertChannelRepIE(struct rt_rtmp_adapter *pAd, | ||
835 | u8 *pFrameBuf, | ||
836 | unsigned long *pFrameLen, | ||
837 | char *pCountry, u8 RegulatoryClass) | ||
838 | { | ||
839 | unsigned long TempLen; | ||
840 | u8 Len; | ||
841 | u8 IEId = IE_AP_CHANNEL_REPORT; | ||
842 | u8 *pChListPtr = NULL; | ||
843 | |||
844 | Len = 1; | ||
845 | if (strncmp(pCountry, "US", 2) == 0) { | ||
846 | if (RegulatoryClass >= USA_REGULATORY_INFO_SIZE) { | ||
847 | DBGPRINT(RT_DEBUG_ERROR, | ||
848 | ("%s: USA Unknow Requlatory class (%d)\n", | ||
849 | __func__, RegulatoryClass)); | ||
850 | return; | ||
851 | } | ||
852 | |||
853 | Len += | ||
854 | USARegulatoryInfo[RegulatoryClass].ChannelSet. | ||
855 | NumberOfChannels; | ||
856 | pChListPtr = | ||
857 | USARegulatoryInfo[RegulatoryClass].ChannelSet.ChannelList; | ||
858 | } else if (strncmp(pCountry, "JP", 2) == 0) { | ||
859 | if (RegulatoryClass >= JP_REGULATORY_INFO_SIZE) { | ||
860 | DBGPRINT(RT_DEBUG_ERROR, | ||
861 | ("%s: JP Unknow Requlatory class (%d)\n", | ||
862 | __func__, RegulatoryClass)); | ||
863 | return; | ||
864 | } | ||
865 | |||
866 | Len += | ||
867 | JapanRegulatoryInfo[RegulatoryClass].ChannelSet. | ||
868 | NumberOfChannels; | ||
869 | pChListPtr = | ||
870 | JapanRegulatoryInfo[RegulatoryClass].ChannelSet.ChannelList; | ||
871 | } else { | ||
872 | DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow Country (%s)\n", | ||
873 | __func__, pCountry)); | ||
874 | return; | ||
875 | } | ||
876 | |||
877 | MakeOutgoingFrame(pFrameBuf, &TempLen, | ||
878 | 1, &IEId, | ||
879 | 1, &Len, | ||
880 | 1, &RegulatoryClass, | ||
881 | Len - 1, pChListPtr, END_OF_ARGS); | ||
882 | |||
883 | *pFrameLen = *pFrameLen + TempLen; | ||
884 | |||
885 | return; | ||
886 | } | ||
887 | |||
888 | /* | ||
889 | ========================================================================== | ||
890 | Description: | ||
891 | Insert Dialog Token into frame. | ||
892 | |||
893 | Parametrs: | ||
894 | 1. frame buffer pointer. | ||
895 | 2. frame length. | ||
896 | 3. Dialog token. | ||
897 | |||
898 | Return : None. | ||
899 | ========================================================================== | ||
900 | */ | ||
901 | void InsertDialogToken(struct rt_rtmp_adapter *pAd, | ||
902 | u8 *pFrameBuf, | ||
903 | unsigned long *pFrameLen, u8 DialogToken) | ||
904 | { | ||
905 | unsigned long TempLen; | ||
906 | MakeOutgoingFrame(pFrameBuf, &TempLen, 1, &DialogToken, END_OF_ARGS); | ||
907 | |||
908 | *pFrameLen = *pFrameLen + TempLen; | ||
909 | |||
910 | return; | ||
911 | } | ||
912 | |||
913 | /* | ||
914 | ========================================================================== | ||
915 | Description: | ||
916 | Insert TPC Request IE into frame. | ||
917 | |||
918 | Parametrs: | ||
919 | 1. frame buffer pointer. | ||
920 | 2. frame length. | ||
921 | |||
922 | Return : None. | ||
923 | ========================================================================== | ||
924 | */ | ||
925 | static void InsertTpcReqIE(struct rt_rtmp_adapter *pAd, | ||
926 | u8 *pFrameBuf, unsigned long *pFrameLen) | ||
927 | { | ||
928 | unsigned long TempLen; | ||
929 | unsigned long Len = 0; | ||
930 | u8 ElementID = IE_TPC_REQUEST; | ||
931 | |||
932 | MakeOutgoingFrame(pFrameBuf, &TempLen, | ||
933 | 1, &ElementID, 1, &Len, END_OF_ARGS); | ||
934 | |||
935 | *pFrameLen = *pFrameLen + TempLen; | ||
936 | |||
937 | return; | ||
938 | } | ||
939 | |||
940 | /* | ||
941 | ========================================================================== | ||
942 | Description: | ||
943 | Insert TPC Report IE into frame. | ||
944 | |||
945 | Parametrs: | ||
946 | 1. frame buffer pointer. | ||
947 | 2. frame length. | ||
948 | 3. Transmit Power. | ||
949 | 4. Link Margin. | ||
950 | |||
951 | Return : None. | ||
952 | ========================================================================== | ||
953 | */ | ||
954 | void InsertTpcReportIE(struct rt_rtmp_adapter *pAd, | ||
955 | u8 *pFrameBuf, | ||
956 | unsigned long *pFrameLen, | ||
957 | u8 TxPwr, u8 LinkMargin) | ||
958 | { | ||
959 | unsigned long TempLen; | ||
960 | unsigned long Len = sizeof(struct rt_tpc_report_info); | ||
961 | u8 ElementID = IE_TPC_REPORT; | ||
962 | struct rt_tpc_report_info TpcReportIE; | ||
963 | |||
964 | TpcReportIE.TxPwr = TxPwr; | ||
965 | TpcReportIE.LinkMargin = LinkMargin; | ||
966 | |||
967 | MakeOutgoingFrame(pFrameBuf, &TempLen, | ||
968 | 1, &ElementID, | ||
969 | 1, &Len, Len, &TpcReportIE, END_OF_ARGS); | ||
970 | |||
971 | *pFrameLen = *pFrameLen + TempLen; | ||
972 | |||
973 | return; | ||
974 | } | ||
975 | |||
976 | /* | ||
977 | ========================================================================== | ||
978 | Description: | ||
979 | Insert Channel Switch Announcement IE into frame. | ||
980 | |||
981 | Parametrs: | ||
982 | 1. frame buffer pointer. | ||
983 | 2. frame length. | ||
984 | 3. channel switch announcement mode. | ||
985 | 4. new selected channel. | ||
986 | 5. channel switch announcement count. | ||
987 | |||
988 | Return : None. | ||
989 | ========================================================================== | ||
990 | */ | ||
991 | static void InsertChSwAnnIE(struct rt_rtmp_adapter *pAd, | ||
992 | u8 *pFrameBuf, | ||
993 | unsigned long *pFrameLen, | ||
994 | u8 ChSwMode, | ||
995 | u8 NewChannel, u8 ChSwCnt) | ||
996 | { | ||
997 | unsigned long TempLen; | ||
998 | unsigned long Len = sizeof(struct rt_ch_sw_ann_info); | ||
999 | u8 ElementID = IE_CHANNEL_SWITCH_ANNOUNCEMENT; | ||
1000 | struct rt_ch_sw_ann_info ChSwAnnIE; | ||
1001 | |||
1002 | ChSwAnnIE.ChSwMode = ChSwMode; | ||
1003 | ChSwAnnIE.Channel = NewChannel; | ||
1004 | ChSwAnnIE.ChSwCnt = ChSwCnt; | ||
1005 | |||
1006 | MakeOutgoingFrame(pFrameBuf, &TempLen, | ||
1007 | 1, &ElementID, 1, &Len, Len, &ChSwAnnIE, END_OF_ARGS); | ||
1008 | |||
1009 | *pFrameLen = *pFrameLen + TempLen; | ||
1010 | |||
1011 | return; | ||
1012 | } | ||
1013 | |||
1014 | /* | ||
1015 | ========================================================================== | ||
1016 | Description: | ||
1017 | Insert Measure Request IE into frame. | ||
1018 | |||
1019 | Parametrs: | ||
1020 | 1. frame buffer pointer. | ||
1021 | 2. frame length. | ||
1022 | 3. Measure Token. | ||
1023 | 4. Measure Request Mode. | ||
1024 | 5. Measure Request Type. | ||
1025 | 6. Measure Channel. | ||
1026 | 7. Measure Start time. | ||
1027 | 8. Measure Duration. | ||
1028 | |||
1029 | Return : None. | ||
1030 | ========================================================================== | ||
1031 | */ | ||
1032 | static void InsertMeasureReqIE(struct rt_rtmp_adapter *pAd, | ||
1033 | u8 *pFrameBuf, | ||
1034 | unsigned long *pFrameLen, | ||
1035 | u8 Len, struct rt_measure_req_info * pMeasureReqIE) | ||
1036 | { | ||
1037 | unsigned long TempLen; | ||
1038 | u8 ElementID = IE_MEASUREMENT_REQUEST; | ||
1039 | |||
1040 | MakeOutgoingFrame(pFrameBuf, &TempLen, | ||
1041 | 1, &ElementID, | ||
1042 | 1, &Len, | ||
1043 | sizeof(struct rt_measure_req_info), pMeasureReqIE, END_OF_ARGS); | ||
1044 | |||
1045 | *pFrameLen = *pFrameLen + TempLen; | ||
1046 | |||
1047 | return; | ||
1048 | } | ||
1049 | |||
1050 | /* | ||
1051 | ========================================================================== | ||
1052 | Description: | ||
1053 | Insert Measure Report IE into frame. | ||
1054 | |||
1055 | Parametrs: | ||
1056 | 1. frame buffer pointer. | ||
1057 | 2. frame length. | ||
1058 | 3. Measure Token. | ||
1059 | 4. Measure Request Mode. | ||
1060 | 5. Measure Request Type. | ||
1061 | 6. Length of Report Information | ||
1062 | 7. Pointer of Report Information Buffer. | ||
1063 | |||
1064 | Return : None. | ||
1065 | ========================================================================== | ||
1066 | */ | ||
1067 | static void InsertMeasureReportIE(struct rt_rtmp_adapter *pAd, | ||
1068 | u8 *pFrameBuf, | ||
1069 | unsigned long *pFrameLen, | ||
1070 | struct rt_measure_report_info * pMeasureReportIE, | ||
1071 | u8 ReportLnfoLen, u8 *pReportInfo) | ||
1072 | { | ||
1073 | unsigned long TempLen; | ||
1074 | unsigned long Len; | ||
1075 | u8 ElementID = IE_MEASUREMENT_REPORT; | ||
1076 | |||
1077 | Len = sizeof(struct rt_measure_report_info) + ReportLnfoLen; | ||
1078 | |||
1079 | MakeOutgoingFrame(pFrameBuf, &TempLen, | ||
1080 | 1, &ElementID, | ||
1081 | 1, &Len, Len, pMeasureReportIE, END_OF_ARGS); | ||
1082 | |||
1083 | *pFrameLen = *pFrameLen + TempLen; | ||
1084 | |||
1085 | if ((ReportLnfoLen > 0) && (pReportInfo != NULL)) { | ||
1086 | MakeOutgoingFrame(pFrameBuf + *pFrameLen, &TempLen, | ||
1087 | ReportLnfoLen, pReportInfo, END_OF_ARGS); | ||
1088 | |||
1089 | *pFrameLen = *pFrameLen + TempLen; | ||
1090 | } | ||
1091 | return; | ||
1092 | } | ||
1093 | |||
1094 | /* | ||
1095 | ========================================================================== | ||
1096 | Description: | ||
1097 | Prepare Measurement request action frame and enqueue it into | ||
1098 | management queue waiting for transmition. | ||
1099 | |||
1100 | Parametrs: | ||
1101 | 1. the destination mac address of the frame. | ||
1102 | |||
1103 | Return : None. | ||
1104 | ========================================================================== | ||
1105 | */ | ||
1106 | void MakeMeasurementReqFrame(struct rt_rtmp_adapter *pAd, | ||
1107 | u8 *pOutBuffer, | ||
1108 | unsigned long *pFrameLen, | ||
1109 | u8 TotalLen, | ||
1110 | u8 Category, | ||
1111 | u8 Action, | ||
1112 | u8 MeasureToken, | ||
1113 | u8 MeasureReqMode, | ||
1114 | u8 MeasureReqType, u8 NumOfRepetitions) | ||
1115 | { | ||
1116 | unsigned long TempLen; | ||
1117 | struct rt_measure_req_info MeasureReqIE; | ||
1118 | |||
1119 | InsertActField(pAd, (pOutBuffer + *pFrameLen), pFrameLen, Category, | ||
1120 | Action); | ||
1121 | |||
1122 | /* fill Dialog Token */ | ||
1123 | InsertDialogToken(pAd, (pOutBuffer + *pFrameLen), pFrameLen, | ||
1124 | MeasureToken); | ||
1125 | |||
1126 | /* fill Number of repetitions. */ | ||
1127 | if (Category == CATEGORY_RM) { | ||
1128 | MakeOutgoingFrame((pOutBuffer + *pFrameLen), &TempLen, | ||
1129 | 2, &NumOfRepetitions, END_OF_ARGS); | ||
1130 | |||
1131 | *pFrameLen += TempLen; | ||
1132 | } | ||
1133 | /* prepare Measurement IE. */ | ||
1134 | NdisZeroMemory(&MeasureReqIE, sizeof(struct rt_measure_req_info)); | ||
1135 | MeasureReqIE.Token = MeasureToken; | ||
1136 | MeasureReqIE.ReqMode.word = MeasureReqMode; | ||
1137 | MeasureReqIE.ReqType = MeasureReqType; | ||
1138 | InsertMeasureReqIE(pAd, (pOutBuffer + *pFrameLen), pFrameLen, | ||
1139 | TotalLen, &MeasureReqIE); | ||
1140 | |||
1141 | return; | ||
1142 | } | ||
1143 | |||
1144 | /* | ||
1145 | ========================================================================== | ||
1146 | Description: | ||
1147 | Prepare Measurement report action frame and enqueue it into | ||
1148 | management queue waiting for transmition. | ||
1149 | |||
1150 | Parametrs: | ||
1151 | 1. the destination mac address of the frame. | ||
1152 | |||
1153 | Return : None. | ||
1154 | ========================================================================== | ||
1155 | */ | ||
1156 | void EnqueueMeasurementRep(struct rt_rtmp_adapter *pAd, | ||
1157 | u8 *pDA, | ||
1158 | u8 DialogToken, | ||
1159 | u8 MeasureToken, | ||
1160 | u8 MeasureReqMode, | ||
1161 | u8 MeasureReqType, | ||
1162 | u8 ReportInfoLen, u8 *pReportInfo) | ||
1163 | { | ||
1164 | u8 *pOutBuffer = NULL; | ||
1165 | int NStatus; | ||
1166 | unsigned long FrameLen; | ||
1167 | struct rt_header_802_11 ActHdr; | ||
1168 | struct rt_measure_report_info MeasureRepIE; | ||
1169 | |||
1170 | /* build action frame header. */ | ||
1171 | MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, | ||
1172 | pAd->CurrentAddress); | ||
1173 | |||
1174 | NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */ | ||
1175 | if (NStatus != NDIS_STATUS_SUCCESS) { | ||
1176 | DBGPRINT(RT_DEBUG_TRACE, | ||
1177 | ("%s() allocate memory failed \n", __func__)); | ||
1178 | return; | ||
1179 | } | ||
1180 | NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11)); | ||
1181 | FrameLen = sizeof(struct rt_header_802_11); | ||
1182 | |||
1183 | InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, | ||
1184 | CATEGORY_SPECTRUM, SPEC_MRP); | ||
1185 | |||
1186 | /* fill Dialog Token */ | ||
1187 | InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); | ||
1188 | |||
1189 | /* prepare Measurement IE. */ | ||
1190 | NdisZeroMemory(&MeasureRepIE, sizeof(struct rt_measure_report_info)); | ||
1191 | MeasureRepIE.Token = MeasureToken; | ||
1192 | MeasureRepIE.ReportMode = MeasureReqMode; | ||
1193 | MeasureRepIE.ReportType = MeasureReqType; | ||
1194 | InsertMeasureReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, | ||
1195 | &MeasureRepIE, ReportInfoLen, pReportInfo); | ||
1196 | |||
1197 | MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); | ||
1198 | MlmeFreeMemory(pAd, pOutBuffer); | ||
1199 | |||
1200 | return; | ||
1201 | } | ||
1202 | |||
1203 | /* | ||
1204 | ========================================================================== | ||
1205 | Description: | ||
1206 | Prepare TPC Request action frame and enqueue it into | ||
1207 | management queue waiting for transmition. | ||
1208 | |||
1209 | Parametrs: | ||
1210 | 1. the destination mac address of the frame. | ||
1211 | |||
1212 | Return : None. | ||
1213 | ========================================================================== | ||
1214 | */ | ||
1215 | void EnqueueTPCReq(struct rt_rtmp_adapter *pAd, u8 *pDA, u8 DialogToken) | ||
1216 | { | ||
1217 | u8 *pOutBuffer = NULL; | ||
1218 | int NStatus; | ||
1219 | unsigned long FrameLen; | ||
1220 | |||
1221 | struct rt_header_802_11 ActHdr; | ||
1222 | |||
1223 | /* build action frame header. */ | ||
1224 | MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, | ||
1225 | pAd->CurrentAddress); | ||
1226 | |||
1227 | NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */ | ||
1228 | if (NStatus != NDIS_STATUS_SUCCESS) { | ||
1229 | DBGPRINT(RT_DEBUG_TRACE, | ||
1230 | ("%s() allocate memory failed \n", __func__)); | ||
1231 | return; | ||
1232 | } | ||
1233 | NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11)); | ||
1234 | FrameLen = sizeof(struct rt_header_802_11); | ||
1235 | |||
1236 | InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, | ||
1237 | CATEGORY_SPECTRUM, SPEC_TPCRQ); | ||
1238 | |||
1239 | /* fill Dialog Token */ | ||
1240 | InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); | ||
1241 | |||
1242 | /* Insert TPC Request IE. */ | ||
1243 | InsertTpcReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen); | ||
1244 | |||
1245 | MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); | ||
1246 | MlmeFreeMemory(pAd, pOutBuffer); | ||
1247 | |||
1248 | return; | ||
1249 | } | ||
1250 | |||
1251 | /* | ||
1252 | ========================================================================== | ||
1253 | Description: | ||
1254 | Prepare TPC Report action frame and enqueue it into | ||
1255 | management queue waiting for transmition. | ||
1256 | |||
1257 | Parametrs: | ||
1258 | 1. the destination mac address of the frame. | ||
1259 | |||
1260 | Return : None. | ||
1261 | ========================================================================== | ||
1262 | */ | ||
1263 | void EnqueueTPCRep(struct rt_rtmp_adapter *pAd, | ||
1264 | u8 *pDA, | ||
1265 | u8 DialogToken, u8 TxPwr, u8 LinkMargin) | ||
1266 | { | ||
1267 | u8 *pOutBuffer = NULL; | ||
1268 | int NStatus; | ||
1269 | unsigned long FrameLen; | ||
1270 | |||
1271 | struct rt_header_802_11 ActHdr; | ||
1272 | |||
1273 | /* build action frame header. */ | ||
1274 | MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, | ||
1275 | pAd->CurrentAddress); | ||
1276 | |||
1277 | NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */ | ||
1278 | if (NStatus != NDIS_STATUS_SUCCESS) { | ||
1279 | DBGPRINT(RT_DEBUG_TRACE, | ||
1280 | ("%s() allocate memory failed \n", __func__)); | ||
1281 | return; | ||
1282 | } | ||
1283 | NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11)); | ||
1284 | FrameLen = sizeof(struct rt_header_802_11); | ||
1285 | |||
1286 | InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, | ||
1287 | CATEGORY_SPECTRUM, SPEC_TPCRP); | ||
1288 | |||
1289 | /* fill Dialog Token */ | ||
1290 | InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); | ||
1291 | |||
1292 | /* Insert TPC Request IE. */ | ||
1293 | InsertTpcReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, TxPwr, | ||
1294 | LinkMargin); | ||
1295 | |||
1296 | MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); | ||
1297 | MlmeFreeMemory(pAd, pOutBuffer); | ||
1298 | |||
1299 | return; | ||
1300 | } | ||
1301 | |||
1302 | /* | ||
1303 | ========================================================================== | ||
1304 | Description: | ||
1305 | Prepare Channel Switch Announcement action frame and enqueue it into | ||
1306 | management queue waiting for transmition. | ||
1307 | |||
1308 | Parametrs: | ||
1309 | 1. the destination mac address of the frame. | ||
1310 | 2. Channel switch announcement mode. | ||
1311 | 2. a New selected channel. | ||
1312 | |||
1313 | Return : None. | ||
1314 | ========================================================================== | ||
1315 | */ | ||
1316 | void EnqueueChSwAnn(struct rt_rtmp_adapter *pAd, | ||
1317 | u8 *pDA, u8 ChSwMode, u8 NewCh) | ||
1318 | { | ||
1319 | u8 *pOutBuffer = NULL; | ||
1320 | int NStatus; | ||
1321 | unsigned long FrameLen; | ||
1322 | |||
1323 | struct rt_header_802_11 ActHdr; | ||
1324 | |||
1325 | /* build action frame header. */ | ||
1326 | MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, | ||
1327 | pAd->CurrentAddress); | ||
1328 | |||
1329 | NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */ | ||
1330 | if (NStatus != NDIS_STATUS_SUCCESS) { | ||
1331 | DBGPRINT(RT_DEBUG_TRACE, | ||
1332 | ("%s() allocate memory failed \n", __func__)); | ||
1333 | return; | ||
1334 | } | ||
1335 | NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11)); | ||
1336 | FrameLen = sizeof(struct rt_header_802_11); | ||
1337 | |||
1338 | InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, | ||
1339 | CATEGORY_SPECTRUM, SPEC_CHANNEL_SWITCH); | ||
1340 | |||
1341 | InsertChSwAnnIE(pAd, (pOutBuffer + FrameLen), &FrameLen, ChSwMode, | ||
1342 | NewCh, 0); | ||
1343 | |||
1344 | MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); | ||
1345 | MlmeFreeMemory(pAd, pOutBuffer); | ||
1346 | |||
1347 | return; | ||
1348 | } | ||
1349 | |||
1350 | static BOOLEAN DfsRequirementCheck(struct rt_rtmp_adapter *pAd, u8 Channel) | ||
1351 | { | ||
1352 | BOOLEAN Result = FALSE; | ||
1353 | int i; | ||
1354 | |||
1355 | do { | ||
1356 | /* check DFS procedure is running. */ | ||
1357 | /* make sure DFS procedure won't start twice. */ | ||
1358 | if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) { | ||
1359 | Result = FALSE; | ||
1360 | break; | ||
1361 | } | ||
1362 | /* check the new channel carried from Channel Switch Announcemnet is valid. */ | ||
1363 | for (i = 0; i < pAd->ChannelListNum; i++) { | ||
1364 | if ((Channel == pAd->ChannelList[i].Channel) | ||
1365 | && (pAd->ChannelList[i].RemainingTimeForUse == 0)) { | ||
1366 | /* found radar signal in the channel. the channel can't use at least for 30 minutes. */ | ||
1367 | pAd->ChannelList[i].RemainingTimeForUse = 1800; /*30 min = 1800 sec */ | ||
1368 | Result = TRUE; | ||
1369 | break; | ||
1370 | } | ||
1371 | } | ||
1372 | } while (FALSE); | ||
1373 | |||
1374 | return Result; | ||
1375 | } | ||
1376 | |||
1377 | void NotifyChSwAnnToPeerAPs(struct rt_rtmp_adapter *pAd, | ||
1378 | u8 *pRA, | ||
1379 | u8 *pTA, u8 ChSwMode, u8 Channel) | ||
1380 | { | ||
1381 | } | ||
1382 | |||
1383 | static void StartDFSProcedure(struct rt_rtmp_adapter *pAd, | ||
1384 | u8 Channel, u8 ChSwMode) | ||
1385 | { | ||
1386 | /* start DFS procedure */ | ||
1387 | pAd->CommonCfg.Channel = Channel; | ||
1388 | |||
1389 | N_ChannelCheck(pAd); | ||
1390 | |||
1391 | pAd->CommonCfg.RadarDetect.RDMode = RD_SWITCHING_MODE; | ||
1392 | pAd->CommonCfg.RadarDetect.CSCount = 0; | ||
1393 | } | ||
1394 | |||
1395 | /* | ||
1396 | ========================================================================== | ||
1397 | Description: | ||
1398 | Channel Switch Announcement action frame sanity check. | ||
1399 | |||
1400 | Parametrs: | ||
1401 | 1. MLME message containing the received frame | ||
1402 | 2. message length. | ||
1403 | 3. Channel switch announcement information buffer. | ||
1404 | |||
1405 | Return : None. | ||
1406 | ========================================================================== | ||
1407 | */ | ||
1408 | |||
1409 | /* | ||
1410 | Channel Switch Announcement IE. | ||
1411 | +----+-----+-----------+------------+-----------+ | ||
1412 | | ID | Len |Ch Sw Mode | New Ch Num | Ch Sw Cnt | | ||
1413 | +----+-----+-----------+------------+-----------+ | ||
1414 | 1 1 1 1 1 | ||
1415 | */ | ||
1416 | static BOOLEAN PeerChSwAnnSanity(struct rt_rtmp_adapter *pAd, | ||
1417 | void * pMsg, | ||
1418 | unsigned long MsgLen, | ||
1419 | struct rt_ch_sw_ann_info * pChSwAnnInfo) | ||
1420 | { | ||
1421 | struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg; | ||
1422 | u8 *pFramePtr = Fr->Octet; | ||
1423 | BOOLEAN result = FALSE; | ||
1424 | struct rt_eid * eid_ptr; | ||
1425 | |||
1426 | /* skip 802.11 header. */ | ||
1427 | MsgLen -= sizeof(struct rt_header_802_11); | ||
1428 | |||
1429 | /* skip category and action code. */ | ||
1430 | pFramePtr += 2; | ||
1431 | MsgLen -= 2; | ||
1432 | |||
1433 | if (pChSwAnnInfo == NULL) | ||
1434 | return result; | ||
1435 | |||
1436 | eid_ptr = (struct rt_eid *) pFramePtr; | ||
1437 | while (((u8 *) eid_ptr + eid_ptr->Len + 1) < | ||
1438 | ((u8 *)pFramePtr + MsgLen)) { | ||
1439 | switch (eid_ptr->Eid) { | ||
1440 | case IE_CHANNEL_SWITCH_ANNOUNCEMENT: | ||
1441 | NdisMoveMemory(&pChSwAnnInfo->ChSwMode, eid_ptr->Octet, | ||
1442 | 1); | ||
1443 | NdisMoveMemory(&pChSwAnnInfo->Channel, | ||
1444 | eid_ptr->Octet + 1, 1); | ||
1445 | NdisMoveMemory(&pChSwAnnInfo->ChSwCnt, | ||
1446 | eid_ptr->Octet + 2, 1); | ||
1447 | |||
1448 | result = TRUE; | ||
1449 | break; | ||
1450 | |||
1451 | default: | ||
1452 | break; | ||
1453 | } | ||
1454 | eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len); | ||
1455 | } | ||
1456 | |||
1457 | return result; | ||
1458 | } | ||
1459 | |||
1460 | /* | ||
1461 | ========================================================================== | ||
1462 | Description: | ||
1463 | Measurement request action frame sanity check. | ||
1464 | |||
1465 | Parametrs: | ||
1466 | 1. MLME message containing the received frame | ||
1467 | 2. message length. | ||
1468 | 3. Measurement request information buffer. | ||
1469 | |||
1470 | Return : None. | ||
1471 | ========================================================================== | ||
1472 | */ | ||
1473 | static BOOLEAN PeerMeasureReqSanity(struct rt_rtmp_adapter *pAd, | ||
1474 | void * pMsg, | ||
1475 | unsigned long MsgLen, | ||
1476 | u8 *pDialogToken, | ||
1477 | struct rt_measure_req_info * pMeasureReqInfo, | ||
1478 | struct rt_measure_req * pMeasureReq) | ||
1479 | { | ||
1480 | struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg; | ||
1481 | u8 *pFramePtr = Fr->Octet; | ||
1482 | BOOLEAN result = FALSE; | ||
1483 | struct rt_eid * eid_ptr; | ||
1484 | u8 *ptr; | ||
1485 | u64 MeasureStartTime; | ||
1486 | u16 MeasureDuration; | ||
1487 | |||
1488 | /* skip 802.11 header. */ | ||
1489 | MsgLen -= sizeof(struct rt_header_802_11); | ||
1490 | |||
1491 | /* skip category and action code. */ | ||
1492 | pFramePtr += 2; | ||
1493 | MsgLen -= 2; | ||
1494 | |||
1495 | if (pMeasureReqInfo == NULL) | ||
1496 | return result; | ||
1497 | |||
1498 | NdisMoveMemory(pDialogToken, pFramePtr, 1); | ||
1499 | pFramePtr += 1; | ||
1500 | MsgLen -= 1; | ||
1501 | |||
1502 | eid_ptr = (struct rt_eid *) pFramePtr; | ||
1503 | while (((u8 *) eid_ptr + eid_ptr->Len + 1) < | ||
1504 | ((u8 *)pFramePtr + MsgLen)) { | ||
1505 | switch (eid_ptr->Eid) { | ||
1506 | case IE_MEASUREMENT_REQUEST: | ||
1507 | NdisMoveMemory(&pMeasureReqInfo->Token, eid_ptr->Octet, | ||
1508 | 1); | ||
1509 | NdisMoveMemory(&pMeasureReqInfo->ReqMode.word, | ||
1510 | eid_ptr->Octet + 1, 1); | ||
1511 | NdisMoveMemory(&pMeasureReqInfo->ReqType, | ||
1512 | eid_ptr->Octet + 2, 1); | ||
1513 | ptr = (u8 *)(eid_ptr->Octet + 3); | ||
1514 | NdisMoveMemory(&pMeasureReq->ChNum, ptr, 1); | ||
1515 | NdisMoveMemory(&MeasureStartTime, ptr + 1, 8); | ||
1516 | pMeasureReq->MeasureStartTime = | ||
1517 | SWAP64(MeasureStartTime); | ||
1518 | NdisMoveMemory(&MeasureDuration, ptr + 9, 2); | ||
1519 | pMeasureReq->MeasureDuration = SWAP16(MeasureDuration); | ||
1520 | |||
1521 | result = TRUE; | ||
1522 | break; | ||
1523 | |||
1524 | default: | ||
1525 | break; | ||
1526 | } | ||
1527 | eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len); | ||
1528 | } | ||
1529 | |||
1530 | return result; | ||
1531 | } | ||
1532 | |||
1533 | /* | ||
1534 | ========================================================================== | ||
1535 | Description: | ||
1536 | Measurement report action frame sanity check. | ||
1537 | |||
1538 | Parametrs: | ||
1539 | 1. MLME message containing the received frame | ||
1540 | 2. message length. | ||
1541 | 3. Measurement report information buffer. | ||
1542 | 4. basic report information buffer. | ||
1543 | |||
1544 | Return : None. | ||
1545 | ========================================================================== | ||
1546 | */ | ||
1547 | |||
1548 | /* | ||
1549 | Measurement Report IE. | ||
1550 | +----+-----+-------+-------------+--------------+----------------+ | ||
1551 | | ID | Len | Token | Report Mode | Measure Type | Measure Report | | ||
1552 | +----+-----+-------+-------------+--------------+----------------+ | ||
1553 | 1 1 1 1 1 variable | ||
1554 | |||
1555 | Basic Report. | ||
1556 | +--------+------------+----------+-----+ | ||
1557 | | Ch Num | Start Time | Duration | Map | | ||
1558 | +--------+------------+----------+-----+ | ||
1559 | 1 8 2 1 | ||
1560 | |||
1561 | Map Field Bit Format. | ||
1562 | +-----+---------------+---------------------+-------+------------+----------+ | ||
1563 | | Bss | OFDM Preamble | Unidentified signal | Radar | Unmeasured | Reserved | | ||
1564 | +-----+---------------+---------------------+-------+------------+----------+ | ||
1565 | 0 1 2 3 4 5-7 | ||
1566 | */ | ||
1567 | static BOOLEAN PeerMeasureReportSanity(struct rt_rtmp_adapter *pAd, | ||
1568 | void * pMsg, | ||
1569 | unsigned long MsgLen, | ||
1570 | u8 *pDialogToken, | ||
1571 | struct rt_measure_report_info * | ||
1572 | pMeasureReportInfo, | ||
1573 | u8 *pReportBuf) | ||
1574 | { | ||
1575 | struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg; | ||
1576 | u8 *pFramePtr = Fr->Octet; | ||
1577 | BOOLEAN result = FALSE; | ||
1578 | struct rt_eid * eid_ptr; | ||
1579 | u8 *ptr; | ||
1580 | |||
1581 | /* skip 802.11 header. */ | ||
1582 | MsgLen -= sizeof(struct rt_header_802_11); | ||
1583 | |||
1584 | /* skip category and action code. */ | ||
1585 | pFramePtr += 2; | ||
1586 | MsgLen -= 2; | ||
1587 | |||
1588 | if (pMeasureReportInfo == NULL) | ||
1589 | return result; | ||
1590 | |||
1591 | NdisMoveMemory(pDialogToken, pFramePtr, 1); | ||
1592 | pFramePtr += 1; | ||
1593 | MsgLen -= 1; | ||
1594 | |||
1595 | eid_ptr = (struct rt_eid *) pFramePtr; | ||
1596 | while (((u8 *) eid_ptr + eid_ptr->Len + 1) < | ||
1597 | ((u8 *)pFramePtr + MsgLen)) { | ||
1598 | switch (eid_ptr->Eid) { | ||
1599 | case IE_MEASUREMENT_REPORT: | ||
1600 | NdisMoveMemory(&pMeasureReportInfo->Token, | ||
1601 | eid_ptr->Octet, 1); | ||
1602 | NdisMoveMemory(&pMeasureReportInfo->ReportMode, | ||
1603 | eid_ptr->Octet + 1, 1); | ||
1604 | NdisMoveMemory(&pMeasureReportInfo->ReportType, | ||
1605 | eid_ptr->Octet + 2, 1); | ||
1606 | if (pMeasureReportInfo->ReportType == RM_BASIC) { | ||
1607 | struct rt_measure_basic_report * pReport = | ||
1608 | (struct rt_measure_basic_report *) pReportBuf; | ||
1609 | ptr = (u8 *)(eid_ptr->Octet + 3); | ||
1610 | NdisMoveMemory(&pReport->ChNum, ptr, 1); | ||
1611 | NdisMoveMemory(&pReport->MeasureStartTime, | ||
1612 | ptr + 1, 8); | ||
1613 | NdisMoveMemory(&pReport->MeasureDuration, | ||
1614 | ptr + 9, 2); | ||
1615 | NdisMoveMemory(&pReport->Map, ptr + 11, 1); | ||
1616 | |||
1617 | } else if (pMeasureReportInfo->ReportType == RM_CCA) { | ||
1618 | struct rt_measure_cca_report * pReport = | ||
1619 | (struct rt_measure_cca_report *) pReportBuf; | ||
1620 | ptr = (u8 *)(eid_ptr->Octet + 3); | ||
1621 | NdisMoveMemory(&pReport->ChNum, ptr, 1); | ||
1622 | NdisMoveMemory(&pReport->MeasureStartTime, | ||
1623 | ptr + 1, 8); | ||
1624 | NdisMoveMemory(&pReport->MeasureDuration, | ||
1625 | ptr + 9, 2); | ||
1626 | NdisMoveMemory(&pReport->CCA_Busy_Fraction, | ||
1627 | ptr + 11, 1); | ||
1628 | |||
1629 | } else if (pMeasureReportInfo->ReportType == | ||
1630 | RM_RPI_HISTOGRAM) { | ||
1631 | struct rt_measure_rpi_report * pReport = | ||
1632 | (struct rt_measure_rpi_report *) pReportBuf; | ||
1633 | ptr = (u8 *)(eid_ptr->Octet + 3); | ||
1634 | NdisMoveMemory(&pReport->ChNum, ptr, 1); | ||
1635 | NdisMoveMemory(&pReport->MeasureStartTime, | ||
1636 | ptr + 1, 8); | ||
1637 | NdisMoveMemory(&pReport->MeasureDuration, | ||
1638 | ptr + 9, 2); | ||
1639 | NdisMoveMemory(&pReport->RPI_Density, ptr + 11, | ||
1640 | 8); | ||
1641 | } | ||
1642 | result = TRUE; | ||
1643 | break; | ||
1644 | |||
1645 | default: | ||
1646 | break; | ||
1647 | } | ||
1648 | eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len); | ||
1649 | } | ||
1650 | |||
1651 | return result; | ||
1652 | } | ||
1653 | |||
1654 | /* | ||
1655 | ========================================================================== | ||
1656 | Description: | ||
1657 | TPC Request action frame sanity check. | ||
1658 | |||
1659 | Parametrs: | ||
1660 | 1. MLME message containing the received frame | ||
1661 | 2. message length. | ||
1662 | 3. Dialog Token. | ||
1663 | |||
1664 | Return : None. | ||
1665 | ========================================================================== | ||
1666 | */ | ||
1667 | static BOOLEAN PeerTpcReqSanity(struct rt_rtmp_adapter *pAd, | ||
1668 | void * pMsg, | ||
1669 | unsigned long MsgLen, u8 *pDialogToken) | ||
1670 | { | ||
1671 | struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg; | ||
1672 | u8 *pFramePtr = Fr->Octet; | ||
1673 | BOOLEAN result = FALSE; | ||
1674 | struct rt_eid * eid_ptr; | ||
1675 | |||
1676 | MsgLen -= sizeof(struct rt_header_802_11); | ||
1677 | |||
1678 | /* skip category and action code. */ | ||
1679 | pFramePtr += 2; | ||
1680 | MsgLen -= 2; | ||
1681 | |||
1682 | if (pDialogToken == NULL) | ||
1683 | return result; | ||
1684 | |||
1685 | NdisMoveMemory(pDialogToken, pFramePtr, 1); | ||
1686 | pFramePtr += 1; | ||
1687 | MsgLen -= 1; | ||
1688 | |||
1689 | eid_ptr = (struct rt_eid *) pFramePtr; | ||
1690 | while (((u8 *) eid_ptr + eid_ptr->Len + 1) < | ||
1691 | ((u8 *)pFramePtr + MsgLen)) { | ||
1692 | switch (eid_ptr->Eid) { | ||
1693 | case IE_TPC_REQUEST: | ||
1694 | result = TRUE; | ||
1695 | break; | ||
1696 | |||
1697 | default: | ||
1698 | break; | ||
1699 | } | ||
1700 | eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len); | ||
1701 | } | ||
1702 | |||
1703 | return result; | ||
1704 | } | ||
1705 | |||
1706 | /* | ||
1707 | ========================================================================== | ||
1708 | Description: | ||
1709 | TPC Report action frame sanity check. | ||
1710 | |||
1711 | Parametrs: | ||
1712 | 1. MLME message containing the received frame | ||
1713 | 2. message length. | ||
1714 | 3. Dialog Token. | ||
1715 | 4. TPC Report IE. | ||
1716 | |||
1717 | Return : None. | ||
1718 | ========================================================================== | ||
1719 | */ | ||
1720 | static BOOLEAN PeerTpcRepSanity(struct rt_rtmp_adapter *pAd, | ||
1721 | void * pMsg, | ||
1722 | unsigned long MsgLen, | ||
1723 | u8 *pDialogToken, | ||
1724 | struct rt_tpc_report_info * pTpcRepInfo) | ||
1725 | { | ||
1726 | struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg; | ||
1727 | u8 *pFramePtr = Fr->Octet; | ||
1728 | BOOLEAN result = FALSE; | ||
1729 | struct rt_eid * eid_ptr; | ||
1730 | |||
1731 | MsgLen -= sizeof(struct rt_header_802_11); | ||
1732 | |||
1733 | /* skip category and action code. */ | ||
1734 | pFramePtr += 2; | ||
1735 | MsgLen -= 2; | ||
1736 | |||
1737 | if (pDialogToken == NULL) | ||
1738 | return result; | ||
1739 | |||
1740 | NdisMoveMemory(pDialogToken, pFramePtr, 1); | ||
1741 | pFramePtr += 1; | ||
1742 | MsgLen -= 1; | ||
1743 | |||
1744 | eid_ptr = (struct rt_eid *) pFramePtr; | ||
1745 | while (((u8 *) eid_ptr + eid_ptr->Len + 1) < | ||
1746 | ((u8 *)pFramePtr + MsgLen)) { | ||
1747 | switch (eid_ptr->Eid) { | ||
1748 | case IE_TPC_REPORT: | ||
1749 | NdisMoveMemory(&pTpcRepInfo->TxPwr, eid_ptr->Octet, 1); | ||
1750 | NdisMoveMemory(&pTpcRepInfo->LinkMargin, | ||
1751 | eid_ptr->Octet + 1, 1); | ||
1752 | result = TRUE; | ||
1753 | break; | ||
1754 | |||
1755 | default: | ||
1756 | break; | ||
1757 | } | ||
1758 | eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len); | ||
1759 | } | ||
1760 | |||
1761 | return result; | ||
1762 | } | ||
1763 | |||
1764 | /* | ||
1765 | ========================================================================== | ||
1766 | Description: | ||
1767 | Channel Switch Announcement action frame handler. | ||
1768 | |||
1769 | Parametrs: | ||
1770 | Elme - MLME message containing the received frame | ||
1771 | |||
1772 | Return : None. | ||
1773 | ========================================================================== | ||
1774 | */ | ||
1775 | static void PeerChSwAnnAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) | ||
1776 | { | ||
1777 | struct rt_ch_sw_ann_info ChSwAnnInfo; | ||
1778 | struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg; | ||
1779 | u8 index = 0, Channel = 0, NewChannel = 0; | ||
1780 | unsigned long Bssidx = 0; | ||
1781 | |||
1782 | NdisZeroMemory(&ChSwAnnInfo, sizeof(struct rt_ch_sw_ann_info)); | ||
1783 | if (!PeerChSwAnnSanity(pAd, Elem->Msg, Elem->MsgLen, &ChSwAnnInfo)) { | ||
1784 | DBGPRINT(RT_DEBUG_TRACE, | ||
1785 | ("Invalid Channel Switch Action Frame.\n")); | ||
1786 | return; | ||
1787 | } | ||
1788 | |||
1789 | if (pAd->OpMode == OPMODE_STA) { | ||
1790 | Bssidx = | ||
1791 | BssTableSearch(&pAd->ScanTab, pFr->Hdr.Addr3, | ||
1792 | pAd->CommonCfg.Channel); | ||
1793 | if (Bssidx == BSS_NOT_FOUND) { | ||
1794 | DBGPRINT(RT_DEBUG_TRACE, | ||
1795 | ("PeerChSwAnnAction - Bssidx is not found\n")); | ||
1796 | return; | ||
1797 | } | ||
1798 | |||
1799 | DBGPRINT(RT_DEBUG_TRACE, | ||
1800 | ("\n****Bssidx is %d, Channel = %d\n", index, | ||
1801 | pAd->ScanTab.BssEntry[Bssidx].Channel)); | ||
1802 | hex_dump("SSID", pAd->ScanTab.BssEntry[Bssidx].Bssid, 6); | ||
1803 | |||
1804 | Channel = pAd->CommonCfg.Channel; | ||
1805 | NewChannel = ChSwAnnInfo.Channel; | ||
1806 | |||
1807 | if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) | ||
1808 | && (Channel != NewChannel)) { | ||
1809 | /* Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection). */ | ||
1810 | /* In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results. */ | ||
1811 | AsicSwitchChannel(pAd, 1, FALSE); | ||
1812 | AsicLockChannel(pAd, 1); | ||
1813 | LinkDown(pAd, FALSE); | ||
1814 | MlmeQueueInit(&pAd->Mlme.Queue); | ||
1815 | BssTableInit(&pAd->ScanTab); | ||
1816 | RTMPusecDelay(1000000); /* use delay to prevent STA do reassoc */ | ||
1817 | |||
1818 | /* channel sanity check */ | ||
1819 | for (index = 0; index < pAd->ChannelListNum; index++) { | ||
1820 | if (pAd->ChannelList[index].Channel == | ||
1821 | NewChannel) { | ||
1822 | pAd->ScanTab.BssEntry[Bssidx].Channel = | ||
1823 | NewChannel; | ||
1824 | pAd->CommonCfg.Channel = NewChannel; | ||
1825 | AsicSwitchChannel(pAd, | ||
1826 | pAd->CommonCfg. | ||
1827 | Channel, FALSE); | ||
1828 | AsicLockChannel(pAd, | ||
1829 | pAd->CommonCfg.Channel); | ||
1830 | DBGPRINT(RT_DEBUG_TRACE, | ||
1831 | ("&&&&&&&&&&&&&&&&PeerChSwAnnAction - STA receive channel switch announcement IE (New Channel =%d)\n", | ||
1832 | NewChannel)); | ||
1833 | break; | ||
1834 | } | ||
1835 | } | ||
1836 | |||
1837 | if (index >= pAd->ChannelListNum) { | ||
1838 | DBGPRINT_ERR("&&&&&&&&&&&&&&&&&&&&&&&&&&PeerChSwAnnAction(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum); | ||
1839 | } | ||
1840 | } | ||
1841 | } | ||
1842 | |||
1843 | return; | ||
1844 | } | ||
1845 | |||
1846 | /* | ||
1847 | ========================================================================== | ||
1848 | Description: | ||
1849 | Measurement Request action frame handler. | ||
1850 | |||
1851 | Parametrs: | ||
1852 | Elme - MLME message containing the received frame | ||
1853 | |||
1854 | Return : None. | ||
1855 | ========================================================================== | ||
1856 | */ | ||
1857 | static void PeerMeasureReqAction(struct rt_rtmp_adapter *pAd, | ||
1858 | struct rt_mlme_queue_elem *Elem) | ||
1859 | { | ||
1860 | struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg; | ||
1861 | u8 DialogToken; | ||
1862 | struct rt_measure_req_info MeasureReqInfo; | ||
1863 | struct rt_measure_req MeasureReq; | ||
1864 | MEASURE_REPORT_MODE ReportMode; | ||
1865 | |||
1866 | if (PeerMeasureReqSanity | ||
1867 | (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo, | ||
1868 | &MeasureReq)) { | ||
1869 | ReportMode.word = 0; | ||
1870 | ReportMode.field.Incapable = 1; | ||
1871 | EnqueueMeasurementRep(pAd, pFr->Hdr.Addr2, DialogToken, | ||
1872 | MeasureReqInfo.Token, ReportMode.word, | ||
1873 | MeasureReqInfo.ReqType, 0, NULL); | ||
1874 | } | ||
1875 | |||
1876 | return; | ||
1877 | } | ||
1878 | |||
1879 | /* | ||
1880 | ========================================================================== | ||
1881 | Description: | ||
1882 | Measurement Report action frame handler. | ||
1883 | |||
1884 | Parametrs: | ||
1885 | Elme - MLME message containing the received frame | ||
1886 | |||
1887 | Return : None. | ||
1888 | ========================================================================== | ||
1889 | */ | ||
1890 | static void PeerMeasureReportAction(struct rt_rtmp_adapter *pAd, | ||
1891 | struct rt_mlme_queue_elem *Elem) | ||
1892 | { | ||
1893 | struct rt_measure_report_info MeasureReportInfo; | ||
1894 | struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg; | ||
1895 | u8 DialogToken; | ||
1896 | u8 *pMeasureReportInfo; | ||
1897 | |||
1898 | /* if (pAd->CommonCfg.bIEEE80211H != TRUE) */ | ||
1899 | /* return; */ | ||
1900 | |||
1901 | pMeasureReportInfo = kmalloc(sizeof(struct rt_measure_rpi_report), GFP_ATOMIC); | ||
1902 | if (pMeasureReportInfo == NULL) { | ||
1903 | DBGPRINT(RT_DEBUG_ERROR, | ||
1904 | ("%s unable to alloc memory for measure report buffer (size=%zu).\n", | ||
1905 | __func__, sizeof(struct rt_measure_rpi_report))); | ||
1906 | return; | ||
1907 | } | ||
1908 | |||
1909 | NdisZeroMemory(&MeasureReportInfo, sizeof(struct rt_measure_report_info)); | ||
1910 | NdisZeroMemory(pMeasureReportInfo, sizeof(struct rt_measure_rpi_report)); | ||
1911 | if (PeerMeasureReportSanity | ||
1912 | (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReportInfo, | ||
1913 | pMeasureReportInfo)) { | ||
1914 | do { | ||
1915 | struct rt_measure_req_entry *pEntry = NULL; | ||
1916 | |||
1917 | /* Not a autonomous measure report. */ | ||
1918 | /* check the dialog token field. drop it if the dialog token doesn't match. */ | ||
1919 | if ((DialogToken != 0) | ||
1920 | && ((pEntry = MeasureReqLookUp(pAd, DialogToken)) == | ||
1921 | NULL)) | ||
1922 | break; | ||
1923 | |||
1924 | if (pEntry != NULL) | ||
1925 | MeasureReqDelete(pAd, pEntry->DialogToken); | ||
1926 | |||
1927 | if (MeasureReportInfo.ReportType == RM_BASIC) { | ||
1928 | struct rt_measure_basic_report * pBasicReport = | ||
1929 | (struct rt_measure_basic_report *) pMeasureReportInfo; | ||
1930 | if ((pBasicReport->Map.field.Radar) | ||
1931 | && | ||
1932 | (DfsRequirementCheck | ||
1933 | (pAd, pBasicReport->ChNum) == TRUE)) { | ||
1934 | NotifyChSwAnnToPeerAPs(pAd, | ||
1935 | pFr->Hdr.Addr1, | ||
1936 | pFr->Hdr.Addr2, | ||
1937 | 1, | ||
1938 | pBasicReport-> | ||
1939 | ChNum); | ||
1940 | StartDFSProcedure(pAd, | ||
1941 | pBasicReport->ChNum, | ||
1942 | 1); | ||
1943 | } | ||
1944 | } | ||
1945 | } while (FALSE); | ||
1946 | } else | ||
1947 | DBGPRINT(RT_DEBUG_TRACE, | ||
1948 | ("Invalid Measurement Report Frame.\n")); | ||
1949 | |||
1950 | kfree(pMeasureReportInfo); | ||
1951 | |||
1952 | return; | ||
1953 | } | ||
1954 | |||
1955 | /* | ||
1956 | ========================================================================== | ||
1957 | Description: | ||
1958 | TPC Request action frame handler. | ||
1959 | |||
1960 | Parametrs: | ||
1961 | Elme - MLME message containing the received frame | ||
1962 | |||
1963 | Return : None. | ||
1964 | ========================================================================== | ||
1965 | */ | ||
1966 | static void PeerTpcReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) | ||
1967 | { | ||
1968 | struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg; | ||
1969 | u8 *pFramePtr = pFr->Octet; | ||
1970 | u8 DialogToken; | ||
1971 | u8 TxPwr = GetCurTxPwr(pAd, Elem->Wcid); | ||
1972 | u8 LinkMargin = 0; | ||
1973 | char RealRssi; | ||
1974 | |||
1975 | /* link margin: Ratio of the received signal power to the minimum desired by the station (STA). The */ | ||
1976 | /* STA may incorporate rate information and channel conditions, including interference, into its computation */ | ||
1977 | /* of link margin. */ | ||
1978 | |||
1979 | RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), | ||
1980 | ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), | ||
1981 | ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); | ||
1982 | |||
1983 | /* skip Category and action code. */ | ||
1984 | pFramePtr += 2; | ||
1985 | |||
1986 | /* Dialog token. */ | ||
1987 | NdisMoveMemory(&DialogToken, pFramePtr, 1); | ||
1988 | |||
1989 | LinkMargin = (RealRssi / MIN_RCV_PWR); | ||
1990 | if (PeerTpcReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken)) | ||
1991 | EnqueueTPCRep(pAd, pFr->Hdr.Addr2, DialogToken, TxPwr, | ||
1992 | LinkMargin); | ||
1993 | |||
1994 | return; | ||
1995 | } | ||
1996 | |||
1997 | /* | ||
1998 | ========================================================================== | ||
1999 | Description: | ||
2000 | TPC Report action frame handler. | ||
2001 | |||
2002 | Parametrs: | ||
2003 | Elme - MLME message containing the received frame | ||
2004 | |||
2005 | Return : None. | ||
2006 | ========================================================================== | ||
2007 | */ | ||
2008 | static void PeerTpcRepAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) | ||
2009 | { | ||
2010 | u8 DialogToken; | ||
2011 | struct rt_tpc_report_info TpcRepInfo; | ||
2012 | struct rt_tpc_req_entry *pEntry = NULL; | ||
2013 | |||
2014 | NdisZeroMemory(&TpcRepInfo, sizeof(struct rt_tpc_report_info)); | ||
2015 | if (PeerTpcRepSanity | ||
2016 | (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &TpcRepInfo)) { | ||
2017 | pEntry = TpcReqLookUp(pAd, DialogToken); | ||
2018 | if (pEntry != NULL) { | ||
2019 | TpcReqDelete(pAd, pEntry->DialogToken); | ||
2020 | DBGPRINT(RT_DEBUG_TRACE, | ||
2021 | ("%s: DialogToken=%x, TxPwr=%d, LinkMargin=%d\n", | ||
2022 | __func__, DialogToken, TpcRepInfo.TxPwr, | ||
2023 | TpcRepInfo.LinkMargin)); | ||
2024 | } | ||
2025 | } | ||
2026 | |||
2027 | return; | ||
2028 | } | ||
2029 | |||
2030 | /* | ||
2031 | ========================================================================== | ||
2032 | Description: | ||
2033 | Spectrun action frames Handler such as channel switch annoucement, | ||
2034 | measurement report, measurement request actions frames. | ||
2035 | |||
2036 | Parametrs: | ||
2037 | Elme - MLME message containing the received frame | ||
2038 | |||
2039 | Return : None. | ||
2040 | ========================================================================== | ||
2041 | */ | ||
2042 | void PeerSpectrumAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) | ||
2043 | { | ||
2044 | |||
2045 | u8 Action = Elem->Msg[LENGTH_802_11 + 1]; | ||
2046 | |||
2047 | if (pAd->CommonCfg.bIEEE80211H != TRUE) | ||
2048 | return; | ||
2049 | |||
2050 | switch (Action) { | ||
2051 | case SPEC_MRQ: | ||
2052 | /* current rt2860 unable do such measure specified in Measurement Request. */ | ||
2053 | /* reject all measurement request. */ | ||
2054 | PeerMeasureReqAction(pAd, Elem); | ||
2055 | break; | ||
2056 | |||
2057 | case SPEC_MRP: | ||
2058 | PeerMeasureReportAction(pAd, Elem); | ||
2059 | break; | ||
2060 | |||
2061 | case SPEC_TPCRQ: | ||
2062 | PeerTpcReqAction(pAd, Elem); | ||
2063 | break; | ||
2064 | |||
2065 | case SPEC_TPCRP: | ||
2066 | PeerTpcRepAction(pAd, Elem); | ||
2067 | break; | ||
2068 | |||
2069 | case SPEC_CHANNEL_SWITCH: | ||
2070 | |||
2071 | PeerChSwAnnAction(pAd, Elem); | ||
2072 | break; | ||
2073 | } | ||
2074 | |||
2075 | return; | ||
2076 | } | ||
2077 | |||
2078 | /* | ||
2079 | ========================================================================== | ||
2080 | Description: | ||
2081 | |||
2082 | Parametrs: | ||
2083 | |||
2084 | Return : None. | ||
2085 | ========================================================================== | ||
2086 | */ | ||
2087 | int Set_MeasureReq_Proc(struct rt_rtmp_adapter *pAd, char *arg) | ||
2088 | { | ||
2089 | u32 Aid = 1; | ||
2090 | u32 ArgIdx; | ||
2091 | char *thisChar; | ||
2092 | |||
2093 | MEASURE_REQ_MODE MeasureReqMode; | ||
2094 | u8 MeasureReqToken = RandomByte(pAd); | ||
2095 | u8 MeasureReqType = RM_BASIC; | ||
2096 | u8 MeasureCh = 1; | ||
2097 | u64 MeasureStartTime = GetCurrentTimeStamp(pAd); | ||
2098 | struct rt_measure_req MeasureReq; | ||
2099 | u8 TotalLen; | ||
2100 | |||
2101 | struct rt_header_802_11 ActHdr; | ||
2102 | u8 *pOutBuffer = NULL; | ||
2103 | int NStatus; | ||
2104 | unsigned long FrameLen; | ||
2105 | |||
2106 | NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */ | ||
2107 | if (NStatus != NDIS_STATUS_SUCCESS) { | ||
2108 | DBGPRINT(RT_DEBUG_TRACE, | ||
2109 | ("%s() allocate memory failed \n", __func__)); | ||
2110 | goto END_OF_MEASURE_REQ; | ||
2111 | } | ||
2112 | |||
2113 | ArgIdx = 1; | ||
2114 | while ((thisChar = strsep((char **)&arg, "-")) != NULL) { | ||
2115 | switch (ArgIdx) { | ||
2116 | case 1: /* Aid. */ | ||
2117 | Aid = (u8)simple_strtol(thisChar, 0, 16); | ||
2118 | break; | ||
2119 | |||
2120 | case 2: /* Measurement Request Type. */ | ||
2121 | MeasureReqType = simple_strtol(thisChar, 0, 16); | ||
2122 | if (MeasureReqType > 3) { | ||
2123 | DBGPRINT(RT_DEBUG_ERROR, | ||
2124 | ("%s: unknow MeasureReqType(%d)\n", | ||
2125 | __func__, MeasureReqType)); | ||
2126 | goto END_OF_MEASURE_REQ; | ||
2127 | } | ||
2128 | break; | ||
2129 | |||
2130 | case 3: /* Measurement channel. */ | ||
2131 | MeasureCh = (u8)simple_strtol(thisChar, 0, 16); | ||
2132 | break; | ||
2133 | } | ||
2134 | ArgIdx++; | ||
2135 | } | ||
2136 | |||
2137 | DBGPRINT(RT_DEBUG_TRACE, | ||
2138 | ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __func__, | ||
2139 | Aid, MeasureReqType, MeasureCh)); | ||
2140 | if (!VALID_WCID(Aid)) { | ||
2141 | DBGPRINT(RT_DEBUG_ERROR, | ||
2142 | ("%s: unknow sta of Aid(%d)\n", __func__, Aid)); | ||
2143 | goto END_OF_MEASURE_REQ; | ||
2144 | } | ||
2145 | |||
2146 | MeasureReqMode.word = 0; | ||
2147 | MeasureReqMode.field.Enable = 1; | ||
2148 | |||
2149 | MeasureReqInsert(pAd, MeasureReqToken); | ||
2150 | |||
2151 | /* build action frame header. */ | ||
2152 | MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, | ||
2153 | pAd->MacTab.Content[Aid].Addr, pAd->CurrentAddress); | ||
2154 | |||
2155 | NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11)); | ||
2156 | FrameLen = sizeof(struct rt_header_802_11); | ||
2157 | |||
2158 | TotalLen = sizeof(struct rt_measure_req_info) + sizeof(struct rt_measure_req); | ||
2159 | |||
2160 | MakeMeasurementReqFrame(pAd, pOutBuffer, &FrameLen, | ||
2161 | sizeof(struct rt_measure_req_info), CATEGORY_RM, RM_BASIC, | ||
2162 | MeasureReqToken, MeasureReqMode.word, | ||
2163 | MeasureReqType, 0); | ||
2164 | |||
2165 | MeasureReq.ChNum = MeasureCh; | ||
2166 | MeasureReq.MeasureStartTime = cpu2le64(MeasureStartTime); | ||
2167 | MeasureReq.MeasureDuration = cpu2le16(2000); | ||
2168 | |||
2169 | { | ||
2170 | unsigned long TempLen; | ||
2171 | MakeOutgoingFrame(pOutBuffer + FrameLen, &TempLen, | ||
2172 | sizeof(struct rt_measure_req), &MeasureReq, | ||
2173 | END_OF_ARGS); | ||
2174 | FrameLen += TempLen; | ||
2175 | } | ||
2176 | |||
2177 | MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, (u32)FrameLen); | ||
2178 | |||
2179 | END_OF_MEASURE_REQ: | ||
2180 | MlmeFreeMemory(pAd, pOutBuffer); | ||
2181 | |||
2182 | return TRUE; | ||
2183 | } | ||
2184 | |||
2185 | int Set_TpcReq_Proc(struct rt_rtmp_adapter *pAd, char *arg) | ||
2186 | { | ||
2187 | u32 Aid; | ||
2188 | |||
2189 | u8 TpcReqToken = RandomByte(pAd); | ||
2190 | |||
2191 | Aid = (u32)simple_strtol(arg, 0, 16); | ||
2192 | |||
2193 | DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d\n", __func__, Aid)); | ||
2194 | if (!VALID_WCID(Aid)) { | ||
2195 | DBGPRINT(RT_DEBUG_ERROR, | ||
2196 | ("%s: unknow sta of Aid(%d)\n", __func__, Aid)); | ||
2197 | return TRUE; | ||
2198 | } | ||
2199 | |||
2200 | TpcReqInsert(pAd, TpcReqToken); | ||
2201 | |||
2202 | EnqueueTPCReq(pAd, pAd->MacTab.Content[Aid].Addr, TpcReqToken); | ||
2203 | |||
2204 | return TRUE; | ||
2205 | } | ||