1/******************************************************************************
2 * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
3 *
4 * Based on the r8180 driver, which is:
5 * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of version 2 of the GNU General Public License as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
18 *
19 * The full GNU General Public License is included in this distribution in the
20 * file called LICENSE.
21 *
22 * Contact Information:
23 * wlanfae <wlanfae@realtek.com>
24******************************************************************************/
25#include "rtl_core.h"
26#include "r8192E_phy.h"
27#include "r8192E_phyreg.h"
28#include "r8190P_rtl8256.h" /* RTL8225 Radio frontend */
29#include "r8192E_cmdpkt.h"
30
31extern int hwwep;
32void CamResetAllEntry(struct net_device *dev)
33{
34	u32 ulcommand = 0;
35
36	ulcommand |= BIT31|BIT30;
37	write_nic_dword(dev, RWCAM, ulcommand);
38}
39
40void write_cam(struct net_device *dev, u8 addr, u32 data)
41{
42	write_nic_dword(dev, WCAMI, data);
43	write_nic_dword(dev, RWCAM, BIT31|BIT16|(addr&0xff));
44}
45
46u32 read_cam(struct net_device *dev, u8 addr)
47{
48	write_nic_dword(dev, RWCAM, 0x80000000|(addr&0xff));
49	return read_nic_dword(dev, 0xa8);
50}
51
52void EnableHWSecurityConfig8192(struct net_device *dev)
53{
54	u8 SECR_value = 0x0;
55	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
56	struct rtllib_device *ieee = priv->rtllib;
57	SECR_value = SCR_TxEncEnable | SCR_RxDecEnable;
58	if (((KEY_TYPE_WEP40 == ieee->pairwise_key_type) ||
59	     (KEY_TYPE_WEP104 == ieee->pairwise_key_type)) &&
60	     (priv->rtllib->auth_mode != 2)) {
61		SECR_value |= SCR_RxUseDK;
62		SECR_value |= SCR_TxUseDK;
63	} else if ((ieee->iw_mode == IW_MODE_ADHOC) &&
64		   (ieee->pairwise_key_type & (KEY_TYPE_CCMP |
65		   KEY_TYPE_TKIP))) {
66		SECR_value |= SCR_RxUseDK;
67		SECR_value |= SCR_TxUseDK;
68	}
69
70
71	ieee->hwsec_active = 1;
72	if ((ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE) || !hwwep) {
73		ieee->hwsec_active = 0;
74		SECR_value &= ~SCR_RxDecEnable;
75	}
76
77	RT_TRACE(COMP_SEC, "%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n",
78		 __func__, ieee->hwsec_active, ieee->pairwise_key_type,
79		 SECR_value);
80	write_nic_byte(dev, SECR,  SECR_value);
81}
82
83void set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
84	       u8 *MacAddr, u8 DefaultKey, u32 *KeyContent, u8 is_mesh)
85{
86	struct r8192_priv *priv = rtllib_priv(dev);
87	struct rtllib_device *ieee = priv->rtllib;
88	RT_TRACE(COMP_DBG, "===========>%s():EntryNo is %d,KeyIndex is "
89		 "%d,KeyType is %d,is_mesh is %d\n", __func__, EntryNo,
90		 KeyIndex, KeyType, is_mesh);
91	if (!is_mesh) {
92		ieee->swcamtable[EntryNo].bused = true;
93		ieee->swcamtable[EntryNo].key_index = KeyIndex;
94		ieee->swcamtable[EntryNo].key_type = KeyType;
95		memcpy(ieee->swcamtable[EntryNo].macaddr, MacAddr, 6);
96		ieee->swcamtable[EntryNo].useDK = DefaultKey;
97		memcpy(ieee->swcamtable[EntryNo].key_buf, (u8 *)KeyContent, 16);
98	}
99}
100
101void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
102	    u8 *MacAddr, u8 DefaultKey, u32 *KeyContent)
103{
104	u32 TargetCommand = 0;
105	u32 TargetContent = 0;
106	u16 usConfig = 0;
107	u8 i;
108	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
109	enum rt_rf_power_state rtState;
110	rtState = priv->rtllib->eRFPowerState;
111	if (priv->rtllib->PowerSaveControl.bInactivePs) {
112		if (rtState == eRfOff) {
113			if (priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS) {
114				RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",
115					__func__);
116				return ;
117			} else {
118				down(&priv->rtllib->ips_sem);
119				IPSLeave(dev);
120				up(&priv->rtllib->ips_sem);
121			}
122		}
123	}
124	priv->rtllib->is_set_key = true;
125	if (EntryNo >= TOTAL_CAM_ENTRY)
126		RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
127
128	RT_TRACE(COMP_SEC, "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d,"
129		 "KeyType:%d, MacAddr %pM\n", dev, EntryNo, KeyIndex,
130		 KeyType, MacAddr);
131
132	if (DefaultKey)
133		usConfig |= BIT15 | (KeyType<<2);
134	else
135		usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
136
137
138	for (i = 0; i < CAM_CONTENT_COUNT; i++) {
139		TargetCommand  = i + CAM_CONTENT_COUNT * EntryNo;
140		TargetCommand |= BIT31|BIT16;
141
142		if (i == 0) {
143			TargetContent = (u32)(*(MacAddr+0)) << 16 |
144				(u32)(*(MacAddr+1)) << 24 |
145				(u32)usConfig;
146
147			write_nic_dword(dev, WCAMI, TargetContent);
148			write_nic_dword(dev, RWCAM, TargetCommand);
149		} else if (i == 1) {
150			TargetContent = (u32)(*(MacAddr+2)) |
151				(u32)(*(MacAddr+3)) <<  8 |
152				(u32)(*(MacAddr+4)) << 16 |
153				(u32)(*(MacAddr+5)) << 24;
154			write_nic_dword(dev, WCAMI, TargetContent);
155			write_nic_dword(dev, RWCAM, TargetCommand);
156		} else {
157			if (KeyContent != NULL) {
158				write_nic_dword(dev, WCAMI,
159						(u32)(*(KeyContent+i-2)));
160				write_nic_dword(dev, RWCAM, TargetCommand);
161				udelay(100);
162			}
163		}
164	}
165	RT_TRACE(COMP_SEC, "=========>after set key, usconfig:%x\n", usConfig);
166}
167
168void CAM_read_entry(struct net_device *dev, u32 iIndex)
169{
170	u32 target_command = 0;
171	u32 target_content = 0;
172	u8 entry_i = 0;
173	u32 ulStatus;
174	s32 i = 100;
175	for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
176		target_command = entry_i+CAM_CONTENT_COUNT*iIndex;
177		target_command = target_command | BIT31;
178
179		while ((i--) >= 0) {
180			ulStatus = read_nic_dword(dev, RWCAM);
181			if (ulStatus & BIT31)
182				continue;
183			else
184				break;
185		}
186		write_nic_dword(dev, RWCAM, target_command);
187		RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A0: %x\n",
188			 target_command);
189		target_content = read_nic_dword(dev, RCAMO);
190		RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A8: %x\n",
191			 target_content);
192	}
193	printk(KERN_INFO "\n");
194}
195
196void CamRestoreAllEntry(struct net_device *dev)
197{
198	u8 EntryId = 0;
199	struct r8192_priv *priv = rtllib_priv(dev);
200	u8 *MacAddr = priv->rtllib->current_network.bssid;
201
202	static u8	CAM_CONST_ADDR[4][6] = {
203		{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
204		{0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
205		{0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
206		{0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
207	};
208	static u8	CAM_CONST_BROAD[] = {
209		0xff, 0xff, 0xff, 0xff, 0xff, 0xff
210	};
211
212	RT_TRACE(COMP_SEC, "CamRestoreAllEntry:\n");
213
214
215	if ((priv->rtllib->pairwise_key_type == KEY_TYPE_WEP40) ||
216	    (priv->rtllib->pairwise_key_type == KEY_TYPE_WEP104)) {
217
218		for (EntryId = 0; EntryId < 4; EntryId++) {
219			MacAddr = CAM_CONST_ADDR[EntryId];
220			if (priv->rtllib->swcamtable[EntryId].bused) {
221				setKey(dev, EntryId , EntryId,
222				       priv->rtllib->pairwise_key_type, MacAddr,
223				       0, (u32 *)(&priv->rtllib->swcamtable
224				      [EntryId].key_buf[0]));
225			}
226		}
227
228	} else if (priv->rtllib->pairwise_key_type == KEY_TYPE_TKIP) {
229		if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
230			setKey(dev, 4, 0, priv->rtllib->pairwise_key_type,
231			       (u8 *)dev->dev_addr, 0,
232			       (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0]));
233		} else {
234			setKey(dev, 4, 0, priv->rtllib->pairwise_key_type,
235			       MacAddr, 0,
236			       (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0]));
237		}
238
239	} else if (priv->rtllib->pairwise_key_type == KEY_TYPE_CCMP) {
240		if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
241			setKey(dev, 4, 0,
242			       priv->rtllib->pairwise_key_type,
243			       (u8 *)dev->dev_addr, 0,
244			       (u32 *)(&priv->rtllib->swcamtable[4].
245			       key_buf[0]));
246		} else {
247			setKey(dev, 4, 0,
248			       priv->rtllib->pairwise_key_type, MacAddr,
249			       0, (u32 *)(&priv->rtllib->swcamtable[4].
250			       key_buf[0]));
251			}
252	}
253
254	if (priv->rtllib->group_key_type == KEY_TYPE_TKIP) {
255		MacAddr = CAM_CONST_BROAD;
256		for (EntryId = 1; EntryId < 4; EntryId++) {
257			if (priv->rtllib->swcamtable[EntryId].bused) {
258				setKey(dev, EntryId, EntryId,
259					priv->rtllib->group_key_type,
260					MacAddr, 0,
261					(u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0])
262				     );
263			}
264		}
265		if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
266			if (priv->rtllib->swcamtable[0].bused) {
267				setKey(dev, 0, 0,
268				       priv->rtllib->group_key_type,
269				       CAM_CONST_ADDR[0], 0,
270				       (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0])
271				     );
272			} else {
273				RT_TRACE(COMP_ERR, "===>%s():ERR!! ADHOC TKIP "
274					 ",but 0 entry is have no data\n",
275					 __func__);
276				return;
277			}
278		}
279	} else if (priv->rtllib->group_key_type == KEY_TYPE_CCMP) {
280		MacAddr = CAM_CONST_BROAD;
281		for (EntryId = 1; EntryId < 4; EntryId++) {
282			if (priv->rtllib->swcamtable[EntryId].bused) {
283				setKey(dev, EntryId , EntryId,
284				       priv->rtllib->group_key_type,
285				       MacAddr, 0,
286				       (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0]));
287			}
288		}
289
290		if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
291			if (priv->rtllib->swcamtable[0].bused) {
292				setKey(dev, 0 , 0,
293					priv->rtllib->group_key_type,
294					CAM_CONST_ADDR[0], 0,
295					(u32 *)(&priv->rtllib->swcamtable[0].key_buf[0]));
296			} else {
297				RT_TRACE(COMP_ERR, "===>%s():ERR!! ADHOC CCMP ,"
298					 "but 0 entry is have no data\n",
299					 __func__);
300				return;
301			}
302		}
303	}
304}
305