aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/rt3070/common/action.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2009-02-25 19:14:55 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2009-04-03 17:54:24 -0400
commite642f09951f7cbb69983781b07bb9cd881546ac4 (patch)
treec783967792f17f0abfab38c9a893fb9565b8bae2 /drivers/staging/rt3070/common/action.c
parent21a6a6e9f81fb26fbcecbb1304018d34dcd1794f (diff)
Staging: add rt3070 wireless driver
This is the Ralink RT3070 driver from the company that does horrible things like reading a config file from /etc. However, the driver that is currently under development from the wireless development community is not working at all yet, so distros and users are using this version instead (quite common hardware on a lot of netbook machines). So here is this driver, for now, until the wireless developers get a "clean" version into the main tree, or until this version is cleaned up sufficiently to move out of the staging tree. Ported to the Linux build system, fixed lots of build issues, forward ported to the current kernel version, and other minor cleanups were all done by me. Cc: Linux wireless <linux-wireless@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/rt3070/common/action.c')
-rw-r--r--drivers/staging/rt3070/common/action.c1038
1 files changed, 1038 insertions, 0 deletions
diff --git a/drivers/staging/rt3070/common/action.c b/drivers/staging/rt3070/common/action.c
new file mode 100644
index 00000000000..b8ae5363366
--- /dev/null
+++ b/drivers/staging/rt3070/common/action.c
@@ -0,0 +1,1038 @@
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
43static VOID ReservedAction(
44 IN PRTMP_ADAPTER pAd,
45 IN MLME_QUEUE_ELEM *Elem);
46
47/*
48 ==========================================================================
49 Description:
50 association state machine init, including state transition and timer init
51 Parameters:
52 S - pointer to the association state machine
53 Note:
54 The state machine looks like the following
55
56 ASSOC_IDLE
57 MT2_MLME_DISASSOC_REQ mlme_disassoc_req_action
58 MT2_PEER_DISASSOC_REQ peer_disassoc_action
59 MT2_PEER_ASSOC_REQ drop
60 MT2_PEER_REASSOC_REQ drop
61 MT2_CLS3ERR cls3err_action
62 ==========================================================================
63 */
64VOID ActionStateMachineInit(
65 IN PRTMP_ADAPTER pAd,
66 IN STATE_MACHINE *S,
67 OUT STATE_MACHINE_FUNC Trans[])
68{
69 StateMachineInit(S, (STATE_MACHINE_FUNC *)Trans, MAX_ACT_STATE, MAX_ACT_MSG, (STATE_MACHINE_FUNC)Drop, ACT_IDLE, ACT_MACHINE_BASE);
70
71 StateMachineSetAction(S, ACT_IDLE, MT2_PEER_SPECTRUM_CATE, (STATE_MACHINE_FUNC)PeerSpectrumAction);
72 StateMachineSetAction(S, ACT_IDLE, MT2_PEER_QOS_CATE, (STATE_MACHINE_FUNC)PeerQOSAction);
73
74 StateMachineSetAction(S, ACT_IDLE, MT2_PEER_DLS_CATE, (STATE_MACHINE_FUNC)ReservedAction);
75#ifdef QOS_DLS_SUPPORT
76 StateMachineSetAction(S, ACT_IDLE, MT2_PEER_DLS_CATE, (STATE_MACHINE_FUNC)PeerDLSAction);
77#endif // QOS_DLS_SUPPORT //
78
79#ifdef DOT11_N_SUPPORT
80 StateMachineSetAction(S, ACT_IDLE, MT2_PEER_BA_CATE, (STATE_MACHINE_FUNC)PeerBAAction);
81 StateMachineSetAction(S, ACT_IDLE, MT2_PEER_HT_CATE, (STATE_MACHINE_FUNC)PeerHTAction);
82 StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ADD_BA_CATE, (STATE_MACHINE_FUNC)MlmeADDBAAction);
83 StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ORI_DELBA_CATE, (STATE_MACHINE_FUNC)MlmeDELBAAction);
84 StateMachineSetAction(S, ACT_IDLE, MT2_MLME_REC_DELBA_CATE, (STATE_MACHINE_FUNC)MlmeDELBAAction);
85#endif // DOT11_N_SUPPORT //
86
87 StateMachineSetAction(S, ACT_IDLE, MT2_PEER_PUBLIC_CATE, (STATE_MACHINE_FUNC)PeerPublicAction);
88 StateMachineSetAction(S, ACT_IDLE, MT2_PEER_RM_CATE, (STATE_MACHINE_FUNC)PeerRMAction);
89
90 StateMachineSetAction(S, ACT_IDLE, MT2_MLME_QOS_CATE, (STATE_MACHINE_FUNC)MlmeQOSAction);
91 StateMachineSetAction(S, ACT_IDLE, MT2_MLME_DLS_CATE, (STATE_MACHINE_FUNC)MlmeDLSAction);
92 StateMachineSetAction(S, ACT_IDLE, MT2_ACT_INVALID, (STATE_MACHINE_FUNC)MlmeInvalidAction);
93}
94
95#ifdef DOT11_N_SUPPORT
96VOID MlmeADDBAAction(
97 IN PRTMP_ADAPTER pAd,
98 IN MLME_QUEUE_ELEM *Elem)
99
100{
101 MLME_ADDBA_REQ_STRUCT *pInfo;
102 UCHAR Addr[6];
103 PUCHAR pOutBuffer = NULL;
104 NDIS_STATUS NStatus;
105 ULONG Idx;
106 FRAME_ADDBA_REQ Frame;
107 ULONG FrameLen;
108 BA_ORI_ENTRY *pBAEntry = NULL;
109
110 pInfo = (MLME_ADDBA_REQ_STRUCT *)Elem->Msg;
111 NdisZeroMemory(&Frame, sizeof(FRAME_ADDBA_REQ));
112
113 if(MlmeAddBAReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr))
114 {
115 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
116 if(NStatus != NDIS_STATUS_SUCCESS)
117 {
118 DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeADDBAAction() allocate memory failed \n"));
119 return;
120 }
121 // 1. find entry
122 Idx = pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID];
123 if (Idx == 0)
124 {
125 MlmeFreeMemory(pAd, pOutBuffer);
126 DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() can't find BAOriEntry \n"));
127 return;
128 }
129 else
130 {
131 pBAEntry =&pAd->BATable.BAOriEntry[Idx];
132 }
133
134#ifdef CONFIG_STA_SUPPORT
135 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
136 {
137 if (ADHOC_ON(pAd))
138 ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
139 else
140 ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pInfo->pAddr);
141
142 }
143#endif // CONFIG_STA_SUPPORT //
144
145 Frame.Category = CATEGORY_BA;
146 Frame.Action = ADDBA_REQ;
147 Frame.BaParm.AMSDUSupported = 0;
148 Frame.BaParm.BAPolicy = IMMED_BA;
149 Frame.BaParm.TID = pInfo->TID;
150 Frame.BaParm.BufSize = pInfo->BaBufSize;
151 Frame.Token = pInfo->Token;
152 Frame.TimeOutValue = pInfo->TimeOutValue;
153 Frame.BaStartSeq.field.FragNum = 0;
154 Frame.BaStartSeq.field.StartSeq = pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID];
155
156 *(USHORT *)(&Frame.BaParm) = cpu2le16(*(USHORT *)(&Frame.BaParm));
157 Frame.TimeOutValue = cpu2le16(Frame.TimeOutValue);
158 Frame.BaStartSeq.word = cpu2le16(Frame.BaStartSeq.word);
159
160 MakeOutgoingFrame(pOutBuffer, &FrameLen,
161 sizeof(FRAME_ADDBA_REQ), &Frame,
162 END_OF_ARGS);
163 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
164 //MiniportDataMMRequest(pAd, MapUserPriorityToAccessCategory[pInfo->TID], pOutBuffer, FrameLen);
165 MlmeFreeMemory(pAd, pOutBuffer);
166
167 DBGPRINT(RT_DEBUG_TRACE, ("BA - Send ADDBA request. StartSeq = %x, FrameLen = %ld. BufSize = %d\n", Frame.BaStartSeq.field.StartSeq, FrameLen, Frame.BaParm.BufSize));
168 }
169}
170
171/*
172 ==========================================================================
173 Description:
174 send DELBA and delete BaEntry if any
175 Parametrs:
176 Elem - MLME message MLME_DELBA_REQ_STRUCT
177
178 IRQL = DISPATCH_LEVEL
179
180 ==========================================================================
181 */
182VOID MlmeDELBAAction(
183 IN PRTMP_ADAPTER pAd,
184 IN MLME_QUEUE_ELEM *Elem)
185{
186 MLME_DELBA_REQ_STRUCT *pInfo;
187 PUCHAR pOutBuffer = NULL;
188 PUCHAR pOutBuffer2 = NULL;
189 NDIS_STATUS NStatus;
190 ULONG Idx;
191 FRAME_DELBA_REQ Frame;
192 ULONG FrameLen;
193 FRAME_BAR FrameBar;
194
195 pInfo = (MLME_DELBA_REQ_STRUCT *)Elem->Msg;
196 // must send back DELBA
197 NdisZeroMemory(&Frame, sizeof(FRAME_DELBA_REQ));
198 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeDELBAAction(), Initiator(%d) \n", pInfo->Initiator));
199
200 if(MlmeDelBAReqSanity(pAd, Elem->Msg, Elem->MsgLen))
201 {
202 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
203 if(NStatus != NDIS_STATUS_SUCCESS)
204 {
205 DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeDELBAAction() allocate memory failed 1. \n"));
206 return;
207 }
208
209 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); //Get an unused nonpaged memory
210 if(NStatus != NDIS_STATUS_SUCCESS)
211 {
212 MlmeFreeMemory(pAd, pOutBuffer);
213 DBGPRINT(RT_DEBUG_ERROR, ("BA - MlmeDELBAAction() allocate memory failed 2. \n"));
214 return;
215 }
216
217 // SEND BAR (Send BAR to refresh peer reordering buffer.)
218 Idx = pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID];
219
220#ifdef CONFIG_STA_SUPPORT
221 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
222 BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->CurrentAddress);
223#endif // CONFIG_STA_SUPPORT //
224
225 FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL funciton.
226 FrameBar.StartingSeq.field.StartSeq = pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID]; // make sure sequence not clear in DEL funciton.
227 FrameBar.BarControl.TID = pInfo->TID; // make sure sequence not clear in DEL funciton.
228 FrameBar.BarControl.ACKPolicy = IMMED_BA; // make sure sequence not clear in DEL funciton.
229 FrameBar.BarControl.Compressed = 1; // make sure sequence not clear in DEL funciton.
230 FrameBar.BarControl.MTID = 0; // make sure sequence not clear in DEL funciton.
231
232 MakeOutgoingFrame(pOutBuffer2, &FrameLen,
233 sizeof(FRAME_BAR), &FrameBar,
234 END_OF_ARGS);
235 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen);
236 MlmeFreeMemory(pAd, pOutBuffer2);
237 DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeDELBAAction() . Send BAR to refresh peer reordering buffer \n"));
238
239 // SEND DELBA FRAME
240 FrameLen = 0;
241#ifdef CONFIG_STA_SUPPORT
242 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
243 {
244 if (ADHOC_ON(pAd))
245 ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
246 else
247 ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->MacTab.Content[pInfo->Wcid].Addr);
248 }
249#endif // CONFIG_STA_SUPPORT //
250 Frame.Category = CATEGORY_BA;
251 Frame.Action = DELBA;
252 Frame.DelbaParm.Initiator = pInfo->Initiator;
253 Frame.DelbaParm.TID = pInfo->TID;
254 Frame.ReasonCode = 39; // Time Out
255 *(USHORT *)(&Frame.DelbaParm) = cpu2le16(*(USHORT *)(&Frame.DelbaParm));
256 Frame.ReasonCode = cpu2le16(Frame.ReasonCode);
257
258 MakeOutgoingFrame(pOutBuffer, &FrameLen,
259 sizeof(FRAME_DELBA_REQ), &Frame,
260 END_OF_ARGS);
261 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
262 MlmeFreeMemory(pAd, pOutBuffer);
263 DBGPRINT(RT_DEBUG_TRACE, ("BA - MlmeDELBAAction() . 3 DELBA sent. Initiator(%d)\n", pInfo->Initiator));
264 }
265}
266#endif // DOT11_N_SUPPORT //
267
268VOID MlmeQOSAction(
269 IN PRTMP_ADAPTER pAd,
270 IN MLME_QUEUE_ELEM *Elem)
271{
272}
273
274VOID MlmeDLSAction(
275 IN PRTMP_ADAPTER pAd,
276 IN MLME_QUEUE_ELEM *Elem)
277{
278}
279
280VOID MlmeInvalidAction(
281 IN PRTMP_ADAPTER pAd,
282 IN MLME_QUEUE_ELEM *Elem)
283{
284 //PUCHAR pOutBuffer = NULL;
285 //Return the receiving frame except the MSB of category filed set to 1. 7.3.1.11
286}
287
288VOID PeerQOSAction(
289 IN PRTMP_ADAPTER pAd,
290 IN MLME_QUEUE_ELEM *Elem)
291{
292}
293
294#ifdef QOS_DLS_SUPPORT
295VOID PeerDLSAction(
296 IN PRTMP_ADAPTER pAd,
297 IN MLME_QUEUE_ELEM *Elem)
298{
299 UCHAR Action = Elem->Msg[LENGTH_802_11+1];
300
301 switch(Action)
302 {
303 case ACTION_DLS_REQUEST:
304#ifdef CONFIG_STA_SUPPORT
305 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
306 PeerDlsReqAction(pAd, Elem);
307#endif // CONFIG_STA_SUPPORT //
308 break;
309
310 case ACTION_DLS_RESPONSE:
311#ifdef CONFIG_STA_SUPPORT
312 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
313 PeerDlsRspAction(pAd, Elem);
314#endif // CONFIG_STA_SUPPORT //
315 break;
316
317 case ACTION_DLS_TEARDOWN:
318#ifdef CONFIG_STA_SUPPORT
319 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
320 PeerDlsTearDownAction(pAd, Elem);
321#endif // CONFIG_STA_SUPPORT //
322 break;
323 }
324}
325#endif // QOS_DLS_SUPPORT //
326
327#ifdef DOT11_N_SUPPORT
328VOID PeerBAAction(
329 IN PRTMP_ADAPTER pAd,
330 IN MLME_QUEUE_ELEM *Elem)
331{
332 UCHAR Action = Elem->Msg[LENGTH_802_11+1];
333
334 switch(Action)
335 {
336 case ADDBA_REQ:
337 PeerAddBAReqAction(pAd,Elem);
338 break;
339 case ADDBA_RESP:
340 PeerAddBARspAction(pAd,Elem);
341 break;
342 case DELBA:
343 PeerDelBAAction(pAd,Elem);
344 break;
345 }
346}
347
348
349#ifdef DOT11N_DRAFT3
350
351#ifdef CONFIG_STA_SUPPORT
352VOID StaPublicAction(
353 IN PRTMP_ADAPTER pAd,
354 IN UCHAR Bss2040Coexist)
355{
356 BSS_2040_COEXIST_IE BssCoexist;
357 MLME_SCAN_REQ_STRUCT ScanReq;
358
359 BssCoexist.word = Bss2040Coexist;
360 // AP asks Station to return a 20/40 BSS Coexistence mgmt frame. So we first starts a scan, then send back 20/40 BSS Coexistence mgmt frame
361 if ((BssCoexist.field.InfoReq == 1) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040)))
362 {
363 // Clear record first. After scan , will update those bit and send back to transmiter.
364 pAd->CommonCfg.BSSCoexist2040.field.InfoReq = 1;
365 pAd->CommonCfg.BSSCoexist2040.field.Intolerant40 = 0;
366 pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq = 0;
367 // Fill out stuff for scan request
368 ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_2040_BSS_COEXIST);
369 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
370 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
371 }
372}
373
374
375/*
376Description : Build Intolerant Channel Rerpot from Trigger event table.
377return : how many bytes copied.
378*/
379ULONG BuildIntolerantChannelRep(
380 IN PRTMP_ADAPTER pAd,
381 IN PUCHAR pDest)
382{
383 ULONG FrameLen = 0;
384 ULONG ReadOffset = 0;
385 UCHAR i;
386 UCHAR LastRegClass = 0xff;
387 PUCHAR pLen;
388
389 for ( i = 0;i < MAX_TRIGGER_EVENT;i++)
390 {
391 if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid == TRUE)
392 {
393 if (pAd->CommonCfg.TriggerEventTab.EventA[i].RegClass == LastRegClass)
394 {
395 *(pDest + ReadOffset) = (UCHAR)pAd->CommonCfg.TriggerEventTab.EventA[i].Channel;
396 *pLen++;
397 ReadOffset++;
398 FrameLen++;
399 }
400 else
401 {
402 *(pDest + ReadOffset) = IE_2040_BSS_INTOLERANT_REPORT; // IE
403 *(pDest + ReadOffset + 1) = 2; // Len = RegClass byte + channel byte.
404 pLen = pDest + ReadOffset + 1;
405 LastRegClass = pAd->CommonCfg.TriggerEventTab.EventA[i].RegClass;
406 *(pDest + ReadOffset + 2) = LastRegClass; // Len = RegClass byte + channel byte.
407 *(pDest + ReadOffset + 3) = (UCHAR)pAd->CommonCfg.TriggerEventTab.EventA[i].Channel;
408 FrameLen += 4;
409 ReadOffset += 4;
410 }
411
412 }
413 }
414 return FrameLen;
415}
416
417
418/*
419Description : Send 20/40 BSS Coexistence Action frame If one trigger event is triggered.
420*/
421VOID Send2040CoexistAction(
422 IN PRTMP_ADAPTER pAd,
423 IN UCHAR Wcid,
424 IN BOOLEAN bAddIntolerantCha)
425{
426 PUCHAR pOutBuffer = NULL;
427 NDIS_STATUS NStatus;
428 FRAME_ACTION_HDR Frame;
429 ULONG FrameLen;
430 ULONG IntolerantChaRepLen;
431
432 IntolerantChaRepLen = 0;
433 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
434 if(NStatus != NDIS_STATUS_SUCCESS)
435 {
436 DBGPRINT(RT_DEBUG_ERROR,("ACT - Send2040CoexistAction() allocate memory failed \n"));
437 return;
438 }
439 ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pAd->CommonCfg.Bssid);
440 Frame.Category = CATEGORY_PUBLIC;
441 Frame.Action = ACTION_BSS_2040_COEXIST;
442
443 MakeOutgoingFrame(pOutBuffer, &FrameLen,
444 sizeof(FRAME_ACTION_HDR), &Frame,
445 END_OF_ARGS);
446
447 *(pOutBuffer + FrameLen) = pAd->CommonCfg.BSSCoexist2040.word;
448 FrameLen++;
449
450 if (bAddIntolerantCha == TRUE)
451 IntolerantChaRepLen = BuildIntolerantChannelRep(pAd, pOutBuffer + FrameLen);
452
453 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen + IntolerantChaRepLen);
454 DBGPRINT(RT_DEBUG_ERROR,("ACT - Send2040CoexistAction( BSSCoexist2040 = 0x%x ) \n", pAd->CommonCfg.BSSCoexist2040.word));
455
456}
457
458
459/*
460 ==========================================================================
461 Description:
462 After scan, Update 20/40 BSS Coexistence IE and send out.
463 According to 802.11n D3.03 11.14.10
464
465 Parameters:
466 ==========================================================================
467 */
468VOID Update2040CoexistFrameAndNotify(
469 IN PRTMP_ADAPTER pAd,
470 IN UCHAR Wcid,
471 IN BOOLEAN bAddIntolerantCha)
472{
473 BSS_2040_COEXIST_IE OldValue;
474
475 OldValue.word = pAd->CommonCfg.BSSCoexist2040.word;
476 if ((pAd->CommonCfg.TriggerEventTab.EventANo > 0) || (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0))
477 pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq = 1;
478
479 // Need to check !!!!
480 // How STA will set Intolerant40 if implementation dependent. Now we don't set this bit first.!!!!!
481 // So Only check BSS20WidthReq change.
482 if (OldValue.field.BSS20WidthReq != pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq)
483 {
484 Send2040CoexistAction(pAd, Wcid, bAddIntolerantCha);
485 }
486}
487#endif // CONFIG_STA_SUPPORT //
488
489
490BOOLEAN ChannelSwitchSanityCheck(
491 IN PRTMP_ADAPTER pAd,
492 IN UCHAR Wcid,
493 IN UCHAR NewChannel,
494 IN UCHAR Secondary)
495{
496 UCHAR i;
497
498 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
499 return FALSE;
500
501 if ((NewChannel > 7) && (Secondary == 1))
502 return FALSE;
503
504 if ((NewChannel < 5) && (Secondary == 3))
505 return FALSE;
506
507 // 0. Check if new channel is in the channellist.
508 for (i = 0;i < pAd->ChannelListNum;i++)
509 {
510 if (pAd->ChannelList[i].Channel == NewChannel)
511 {
512 break;
513 }
514 }
515
516 if (i == pAd->ChannelListNum)
517 return FALSE;
518
519 return TRUE;
520}
521
522
523VOID ChannelSwitchAction(
524 IN PRTMP_ADAPTER pAd,
525 IN UCHAR Wcid,
526 IN UCHAR NewChannel,
527 IN UCHAR Secondary)
528{
529 UCHAR BBPValue = 0;
530 ULONG MACValue;
531
532 DBGPRINT(RT_DEBUG_TRACE,("SPECTRUM - ChannelSwitchAction(NewChannel = %d , Secondary = %d) \n", NewChannel, Secondary));
533
534 if (ChannelSwitchSanityCheck(pAd, Wcid, NewChannel, Secondary) == FALSE)
535 return;
536
537 // 1. Switches to BW = 20.
538 if (Secondary == 0)
539 {
540 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
541 BBPValue&= (~0x18);
542 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
543 if (pAd->MACVersion == 0x28600100)
544 {
545 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16);
546 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x08);
547 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x11);
548 DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" ));
549 }
550 pAd->CommonCfg.BBPCurrentBW = BW_20;
551 pAd->CommonCfg.Channel = NewChannel;
552 pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel;
553 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel,FALSE);
554 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
555 pAd->MacTab.Content[Wcid].HTPhyMode.field.BW = 0;
556 DBGPRINT(RT_DEBUG_TRACE, ("!!!20MHz !!! \n" ));
557 }
558 // 1. Switches to BW = 40 And Station supports BW = 40.
559 else if (((Secondary == 1) || (Secondary == 3)) && (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == 1))
560 {
561 pAd->CommonCfg.Channel = NewChannel;
562
563 if (Secondary == 1)
564 {
565 // Secondary above.
566 pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2;
567 RTMP_IO_READ32(pAd, TX_BAND_CFG, &MACValue);
568 MACValue &= 0xfe;
569 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, MACValue);
570 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
571 BBPValue&= (~0x18);
572 BBPValue|= (0x10);
573 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
574 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPValue);
575 BBPValue&= (~0x20);
576 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPValue);
577 DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Lower LINK UP !!! Control Channel at Below. Central = %d \n", pAd->CommonCfg.CentralChannel ));
578 }
579 else
580 {
581 // Secondary below.
582 pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2;
583 RTMP_IO_READ32(pAd, TX_BAND_CFG, &MACValue);
584 MACValue &= 0xfe;
585 MACValue |= 0x1;
586 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, MACValue);
587 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
588 BBPValue&= (~0x18);
589 BBPValue|= (0x10);
590 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
591 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPValue);
592 BBPValue&= (~0x20);
593 BBPValue|= (0x20);
594 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPValue);
595 DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Upper LINK UP !!! Control Channel at UpperCentral = %d \n", pAd->CommonCfg.CentralChannel ));
596 }
597 pAd->CommonCfg.BBPCurrentBW = BW_40;
598 AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
599 AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
600 pAd->MacTab.Content[Wcid].HTPhyMode.field.BW = 1;
601 }
602}
603#endif // DOT11N_DRAFT3 //
604#endif // DOT11_N_SUPPORT //
605
606VOID PeerPublicAction(
607 IN PRTMP_ADAPTER pAd,
608 IN MLME_QUEUE_ELEM *Elem)
609{
610#ifdef DOT11N_DRAFT3
611 UCHAR Action = Elem->Msg[LENGTH_802_11+1];
612#endif // DOT11N_DRAFT3 //
613
614 if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
615 return;
616
617#ifdef DOT11N_DRAFT3
618 switch(Action)
619 {
620 case ACTION_BSS_2040_COEXIST: // Format defined in IEEE 7.4.7a.1 in 11n Draf3.03
621 {
622 //UCHAR BssCoexist;
623 BSS_2040_COEXIST_ELEMENT *pCoexistInfo;
624 BSS_2040_COEXIST_IE *pBssCoexistIe;
625 BSS_2040_INTOLERANT_CH_REPORT *pIntolerantReport = NULL;
626
627 if (Elem->MsgLen <= (LENGTH_802_11 + sizeof(BSS_2040_COEXIST_ELEMENT)) )
628 {
629 DBGPRINT(RT_DEBUG_ERROR, ("ACTION - 20/40 BSS Coexistence Management Frame length too short! len = %ld!\n", Elem->MsgLen));
630 break;
631 }
632 DBGPRINT(RT_DEBUG_TRACE, ("ACTION - 20/40 BSS Coexistence Management action----> \n"));
633 hex_dump("CoexistenceMgmtFrame", Elem->Msg, Elem->MsgLen);
634
635
636 pCoexistInfo = (BSS_2040_COEXIST_ELEMENT *) &Elem->Msg[LENGTH_802_11+2];
637 //hex_dump("CoexistInfo", (PUCHAR)pCoexistInfo, sizeof(BSS_2040_COEXIST_ELEMENT));
638 if (Elem->MsgLen >= (LENGTH_802_11 + sizeof(BSS_2040_COEXIST_ELEMENT) + sizeof(BSS_2040_INTOLERANT_CH_REPORT)))
639 {
640 pIntolerantReport = (BSS_2040_INTOLERANT_CH_REPORT *)((PUCHAR)pCoexistInfo + sizeof(BSS_2040_COEXIST_ELEMENT));
641 }
642 //hex_dump("IntolerantReport ", (PUCHAR)pIntolerantReport, sizeof(BSS_2040_INTOLERANT_CH_REPORT));
643
644 pBssCoexistIe = (BSS_2040_COEXIST_IE *)(&pCoexistInfo->BssCoexistIe);
645
646#ifdef CONFIG_STA_SUPPORT
647 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
648 {
649 if (INFRA_ON(pAd))
650 {
651 StaPublicAction(pAd, pCoexistInfo);
652 }
653 }
654#endif // CONFIG_STA_SUPPORT //
655
656 }
657 break;
658 }
659
660#endif // DOT11N_DRAFT3 //
661
662}
663
664
665static VOID ReservedAction(
666 IN PRTMP_ADAPTER pAd,
667 IN MLME_QUEUE_ELEM *Elem)
668{
669 UCHAR Category;
670
671 if (Elem->MsgLen <= LENGTH_802_11)
672 {
673 return;
674 }
675
676 Category = Elem->Msg[LENGTH_802_11];
677 DBGPRINT(RT_DEBUG_TRACE,("Rcv reserved category(%d) Action Frame\n", Category));
678 hex_dump("Reserved Action Frame", &Elem->Msg[0], Elem->MsgLen);
679}
680
681VOID PeerRMAction(
682 IN PRTMP_ADAPTER pAd,
683 IN MLME_QUEUE_ELEM *Elem)
684
685{
686 return;
687}
688
689#ifdef DOT11_N_SUPPORT
690static VOID respond_ht_information_exchange_action(
691 IN PRTMP_ADAPTER pAd,
692 IN MLME_QUEUE_ELEM *Elem)
693{
694 PUCHAR pOutBuffer = NULL;
695 NDIS_STATUS NStatus;
696 ULONG FrameLen;
697 FRAME_HT_INFO HTINFOframe, *pFrame;
698 UCHAR *pAddr;
699
700
701 // 2. Always send back ADDBA Response
702 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
703
704 if (NStatus != NDIS_STATUS_SUCCESS)
705 {
706 DBGPRINT(RT_DEBUG_TRACE,("ACTION - respond_ht_information_exchange_action() allocate memory failed \n"));
707 return;
708 }
709
710 // get RA
711 pFrame = (FRAME_HT_INFO *) &Elem->Msg[0];
712 pAddr = pFrame->Hdr.Addr2;
713
714 NdisZeroMemory(&HTINFOframe, sizeof(FRAME_HT_INFO));
715 // 2-1. Prepare ADDBA Response frame.
716#ifdef CONFIG_STA_SUPPORT
717 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
718 {
719 if (ADHOC_ON(pAd))
720 ActHeaderInit(pAd, &HTINFOframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
721 else
722 ActHeaderInit(pAd, &HTINFOframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr);
723 }
724#endif // CONFIG_STA_SUPPORT //
725
726 HTINFOframe.Category = CATEGORY_HT;
727 HTINFOframe.Action = HT_INFO_EXCHANGE;
728 HTINFOframe.HT_Info.Request = 0;
729 HTINFOframe.HT_Info.Forty_MHz_Intolerant = pAd->CommonCfg.HtCapability.HtCapInfo.Forty_Mhz_Intolerant;
730 HTINFOframe.HT_Info.STA_Channel_Width = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth;
731
732 MakeOutgoingFrame(pOutBuffer, &FrameLen,
733 sizeof(FRAME_HT_INFO), &HTINFOframe,
734 END_OF_ARGS);
735
736 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
737 MlmeFreeMemory(pAd, pOutBuffer);
738}
739
740
741#ifdef DOT11N_DRAFT3
742VOID SendNotifyBWActionFrame(
743 IN PRTMP_ADAPTER pAd,
744 IN UCHAR Wcid,
745 IN UCHAR apidx)
746{
747 PUCHAR pOutBuffer = NULL;
748 NDIS_STATUS NStatus;
749 FRAME_ACTION_HDR Frame;
750 ULONG FrameLen;
751 PUCHAR pAddr1;
752
753
754 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
755 if(NStatus != NDIS_STATUS_SUCCESS)
756 {
757 DBGPRINT(RT_DEBUG_ERROR,("ACT - SendNotifyBWAction() allocate memory failed \n"));
758 return;
759 }
760
761 if (Wcid == MCAST_WCID)
762 pAddr1 = &BROADCAST_ADDR[0];
763 else
764 pAddr1 = pAd->MacTab.Content[Wcid].Addr;
765 ActHeaderInit(pAd, &Frame.Hdr, pAddr1, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid);
766
767 Frame.Category = CATEGORY_HT;
768 Frame.Action = NOTIFY_BW_ACTION;
769
770 MakeOutgoingFrame(pOutBuffer, &FrameLen,
771 sizeof(FRAME_ACTION_HDR), &Frame,
772 END_OF_ARGS);
773
774 *(pOutBuffer + FrameLen) = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth;
775 FrameLen++;
776
777
778 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
779 DBGPRINT(RT_DEBUG_TRACE,("ACT - SendNotifyBWAction(NotifyBW= %d)!\n", pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth));
780
781}
782#endif // DOT11N_DRAFT3 //
783
784
785VOID PeerHTAction(
786 IN PRTMP_ADAPTER pAd,
787 IN MLME_QUEUE_ELEM *Elem)
788{
789 UCHAR Action = Elem->Msg[LENGTH_802_11+1];
790
791 if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
792 return;
793
794 switch(Action)
795 {
796 case NOTIFY_BW_ACTION:
797 DBGPRINT(RT_DEBUG_TRACE,("ACTION - HT Notify Channel bandwidth action----> \n"));
798#ifdef CONFIG_STA_SUPPORT
799 if(pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
800 {
801 // Note, this is to patch DIR-1353 AP. When the AP set to Wep, it will use legacy mode. But AP still keeps
802 // sending BW_Notify Action frame, and cause us to linkup and linkdown.
803 // In legacy mode, don't need to parse HT action frame.
804 DBGPRINT(RT_DEBUG_TRACE,("ACTION -Ignore HT Notify Channel BW when link as legacy mode. BW = %d---> \n",
805 Elem->Msg[LENGTH_802_11+2] ));
806 break;
807 }
808#endif // CONFIG_STA_SUPPORT //
809
810 if (Elem->Msg[LENGTH_802_11+2] == 0) // 7.4.8.2. if value is 1, keep the same as supported channel bandwidth.
811 pAd->MacTab.Content[Elem->Wcid].HTPhyMode.field.BW = 0;
812
813 break;
814
815 case SMPS_ACTION:
816 // 7.3.1.25
817 DBGPRINT(RT_DEBUG_TRACE,("ACTION - SMPS action----> \n"));
818 if (((Elem->Msg[LENGTH_802_11+2]&0x1) == 0))
819 {
820 pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_ENABLE;
821 }
822 else if (((Elem->Msg[LENGTH_802_11+2]&0x2) == 0))
823 {
824 pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_STATIC;
825 }
826 else
827 {
828 pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_DYNAMIC;
829 }
830
831 DBGPRINT(RT_DEBUG_TRACE,("Aid(%d) MIMO PS = %d\n", Elem->Wcid, pAd->MacTab.Content[Elem->Wcid].MmpsMode));
832 // rt2860c : add something for smps change.
833 break;
834
835 case SETPCO_ACTION:
836 break;
837
838 case MIMO_CHA_MEASURE_ACTION:
839 break;
840
841 case HT_INFO_EXCHANGE:
842 {
843 HT_INFORMATION_OCTET *pHT_info;
844
845 pHT_info = (HT_INFORMATION_OCTET *) &Elem->Msg[LENGTH_802_11+2];
846 // 7.4.8.10
847 DBGPRINT(RT_DEBUG_TRACE,("ACTION - HT Information Exchange action----> \n"));
848 if (pHT_info->Request)
849 {
850 respond_ht_information_exchange_action(pAd, Elem);
851 }
852 }
853 break;
854 }
855}
856
857
858/*
859 ==========================================================================
860 Description:
861 Retry sending ADDBA Reqest.
862
863 IRQL = DISPATCH_LEVEL
864
865 Parametrs:
866 p8023Header: if this is already 802.3 format, p8023Header is NULL
867
868 Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
869 FALSE , then continue indicaterx at this moment.
870 ==========================================================================
871 */
872VOID ORIBATimerTimeout(
873 IN PRTMP_ADAPTER pAd)
874{
875 MAC_TABLE_ENTRY *pEntry;
876 INT i, total;
877// FRAME_BAR FrameBar;
878// ULONG FrameLen;
879// NDIS_STATUS NStatus;
880// PUCHAR pOutBuffer = NULL;
881// USHORT Sequence;
882 UCHAR TID;
883
884#ifdef RALINK_ATE
885 if (ATE_ON(pAd))
886 return;
887#endif // RALINK_ATE //
888
889 total = pAd->MacTab.Size * NUM_OF_TID;
890
891 for (i = 1; ((i <MAX_LEN_OF_BA_ORI_TABLE) && (total > 0)) ; i++)
892 {
893 if (pAd->BATable.BAOriEntry[i].ORI_BA_Status == Originator_Done)
894 {
895 pEntry = &pAd->MacTab.Content[pAd->BATable.BAOriEntry[i].Wcid];
896 TID = pAd->BATable.BAOriEntry[i].TID;
897
898 ASSERT(pAd->BATable.BAOriEntry[i].Wcid < MAX_LEN_OF_MAC_TABLE);
899 }
900 total --;
901 }
902}
903
904
905VOID SendRefreshBAR(
906 IN PRTMP_ADAPTER pAd,
907 IN MAC_TABLE_ENTRY *pEntry)
908{
909 FRAME_BAR FrameBar;
910 ULONG FrameLen;
911 NDIS_STATUS NStatus;
912 PUCHAR pOutBuffer = NULL;
913 USHORT Sequence;
914 UCHAR i, TID;
915 USHORT idx;
916 BA_ORI_ENTRY *pBAEntry;
917
918 for (i = 0; i <NUM_OF_TID; i++)
919 {
920 idx = pEntry->BAOriWcidArray[i];
921 if (idx == 0)
922 {
923 continue;
924 }
925 pBAEntry = &pAd->BATable.BAOriEntry[idx];
926
927 if (pBAEntry->ORI_BA_Status == Originator_Done)
928 {
929 TID = pBAEntry->TID;
930
931 ASSERT(pBAEntry->Wcid < MAX_LEN_OF_MAC_TABLE);
932
933 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
934 if(NStatus != NDIS_STATUS_SUCCESS)
935 {
936 DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n"));
937 return;
938 }
939
940 Sequence = pEntry->TxSeq[TID];
941
942
943#ifdef CONFIG_STA_SUPPORT
944 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
945 BarHeaderInit(pAd, &FrameBar, pEntry->Addr, pAd->CurrentAddress);
946#endif // CONFIG_STA_SUPPORT //
947
948 FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL function.
949 FrameBar.StartingSeq.field.StartSeq = Sequence; // make sure sequence not clear in DEL funciton.
950 FrameBar.BarControl.TID = TID; // make sure sequence not clear in DEL funciton.
951
952 MakeOutgoingFrame(pOutBuffer, &FrameLen,
953 sizeof(FRAME_BAR), &FrameBar,
954 END_OF_ARGS);
955 //if (!(CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET)))
956 if (1) // Now we always send BAR.
957 {
958 //MiniportMMRequestUnlock(pAd, 0, pOutBuffer, FrameLen);
959 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
960 //MiniportDataMMRequest(pAd, MapUserPriorityToAccessCategory[TID], pOutBuffer, FrameLen);
961 }
962 MlmeFreeMemory(pAd, pOutBuffer);
963 }
964 }
965}
966#endif // DOT11_N_SUPPORT //
967
968VOID ActHeaderInit(
969 IN PRTMP_ADAPTER pAd,
970 IN OUT PHEADER_802_11 pHdr80211,
971 IN PUCHAR Addr1,
972 IN PUCHAR Addr2,
973 IN PUCHAR Addr3)
974{
975 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
976 pHdr80211->FC.Type = BTYPE_MGMT;
977 pHdr80211->FC.SubType = SUBTYPE_ACTION;
978
979 COPY_MAC_ADDR(pHdr80211->Addr1, Addr1);
980 COPY_MAC_ADDR(pHdr80211->Addr2, Addr2);
981 COPY_MAC_ADDR(pHdr80211->Addr3, Addr3);
982}
983
984VOID BarHeaderInit(
985 IN PRTMP_ADAPTER pAd,
986 IN OUT PFRAME_BAR pCntlBar,
987 IN PUCHAR pDA,
988 IN PUCHAR pSA)
989{
990// USHORT Duration;
991
992 NdisZeroMemory(pCntlBar, sizeof(FRAME_BAR));
993 pCntlBar->FC.Type = BTYPE_CNTL;
994 pCntlBar->FC.SubType = SUBTYPE_BLOCK_ACK_REQ;
995 pCntlBar->BarControl.MTID = 0;
996 pCntlBar->BarControl.Compressed = 1;
997 pCntlBar->BarControl.ACKPolicy = 0;
998
999
1000 pCntlBar->Duration = 16 + RTMPCalcDuration(pAd, RATE_1, sizeof(FRAME_BA));
1001
1002 COPY_MAC_ADDR(pCntlBar->Addr1, pDA);
1003 COPY_MAC_ADDR(pCntlBar->Addr2, pSA);
1004}
1005
1006
1007/*
1008 ==========================================================================
1009 Description:
1010 Insert Category and action code into the action frame.
1011
1012 Parametrs:
1013 1. frame buffer pointer.
1014 2. frame length.
1015 3. category code of the frame.
1016 4. action code of the frame.
1017
1018 Return : None.
1019 ==========================================================================
1020 */
1021VOID InsertActField(
1022 IN PRTMP_ADAPTER pAd,
1023 OUT PUCHAR pFrameBuf,
1024 OUT PULONG pFrameLen,
1025 IN UINT8 Category,
1026 IN UINT8 ActCode)
1027{
1028 ULONG TempLen;
1029
1030 MakeOutgoingFrame( pFrameBuf, &TempLen,
1031 1, &Category,
1032 1, &ActCode,
1033 END_OF_ARGS);
1034
1035 *pFrameLen = *pFrameLen + TempLen;
1036
1037 return;
1038}