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  * The full GNU General Public License is included in this distribution in the
16  * file called LICENSE.
17  *
18  * Contact Information:
19  * wlanfae <wlanfae@realtek.com>
20  *****************************************************************************/
21 #include "rtl_core.h"
22 #include "r8192E_phy.h"
23 #include "r8192E_phyreg.h"
24 #include "r8190P_rtl8256.h" /* RTL8225 Radio frontend */
25 #include "r8192E_cmdpkt.h"
26 
rtl92e_cam_reset(struct net_device * dev)27 void rtl92e_cam_reset(struct net_device *dev)
28 {
29 	u32 ulcommand = 0;
30 
31 	ulcommand |= BIT31|BIT30;
32 	rtl92e_writel(dev, RWCAM, ulcommand);
33 }
34 
rtl92e_enable_hw_security_config(struct net_device * dev)35 void rtl92e_enable_hw_security_config(struct net_device *dev)
36 {
37 	u8 SECR_value = 0x0;
38 	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
39 	struct rtllib_device *ieee = priv->rtllib;
40 
41 	SECR_value = SCR_TxEncEnable | SCR_RxDecEnable;
42 	if (((ieee->pairwise_key_type == KEY_TYPE_WEP40) ||
43 	     (ieee->pairwise_key_type == KEY_TYPE_WEP104)) &&
44 	     (priv->rtllib->auth_mode != 2)) {
45 		SECR_value |= SCR_RxUseDK;
46 		SECR_value |= SCR_TxUseDK;
47 	} else if ((ieee->iw_mode == IW_MODE_ADHOC) &&
48 		   (ieee->pairwise_key_type & (KEY_TYPE_CCMP |
49 		   KEY_TYPE_TKIP))) {
50 		SECR_value |= SCR_RxUseDK;
51 		SECR_value |= SCR_TxUseDK;
52 	}
53 
54 
55 	ieee->hwsec_active = 1;
56 	if ((ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE) || !hwwep) {
57 		ieee->hwsec_active = 0;
58 		SECR_value &= ~SCR_RxDecEnable;
59 	}
60 
61 	RT_TRACE(COMP_SEC, "%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n",
62 		 __func__, ieee->hwsec_active, ieee->pairwise_key_type,
63 		 SECR_value);
64 	rtl92e_writeb(dev, SECR, SECR_value);
65 }
66 
rtl92e_set_swcam(struct net_device * dev,u8 EntryNo,u8 KeyIndex,u16 KeyType,const u8 * MacAddr,u8 DefaultKey,u32 * KeyContent,u8 is_mesh)67 void rtl92e_set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex,
68 		      u16 KeyType, const u8 *MacAddr, u8 DefaultKey,
69 		      u32 *KeyContent, u8 is_mesh)
70 {
71 	struct r8192_priv *priv = rtllib_priv(dev);
72 	struct rtllib_device *ieee = priv->rtllib;
73 
74 	RT_TRACE(COMP_DBG,
75 		 "===========>%s():EntryNo is %d,KeyIndex is %d,KeyType is %d,is_mesh is %d\n",
76 		 __func__, EntryNo, KeyIndex, KeyType, is_mesh);
77 
78 	if (EntryNo >= TOTAL_CAM_ENTRY)
79 		return;
80 
81 	if (!is_mesh) {
82 		ieee->swcamtable[EntryNo].bused = true;
83 		ieee->swcamtable[EntryNo].key_index = KeyIndex;
84 		ieee->swcamtable[EntryNo].key_type = KeyType;
85 		memcpy(ieee->swcamtable[EntryNo].macaddr, MacAddr, 6);
86 		ieee->swcamtable[EntryNo].useDK = DefaultKey;
87 		memcpy(ieee->swcamtable[EntryNo].key_buf, (u8 *)KeyContent, 16);
88 	}
89 }
90 
rtl92e_set_key(struct net_device * dev,u8 EntryNo,u8 KeyIndex,u16 KeyType,const u8 * MacAddr,u8 DefaultKey,u32 * KeyContent)91 void rtl92e_set_key(struct net_device *dev, u8 EntryNo, u8 KeyIndex,
92 		    u16 KeyType, const u8 *MacAddr, u8 DefaultKey,
93 		    u32 *KeyContent)
94 {
95 	u32 TargetCommand = 0;
96 	u32 TargetContent = 0;
97 	u16 usConfig = 0;
98 	u8 i;
99 	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
100 	enum rt_rf_power_state rtState;
101 
102 	rtState = priv->rtllib->eRFPowerState;
103 	if (priv->rtllib->PowerSaveControl.bInactivePs) {
104 		if (rtState == eRfOff) {
105 			if (priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS) {
106 				netdev_warn(dev, "%s(): RF is OFF.\n",
107 					    __func__);
108 				return;
109 			}
110 			mutex_lock(&priv->rtllib->ips_mutex);
111 			rtl92e_ips_leave(dev);
112 			mutex_unlock(&priv->rtllib->ips_mutex);
113 		}
114 	}
115 	priv->rtllib->is_set_key = true;
116 	if (EntryNo >= TOTAL_CAM_ENTRY) {
117 		netdev_info(dev, "%s(): Invalid CAM entry\n", __func__);
118 		return;
119 	}
120 
121 	RT_TRACE(COMP_SEC,
122 		 "====>to rtl92e_set_key(), dev:%p, EntryNo:%d, KeyIndex:%d,KeyType:%d, MacAddr %pM\n",
123 		 dev, EntryNo, KeyIndex, KeyType, MacAddr);
124 
125 	if (DefaultKey)
126 		usConfig |= BIT15 | (KeyType<<2);
127 	else
128 		usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
129 
130 
131 	for (i = 0; i < CAM_CONTENT_COUNT; i++) {
132 		TargetCommand  = i + CAM_CONTENT_COUNT * EntryNo;
133 		TargetCommand |= BIT31|BIT16;
134 
135 		if (i == 0) {
136 			TargetContent = (u32)(*(MacAddr+0)) << 16 |
137 				(u32)(*(MacAddr+1)) << 24 |
138 				(u32)usConfig;
139 
140 			rtl92e_writel(dev, WCAMI, TargetContent);
141 			rtl92e_writel(dev, RWCAM, TargetCommand);
142 		} else if (i == 1) {
143 			TargetContent = (u32)(*(MacAddr+2)) |
144 				(u32)(*(MacAddr+3)) <<  8 |
145 				(u32)(*(MacAddr+4)) << 16 |
146 				(u32)(*(MacAddr+5)) << 24;
147 			rtl92e_writel(dev, WCAMI, TargetContent);
148 			rtl92e_writel(dev, RWCAM, TargetCommand);
149 		} else {
150 			if (KeyContent != NULL) {
151 				rtl92e_writel(dev, WCAMI,
152 					      (u32)(*(KeyContent+i-2)));
153 				rtl92e_writel(dev, RWCAM, TargetCommand);
154 				udelay(100);
155 			}
156 		}
157 	}
158 	RT_TRACE(COMP_SEC, "=========>after set key, usconfig:%x\n", usConfig);
159 }
160 
rtl92e_cam_restore(struct net_device * dev)161 void rtl92e_cam_restore(struct net_device *dev)
162 {
163 	u8 EntryId = 0;
164 	struct r8192_priv *priv = rtllib_priv(dev);
165 	u8 *MacAddr = priv->rtllib->current_network.bssid;
166 
167 	static u8	CAM_CONST_ADDR[4][6] = {
168 		{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
169 		{0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
170 		{0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
171 		{0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
172 	};
173 	static u8	CAM_CONST_BROAD[] = {
174 		0xff, 0xff, 0xff, 0xff, 0xff, 0xff
175 	};
176 
177 	RT_TRACE(COMP_SEC, "rtl92e_cam_restore:\n");
178 
179 
180 	if ((priv->rtllib->pairwise_key_type == KEY_TYPE_WEP40) ||
181 	    (priv->rtllib->pairwise_key_type == KEY_TYPE_WEP104)) {
182 
183 		for (EntryId = 0; EntryId < 4; EntryId++) {
184 			MacAddr = CAM_CONST_ADDR[EntryId];
185 			if (priv->rtllib->swcamtable[EntryId].bused) {
186 				rtl92e_set_key(dev, EntryId, EntryId,
187 					       priv->rtllib->pairwise_key_type,
188 					       MacAddr, 0,
189 					       (u32 *)(&priv->rtllib->swcamtable
190 						       [EntryId].key_buf[0]));
191 			}
192 		}
193 
194 	} else if (priv->rtllib->pairwise_key_type == KEY_TYPE_TKIP) {
195 		if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
196 			rtl92e_set_key(dev, 4, 0,
197 				       priv->rtllib->pairwise_key_type,
198 				       (u8 *)dev->dev_addr, 0,
199 				       (u32 *)(&priv->rtllib->swcamtable[4].
200 				       key_buf[0]));
201 		} else {
202 			rtl92e_set_key(dev, 4, 0,
203 				       priv->rtllib->pairwise_key_type,
204 				       MacAddr, 0,
205 				       (u32 *)(&priv->rtllib->swcamtable[4].
206 				       key_buf[0]));
207 		}
208 
209 	} else if (priv->rtllib->pairwise_key_type == KEY_TYPE_CCMP) {
210 		if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
211 			rtl92e_set_key(dev, 4, 0,
212 				       priv->rtllib->pairwise_key_type,
213 				       (u8 *)dev->dev_addr, 0,
214 				       (u32 *)(&priv->rtllib->swcamtable[4].
215 				       key_buf[0]));
216 		} else {
217 			rtl92e_set_key(dev, 4, 0,
218 				       priv->rtllib->pairwise_key_type, MacAddr,
219 				       0, (u32 *)(&priv->rtllib->swcamtable[4].
220 				       key_buf[0]));
221 			}
222 	}
223 
224 	if (priv->rtllib->group_key_type == KEY_TYPE_TKIP) {
225 		MacAddr = CAM_CONST_BROAD;
226 		for (EntryId = 1; EntryId < 4; EntryId++) {
227 			if (priv->rtllib->swcamtable[EntryId].bused) {
228 				rtl92e_set_key(dev, EntryId, EntryId,
229 					       priv->rtllib->group_key_type,
230 					       MacAddr, 0,
231 					       (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0]));
232 			}
233 		}
234 		if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
235 			if (priv->rtllib->swcamtable[0].bused) {
236 				rtl92e_set_key(dev, 0, 0,
237 					       priv->rtllib->group_key_type,
238 					       CAM_CONST_ADDR[0], 0,
239 					       (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0]));
240 			} else {
241 				netdev_warn(dev,
242 					    "%s(): ADHOC TKIP: missing key entry.\n",
243 					    __func__);
244 				return;
245 			}
246 		}
247 	} else if (priv->rtllib->group_key_type == KEY_TYPE_CCMP) {
248 		MacAddr = CAM_CONST_BROAD;
249 		for (EntryId = 1; EntryId < 4; EntryId++) {
250 			if (priv->rtllib->swcamtable[EntryId].bused) {
251 				rtl92e_set_key(dev, EntryId, EntryId,
252 					       priv->rtllib->group_key_type,
253 					       MacAddr, 0,
254 					       (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0]));
255 			}
256 		}
257 
258 		if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
259 			if (priv->rtllib->swcamtable[0].bused) {
260 				rtl92e_set_key(dev, 0, 0,
261 					       priv->rtllib->group_key_type,
262 					       CAM_CONST_ADDR[0], 0,
263 					       (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0]));
264 			} else {
265 				netdev_warn(dev,
266 					    "%s(): ADHOC CCMP: missing key entry.\n",
267 					    __func__);
268 				return;
269 			}
270 		}
271 	}
272 }
273