Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
staging
vt6656
power.c
Go to the documentation of this file.
1
/*
2
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
3
* All rights reserved.
4
*
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
9
*
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
14
*
15
* You should have received a copy of the GNU General Public License along
16
* with this program; if not, write to the Free Software Foundation, Inc.,
17
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
*
20
* File: power.c
21
*
22
* Purpose: Handles 802.11 power management functions
23
*
24
* Author: Lyndon Chen
25
*
26
* Date: July 17, 2002
27
*
28
* Functions:
29
* PSvEnablePowerSaving - Enable Power Saving Mode
30
* PSvDiasblePowerSaving - Disable Power Saving Mode
31
* PSbConsiderPowerDown - Decide if we can Power Down
32
* PSvSendPSPOLL - Send PS-POLL packet
33
* PSbSendNullPacket - Send Null packet
34
* PSbIsNextTBTTWakeUp - Decide if we need to wake up at next Beacon
35
*
36
* Revision History:
37
*
38
*/
39
40
#include "
ttype.h
"
41
#include "
mac.h
"
42
#include "
device.h
"
43
#include "
wmgr.h
"
44
#include "
power.h
"
45
#include "
wcmd.h
"
46
#include "
rxtx.h
"
47
#include "
card.h
"
48
#include "
control.h
"
49
#include "
rndis.h
"
50
51
/*--------------------- Static Definitions -------------------------*/
52
53
/*--------------------- Static Classes ----------------------------*/
54
55
/*--------------------- Static Variables --------------------------*/
56
static
int
msglevel =
MSG_LEVEL_INFO
;
57
/*--------------------- Static Functions --------------------------*/
58
59
/*--------------------- Export Variables --------------------------*/
60
61
/*--------------------- Export Functions --------------------------*/
62
63
/*
64
*
65
* Routine Description:
66
* Enable hw power saving functions
67
*
68
* Return Value:
69
* None.
70
*
71
*/
72
73
void
PSvEnablePowerSaving
(
void
*hDeviceContext,
74
WORD
wListenInterval)
75
{
76
PSDevice
pDevice = (
PSDevice
)hDeviceContext;
77
PSMgmtObject
pMgmt = &(pDevice->
sMgmtObj
);
78
WORD
wAID = pMgmt->
wCurrAID
|
BIT14
|
BIT15
;
79
80
/* set period of power up before TBTT */
81
MACvWriteWord
(pDevice,
MAC_REG_PWBT
,
C_PWBT
);
82
83
if
(pDevice->
eOPMode
!=
OP_MODE_ADHOC
) {
84
/* set AID */
85
MACvWriteWord
(pDevice,
MAC_REG_AIDATIM
, wAID);
86
}
else
{
87
/* set ATIM Window */
88
/* MACvWriteATIMW(pDevice->PortOffset, pMgmt->wCurrATIMWindow); */
89
}
90
91
/* Warren:06-18-2004,the sequence must follow PSEN->AUTOSLEEP->GO2DOZE */
92
/* enable power saving hw function */
93
MACvRegBitsOn
(pDevice,
MAC_REG_PSCTL
,
PSCTL_PSEN
);
94
95
/* Set AutoSleep */
96
MACvRegBitsOn
(pDevice,
MAC_REG_PSCFG
,
PSCFG_AUTOSLEEP
);
97
98
/* Warren:MUST turn on this once before turn on AUTOSLEEP ,or the AUTOSLEEP doesn't work */
99
MACvRegBitsOn
(pDevice,
MAC_REG_PSCTL
,
PSCTL_GO2DOZE
);
100
101
if
(wListenInterval >= 2) {
102
103
/* clear always listen beacon */
104
MACvRegBitsOff
(pDevice,
MAC_REG_PSCTL
,
PSCTL_ALBCN
);
105
106
/* first time set listen next beacon */
107
MACvRegBitsOn
(pDevice,
MAC_REG_PSCTL
,
PSCTL_LNBCN
);
108
109
pMgmt->
wCountToWakeUp
= wListenInterval;
110
111
}
else
{
112
113
/* always listen beacon */
114
MACvRegBitsOn
(pDevice,
MAC_REG_PSCTL
,
PSCTL_ALBCN
);
115
116
pMgmt->
wCountToWakeUp
= 0;
117
}
118
119
pDevice->
bEnablePSMode
=
TRUE
;
120
121
/* We don't send null pkt in ad hoc mode since beacon will handle this. */
122
if
(pDevice->
eOPMode
==
OP_MODE_INFRASTRUCTURE
)
123
PSbSendNullPacket
(pDevice);
124
125
pDevice->
bPWBitOn
=
TRUE
;
126
DBG_PRT
(
MSG_LEVEL_DEBUG
,
KERN_INFO
"PS:Power Saving Mode Enable...\n"
);
127
}
128
129
/*
130
*
131
* Routine Description:
132
* Disable hw power saving functions
133
*
134
* Return Value:
135
* None.
136
*
137
*/
138
139
void
PSvDisablePowerSaving
(
void
*hDeviceContext)
140
{
141
PSDevice
pDevice = (
PSDevice
)hDeviceContext;
142
/* PSMgmtObject pMgmt = &(pDevice->sMgmtObj); */
143
144
/* disable power saving hw function */
145
CONTROLnsRequestOut
(pDevice,
MESSAGE_TYPE_DISABLE_PS
, 0,
146
0, 0,
NULL
);
147
148
/* clear AutoSleep */
149
MACvRegBitsOff
(pDevice,
MAC_REG_PSCFG
,
PSCFG_AUTOSLEEP
);
150
151
/* set always listen beacon */
152
MACvRegBitsOn
(pDevice,
MAC_REG_PSCTL
,
PSCTL_ALBCN
);
153
pDevice->
bEnablePSMode
=
FALSE
;
154
155
if
(pDevice->
eOPMode
==
OP_MODE_INFRASTRUCTURE
)
156
PSbSendNullPacket
(pDevice);
157
158
pDevice->
bPWBitOn
=
FALSE
;
159
}
160
161
/*
162
*
163
* Routine Description:
164
* Consider to power down when no more packets to tx or rx.
165
*
166
* Return Value:
167
* TRUE, if power down success
168
* FALSE, if fail
169
*/
170
171
BOOL
PSbConsiderPowerDown
(
void
*hDeviceContext,
172
BOOL
bCheckRxDMA,
173
BOOL
bCheckCountToWakeUp)
174
{
175
PSDevice
pDevice = (
PSDevice
)hDeviceContext;
176
PSMgmtObject
pMgmt = &(pDevice->
sMgmtObj
);
177
BYTE
byData;
178
179
/* check if already in Doze mode */
180
ControlvReadByte
(pDevice,
MESSAGE_REQUEST_MACREG
,
181
MAC_REG_PSCTL
, &byData);
182
183
if
((byData &
PSCTL_PS
) != 0)
184
return
TRUE
;
185
186
if
(pMgmt->
eCurrMode
!=
WMAC_MODE_IBSS_STA
) {
187
/* check if in TIM wake period */
188
if
(pMgmt->
bInTIMWake
)
189
return
FALSE
;
190
}
191
192
/* check scan state */
193
if
(pDevice->
bCmdRunning
)
194
return
FALSE
;
195
196
/* Tx Burst */
197
if
(pDevice->
bPSModeTxBurst
)
198
return
FALSE
;
199
200
/* Froce PSEN on */
201
MACvRegBitsOn
(pDevice,
MAC_REG_PSCTL
,
PSCTL_PSEN
);
202
203
if
(pMgmt->
eCurrMode
!=
WMAC_MODE_IBSS_STA
) {
204
if
(bCheckCountToWakeUp && (pMgmt->
wCountToWakeUp
== 0
205
|| pMgmt->
wCountToWakeUp
== 1)) {
206
return
FALSE
;
207
}
208
}
209
210
pDevice->
bPSRxBeacon
=
TRUE
;
211
212
/* no Tx, no Rx isr, now go to Doze */
213
MACvRegBitsOn
(pDevice,
MAC_REG_PSCTL
,
PSCTL_GO2DOZE
);
214
DBG_PRT
(
MSG_LEVEL_DEBUG
,
KERN_INFO
"Go to Doze ZZZZZZZZZZZZZZZ\n"
);
215
return
TRUE
;
216
}
217
218
/*
219
*
220
* Routine Description:
221
* Send PS-POLL packet
222
*
223
* Return Value:
224
* None.
225
*
226
*/
227
228
void
PSvSendPSPOLL
(
void
*hDeviceContext)
229
{
230
PSDevice
pDevice = (
PSDevice
)hDeviceContext;
231
PSMgmtObject
pMgmt = &(pDevice->
sMgmtObj
);
232
PSTxMgmtPacket
pTxPacket =
NULL
;
233
234
memset
(pMgmt->
pbyPSPacketPool
, 0,
sizeof
(
STxMgmtPacket
) +
WLAN_HDR_ADDR2_LEN
);
235
pTxPacket = (
PSTxMgmtPacket
)pMgmt->
pbyPSPacketPool
;
236
pTxPacket->
p80211Header
= (
PUWLAN_80211HDR
)((
PBYTE
)pTxPacket +
sizeof
(
STxMgmtPacket
));
237
pTxPacket->
p80211Header
->
sA2
.wFrameCtl =
cpu_to_le16
(
238
(
239
WLAN_SET_FC_FTYPE
(
WLAN_TYPE_CTL
) |
240
WLAN_SET_FC_FSTYPE
(
WLAN_FSTYPE_PSPOLL
) |
241
WLAN_SET_FC_PWRMGT
(0)
242
));
243
244
pTxPacket->
p80211Header
->
sA2
.wDurationID = pMgmt->
wCurrAID
|
BIT14
|
BIT15
;
245
memcpy
(pTxPacket->
p80211Header
->
sA2
.abyAddr1, pMgmt->
abyCurrBSSID
,
WLAN_ADDR_LEN
);
246
memcpy
(pTxPacket->
p80211Header
->
sA2
.abyAddr2, pMgmt->
abyMACAddr
,
WLAN_ADDR_LEN
);
247
pTxPacket->
cbMPDULen
=
WLAN_HDR_ADDR2_LEN
;
248
pTxPacket->
cbPayloadLen
= 0;
249
250
/* log failure if sending failed */
251
if
(
csMgmt_xmit
(pDevice, pTxPacket) !=
CMD_STATUS_PENDING
) {
252
DBG_PRT
(
MSG_LEVEL_DEBUG
,
KERN_INFO
"Send PS-Poll packet failed..\n"
);
253
}
254
}
255
256
/*
257
*
258
* Routine Description:
259
* Send NULL packet to AP for notification power state of STA
260
*
261
* Return Value:
262
* None.
263
*
264
*/
265
266
BOOL
PSbSendNullPacket
(
void
*hDeviceContext)
267
{
268
PSDevice
pDevice = (
PSDevice
)hDeviceContext;
269
PSTxMgmtPacket
pTxPacket =
NULL
;
270
PSMgmtObject
pMgmt = &(pDevice->
sMgmtObj
);
271
u16
flags
= 0;
272
273
if
(pDevice->
bLinkPass
==
FALSE
)
274
return
FALSE
;
275
276
if
((pDevice->
bEnablePSMode
==
FALSE
) &&
277
(pDevice->
fTxDataInSleep
==
FALSE
)) {
278
return
FALSE
;
279
}
280
281
memset
(pMgmt->
pbyPSPacketPool
, 0,
sizeof
(
STxMgmtPacket
) +
WLAN_NULLDATA_FR_MAXLEN
);
282
pTxPacket = (
PSTxMgmtPacket
)pMgmt->
pbyPSPacketPool
;
283
pTxPacket->
p80211Header
= (
PUWLAN_80211HDR
)((
PBYTE
)pTxPacket +
sizeof
(
STxMgmtPacket
));
284
285
flags =
WLAN_SET_FC_FTYPE
(
WLAN_TYPE_DATA
) |
286
WLAN_SET_FC_FSTYPE
(
WLAN_FSTYPE_NULL
);
287
288
if
(pDevice->
bEnablePSMode
)
289
flags |=
WLAN_SET_FC_PWRMGT
(1);
290
else
291
flags |=
WLAN_SET_FC_PWRMGT
(0);
292
293
pTxPacket->
p80211Header
->
sA3
.wFrameCtl =
cpu_to_le16
(flags);
294
295
if
(pMgmt->
eCurrMode
!=
WMAC_MODE_IBSS_STA
)
296
pTxPacket->
p80211Header
->
sA3
.wFrameCtl |=
cpu_to_le16
((
WORD
)
WLAN_SET_FC_TODS
(1));
297
298
memcpy
(pTxPacket->
p80211Header
->
sA3
.abyAddr1, pMgmt->
abyCurrBSSID
,
WLAN_ADDR_LEN
);
299
memcpy
(pTxPacket->
p80211Header
->
sA3
.abyAddr2, pMgmt->
abyMACAddr
,
WLAN_ADDR_LEN
);
300
memcpy
(pTxPacket->
p80211Header
->
sA3
.abyAddr3, pMgmt->
abyCurrBSSID
,
WLAN_BSSID_LEN
);
301
pTxPacket->
cbMPDULen
=
WLAN_HDR_ADDR3_LEN
;
302
pTxPacket->
cbPayloadLen
= 0;
303
/* log error if sending failed */
304
if
(
csMgmt_xmit
(pDevice, pTxPacket) !=
CMD_STATUS_PENDING
) {
305
DBG_PRT
(
MSG_LEVEL_DEBUG
,
KERN_INFO
"Send Null Packet failed !\n"
);
306
return
FALSE
;
307
}
308
return
TRUE
;
309
}
310
311
/*
312
*
313
* Routine Description:
314
* Check if Next TBTT must wake up
315
*
316
* Return Value:
317
* None.
318
*
319
*/
320
321
BOOL
PSbIsNextTBTTWakeUp
(
void
*hDeviceContext)
322
{
323
PSDevice
pDevice = (
PSDevice
)hDeviceContext;
324
PSMgmtObject
pMgmt = &(pDevice->
sMgmtObj
);
325
BOOL
bWakeUp =
FALSE
;
326
327
if
(pMgmt->
wListenInterval
>= 2) {
328
if
(pMgmt->
wCountToWakeUp
== 0)
329
pMgmt->
wCountToWakeUp
= pMgmt->
wListenInterval
;
330
331
pMgmt->
wCountToWakeUp
--;
332
333
if
(pMgmt->
wCountToWakeUp
== 1) {
334
/* Turn on wake up to listen next beacon */
335
MACvRegBitsOn
(pDevice,
MAC_REG_PSCTL
,
PSCTL_LNBCN
);
336
pDevice->
bPSRxBeacon
=
FALSE
;
337
bWakeUp =
TRUE
;
338
}
else
if
(!pDevice->
bPSRxBeacon
) {
339
/* Listen until RxBeacon */
340
MACvRegBitsOn
(pDevice,
MAC_REG_PSCTL
,
PSCTL_LNBCN
);
341
}
342
}
343
return
bWakeUp;
344
}
345
Generated on Thu Jan 10 2013 13:08:50 for Linux Kernel by
1.8.2