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 <andrea.merello@gmail.com>, 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 
CamResetAllEntry(struct net_device * dev)31 void CamResetAllEntry(struct net_device *dev)
32 {
33 	u32 ulcommand = 0;
34 
35 	ulcommand |= BIT31|BIT30;
36 	write_nic_dword(dev, RWCAM, ulcommand);
37 }
38 
write_cam(struct net_device * dev,u8 addr,u32 data)39 void write_cam(struct net_device *dev, u8 addr, u32 data)
40 {
41 	write_nic_dword(dev, WCAMI, data);
42 	write_nic_dword(dev, RWCAM, BIT31|BIT16|(addr&0xff));
43 }
44 
read_cam(struct net_device * dev,u8 addr)45 u32 read_cam(struct net_device *dev, u8 addr)
46 {
47 	write_nic_dword(dev, RWCAM, 0x80000000|(addr&0xff));
48 	return read_nic_dword(dev, 0xa8);
49 }
50 
EnableHWSecurityConfig8192(struct net_device * dev)51 void EnableHWSecurityConfig8192(struct net_device *dev)
52 {
53 	u8 SECR_value = 0x0;
54 	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
55 	struct rtllib_device *ieee = priv->rtllib;
56 
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 
89 	RT_TRACE(COMP_DBG,
90 		 "===========>%s():EntryNo is %d,KeyIndex is %d,KeyType is %d,is_mesh is %d\n",
91 		 __func__, EntryNo, KeyIndex, KeyType, is_mesh);
92 	if (!is_mesh) {
93 		ieee->swcamtable[EntryNo].bused = true;
94 		ieee->swcamtable[EntryNo].key_index = KeyIndex;
95 		ieee->swcamtable[EntryNo].key_type = KeyType;
96 		memcpy(ieee->swcamtable[EntryNo].macaddr, MacAddr, 6);
97 		ieee->swcamtable[EntryNo].useDK = DefaultKey;
98 		memcpy(ieee->swcamtable[EntryNo].key_buf, (u8 *)KeyContent, 16);
99 	}
100 }
101 
setKey(struct net_device * dev,u8 EntryNo,u8 KeyIndex,u16 KeyType,u8 * MacAddr,u8 DefaultKey,u32 * KeyContent)102 void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
103 	    u8 *MacAddr, u8 DefaultKey, u32 *KeyContent)
104 {
105 	u32 TargetCommand = 0;
106 	u32 TargetContent = 0;
107 	u16 usConfig = 0;
108 	u8 i;
109 	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
110 	enum rt_rf_power_state rtState;
111 
112 	rtState = priv->rtllib->eRFPowerState;
113 	if (priv->rtllib->PowerSaveControl.bInactivePs) {
114 		if (rtState == eRfOff) {
115 			if (priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS) {
116 				RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",
117 					__func__);
118 				return;
119 			}
120 			down(&priv->rtllib->ips_sem);
121 			IPSLeave(dev);
122 			up(&priv->rtllib->ips_sem);
123 		}
124 	}
125 	priv->rtllib->is_set_key = true;
126 	if (EntryNo >= TOTAL_CAM_ENTRY)
127 		RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
128 
129 	RT_TRACE(COMP_SEC,
130 		 "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d,KeyType:%d, MacAddr %pM\n",
131 		 dev, EntryNo, KeyIndex, KeyType, MacAddr);
132 
133 	if (DefaultKey)
134 		usConfig |= BIT15 | (KeyType<<2);
135 	else
136 		usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
137 
138 
139 	for (i = 0; i < CAM_CONTENT_COUNT; i++) {
140 		TargetCommand  = i + CAM_CONTENT_COUNT * EntryNo;
141 		TargetCommand |= BIT31|BIT16;
142 
143 		if (i == 0) {
144 			TargetContent = (u32)(*(MacAddr+0)) << 16 |
145 				(u32)(*(MacAddr+1)) << 24 |
146 				(u32)usConfig;
147 
148 			write_nic_dword(dev, WCAMI, TargetContent);
149 			write_nic_dword(dev, RWCAM, TargetCommand);
150 		} else if (i == 1) {
151 			TargetContent = (u32)(*(MacAddr+2)) |
152 				(u32)(*(MacAddr+3)) <<  8 |
153 				(u32)(*(MacAddr+4)) << 16 |
154 				(u32)(*(MacAddr+5)) << 24;
155 			write_nic_dword(dev, WCAMI, TargetContent);
156 			write_nic_dword(dev, RWCAM, TargetCommand);
157 		} else {
158 			if (KeyContent != NULL) {
159 				write_nic_dword(dev, WCAMI,
160 						(u32)(*(KeyContent+i-2)));
161 				write_nic_dword(dev, RWCAM, TargetCommand);
162 				udelay(100);
163 			}
164 		}
165 	}
166 	RT_TRACE(COMP_SEC, "=========>after set key, usconfig:%x\n", usConfig);
167 }
168 
CamRestoreAllEntry(struct net_device * dev)169 void CamRestoreAllEntry(struct net_device *dev)
170 {
171 	u8 EntryId = 0;
172 	struct r8192_priv *priv = rtllib_priv(dev);
173 	u8 *MacAddr = priv->rtllib->current_network.bssid;
174 
175 	static u8	CAM_CONST_ADDR[4][6] = {
176 		{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
177 		{0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
178 		{0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
179 		{0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
180 	};
181 	static u8	CAM_CONST_BROAD[] = {
182 		0xff, 0xff, 0xff, 0xff, 0xff, 0xff
183 	};
184 
185 	RT_TRACE(COMP_SEC, "CamRestoreAllEntry:\n");
186 
187 
188 	if ((priv->rtllib->pairwise_key_type == KEY_TYPE_WEP40) ||
189 	    (priv->rtllib->pairwise_key_type == KEY_TYPE_WEP104)) {
190 
191 		for (EntryId = 0; EntryId < 4; EntryId++) {
192 			MacAddr = CAM_CONST_ADDR[EntryId];
193 			if (priv->rtllib->swcamtable[EntryId].bused) {
194 				setKey(dev, EntryId, EntryId,
195 				       priv->rtllib->pairwise_key_type, MacAddr,
196 				       0, (u32 *)(&priv->rtllib->swcamtable
197 				      [EntryId].key_buf[0]));
198 			}
199 		}
200 
201 	} else if (priv->rtllib->pairwise_key_type == KEY_TYPE_TKIP) {
202 		if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
203 			setKey(dev, 4, 0, priv->rtllib->pairwise_key_type,
204 			       (u8 *)dev->dev_addr, 0,
205 			       (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0]));
206 		} else {
207 			setKey(dev, 4, 0, priv->rtllib->pairwise_key_type,
208 			       MacAddr, 0,
209 			       (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0]));
210 		}
211 
212 	} else if (priv->rtllib->pairwise_key_type == KEY_TYPE_CCMP) {
213 		if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
214 			setKey(dev, 4, 0,
215 			       priv->rtllib->pairwise_key_type,
216 			       (u8 *)dev->dev_addr, 0,
217 			       (u32 *)(&priv->rtllib->swcamtable[4].
218 			       key_buf[0]));
219 		} else {
220 			setKey(dev, 4, 0,
221 			       priv->rtllib->pairwise_key_type, MacAddr,
222 			       0, (u32 *)(&priv->rtllib->swcamtable[4].
223 			       key_buf[0]));
224 			}
225 	}
226 
227 	if (priv->rtllib->group_key_type == KEY_TYPE_TKIP) {
228 		MacAddr = CAM_CONST_BROAD;
229 		for (EntryId = 1; EntryId < 4; EntryId++) {
230 			if (priv->rtllib->swcamtable[EntryId].bused) {
231 				setKey(dev, EntryId, EntryId,
232 					priv->rtllib->group_key_type,
233 					MacAddr, 0,
234 					(u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0])
235 				     );
236 			}
237 		}
238 		if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
239 			if (priv->rtllib->swcamtable[0].bused) {
240 				setKey(dev, 0, 0,
241 				       priv->rtllib->group_key_type,
242 				       CAM_CONST_ADDR[0], 0,
243 				       (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0])
244 				     );
245 			} else {
246 				RT_TRACE(COMP_ERR,
247 					 "===>%s():ERR!! ADHOC TKIP ,but 0 entry is have no data\n",
248 					 __func__);
249 				return;
250 			}
251 		}
252 	} else if (priv->rtllib->group_key_type == KEY_TYPE_CCMP) {
253 		MacAddr = CAM_CONST_BROAD;
254 		for (EntryId = 1; EntryId < 4; EntryId++) {
255 			if (priv->rtllib->swcamtable[EntryId].bused) {
256 				setKey(dev, EntryId, EntryId,
257 				       priv->rtllib->group_key_type,
258 				       MacAddr, 0,
259 				       (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0]));
260 			}
261 		}
262 
263 		if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
264 			if (priv->rtllib->swcamtable[0].bused) {
265 				setKey(dev, 0, 0,
266 					priv->rtllib->group_key_type,
267 					CAM_CONST_ADDR[0], 0,
268 					(u32 *)(&priv->rtllib->swcamtable[0].key_buf[0]));
269 			} else {
270 				RT_TRACE(COMP_ERR,
271 					 "===>%s():ERR!! ADHOC CCMP ,but 0 entry is have no data\n",
272 					 __func__);
273 				return;
274 			}
275 		}
276 	}
277 }
278