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 "mac.h"
41#include "device.h"
42#include "power.h"
43#include "card.h"
44
45/*---------------------  Static Definitions -------------------------*/
46
47/*---------------------  Static Classes  ----------------------------*/
48
49/*---------------------  Static Functions  --------------------------*/
50
51/*---------------------  Export Variables  --------------------------*/
52
53/*---------------------  Export Functions  --------------------------*/
54
55/*+
56 *
57 * Routine Description:
58 * Enable hw power saving functions
59 *
60 * Return Value:
61 *    None.
62 *
63 -*/
64
65void
66PSvEnablePowerSaving(
67	void *hDeviceContext,
68	unsigned short wListenInterval
69)
70{
71	struct vnt_private *pDevice = hDeviceContext;
72	u16 wAID = pDevice->current_aid | BIT(14) | BIT(15);
73
74	/* set period of power up before TBTT */
75	VNSvOutPortW(pDevice->PortOffset + MAC_REG_PWBT, C_PWBT);
76	if (pDevice->op_mode != NL80211_IFTYPE_ADHOC) {
77		/* set AID */
78		VNSvOutPortW(pDevice->PortOffset + MAC_REG_AIDATIM, wAID);
79	} else {
80		/* set ATIM Window */
81#if 0 /* TODO atim window */
82		MACvWriteATIMW(pDevice->PortOffset, pMgmt->wCurrATIMWindow);
83#endif
84	}
85	/* Set AutoSleep */
86	MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
87	/* Set HWUTSF */
88	MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF);
89
90	if (wListenInterval >= 2) {
91		/* clear always listen beacon */
92		MACvRegBitsOff(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN);
93		/* first time set listen next beacon */
94		MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_LNBCN);
95	} else {
96		/* always listen beacon */
97		MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN);
98	}
99
100	/* enable power saving hw function */
101	MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PSEN);
102	pDevice->bEnablePSMode = true;
103
104	pDevice->bPWBitOn = true;
105	pr_debug("PS:Power Saving Mode Enable...\n");
106}
107
108/*+
109 *
110 * Routine Description:
111 * Disable hw power saving functions
112 *
113 * Return Value:
114 *    None.
115 *
116 -*/
117
118void
119PSvDisablePowerSaving(
120	void *hDeviceContext
121)
122{
123	struct vnt_private *pDevice = hDeviceContext;
124
125	/* disable power saving hw function */
126	MACbPSWakeup(pDevice->PortOffset);
127	/* clear AutoSleep */
128	MACvRegBitsOff(pDevice->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
129	/* clear HWUTSF */
130	MACvRegBitsOff(pDevice->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF);
131	/* set always listen beacon */
132	MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN);
133
134	pDevice->bEnablePSMode = false;
135
136	pDevice->bPWBitOn = false;
137}
138
139
140/*+
141 *
142 * Routine Description:
143 * Check if Next TBTT must wake up
144 *
145 * Return Value:
146 *    None.
147 *
148 -*/
149
150bool
151PSbIsNextTBTTWakeUp(
152	void *hDeviceContext
153)
154{
155	struct vnt_private *pDevice = hDeviceContext;
156	struct ieee80211_hw *hw = pDevice->hw;
157	struct ieee80211_conf *conf = &hw->conf;
158	bool bWakeUp = false;
159
160	if (conf->listen_interval > 1) {
161		if (!pDevice->wake_up_count)
162			pDevice->wake_up_count = conf->listen_interval;
163
164		--pDevice->wake_up_count;
165
166		if (pDevice->wake_up_count == 1) {
167			/* Turn on wake up to listen next beacon */
168			MACvRegBitsOn(pDevice->PortOffset,
169				      MAC_REG_PSCTL, PSCTL_LNBCN);
170			bWakeUp = true;
171		}
172	}
173
174	return bWakeUp;
175}
176