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 
31 extern int hwwep;
CamResetAllEntry(struct net_device * dev)32 void CamResetAllEntry(struct net_device *dev)
33 {
34 	u32 ulcommand = 0;
35 
36 	ulcommand |= BIT31|BIT30;
37 	write_nic_dword(dev, RWCAM, ulcommand);
38 }
39 
write_cam(struct net_device * dev,u8 addr,u32 data)40 void 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 
read_cam(struct net_device * dev,u8 addr)46 u32 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 
EnableHWSecurityConfig8192(struct net_device * dev)52 void 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 
set_swcam(struct net_device * dev,u8 EntryNo,u8 KeyIndex,u16 KeyType,u8 * MacAddr,u8 DefaultKey,u32 * KeyContent,u8 is_mesh)83 void 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 
setKey(struct net_device * dev,u8 EntryNo,u8 KeyIndex,u16 KeyType,u8 * MacAddr,u8 DefaultKey,u32 * KeyContent)101 void 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 
CAM_read_entry(struct net_device * dev,u32 iIndex)168 void 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 
CamRestoreAllEntry(struct net_device * dev)196 void 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