Commit | Line | Data |
---|---|---|
94a79942 LF |
1 | /****************************************************************************** |
2 | * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. | |
3 | * | |
4 | * Based on the r8180 driver, which is: | |
559a4c31 | 5 | * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al. |
94a79942 LF |
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 | * | |
94a79942 LF |
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 | ||
358e4ee1 | 27 | void rtl92e_cam_reset(struct net_device *dev) |
94a79942 LF |
28 | { |
29 | u32 ulcommand = 0; | |
30 | ||
31 | ulcommand |= BIT31|BIT30; | |
8ea54100 | 32 | rtl92e_writel(dev, RWCAM, ulcommand); |
94a79942 LF |
33 | } |
34 | ||
37420932 | 35 | void rtl92e_enable_hw_security_config(struct net_device *dev) |
94a79942 LF |
36 | { |
37 | u8 SECR_value = 0x0; | |
38 | struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); | |
b6da7313 | 39 | struct rtllib_device *ieee = priv->rtllib; |
3a6b70c3 | 40 | |
94a79942 | 41 | SECR_value = SCR_TxEncEnable | SCR_RxDecEnable; |
4c29207a MK |
42 | if (((ieee->pairwise_key_type == KEY_TYPE_WEP40) || |
43 | (ieee->pairwise_key_type == KEY_TYPE_WEP104)) && | |
b6da7313 | 44 | (priv->rtllib->auth_mode != 2)) { |
94a79942 LF |
45 | SECR_value |= SCR_RxUseDK; |
46 | SECR_value |= SCR_TxUseDK; | |
b6da7313 LF |
47 | } else if ((ieee->iw_mode == IW_MODE_ADHOC) && |
48 | (ieee->pairwise_key_type & (KEY_TYPE_CCMP | | |
49 | KEY_TYPE_TKIP))) { | |
94a79942 LF |
50 | SECR_value |= SCR_RxUseDK; |
51 | SECR_value |= SCR_TxUseDK; | |
52 | } | |
53 | ||
54 | ||
55 | ieee->hwsec_active = 1; | |
b6da7313 | 56 | if ((ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE) || !hwwep) { |
94a79942 LF |
57 | ieee->hwsec_active = 0; |
58 | SECR_value &= ~SCR_RxDecEnable; | |
59 | } | |
60 | ||
b6da7313 LF |
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); | |
d8ae1967 | 64 | rtl92e_writeb(dev, SECR, SECR_value); |
94a79942 LF |
65 | } |
66 | ||
aae7e72e MK |
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) | |
94a79942 LF |
70 | { |
71 | struct r8192_priv *priv = rtllib_priv(dev); | |
72 | struct rtllib_device *ieee = priv->rtllib; | |
3a6b70c3 | 73 | |
0822339b MK |
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); | |
d1f0f311 DC |
77 | |
78 | if (EntryNo >= TOTAL_CAM_ENTRY) | |
79 | return; | |
80 | ||
b6da7313 LF |
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); | |
94a79942 LF |
88 | } |
89 | } | |
90 | ||
408bd7b7 MK |
91 | void rtl92e_set_key(struct net_device *dev, u8 EntryNo, u8 KeyIndex, |
92 | u16 KeyType, const u8 *MacAddr, u8 DefaultKey, | |
93 | u32 *KeyContent) | |
94a79942 LF |
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); | |
de7c885a | 100 | enum rt_rf_power_state rtState; |
3a6b70c3 | 101 | |
94a79942 | 102 | rtState = priv->rtllib->eRFPowerState; |
b6da7313 LF |
103 | if (priv->rtllib->PowerSaveControl.bInactivePs) { |
104 | if (rtState == eRfOff) { | |
105 | if (priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS) { | |
3b4140af MK |
106 | netdev_warn(dev, "%s(): RF is OFF.\n", |
107 | __func__); | |
dc986e3e | 108 | return; |
b6da7313 | 109 | } |
38bee763 | 110 | mutex_lock(&priv->rtllib->ips_mutex); |
2ab2aba2 | 111 | rtl92e_ips_leave(dev); |
38bee763 | 112 | mutex_unlock(&priv->rtllib->ips_mutex); |
94a79942 LF |
113 | } |
114 | } | |
115 | priv->rtllib->is_set_key = true; | |
a9cf7250 | 116 | if (EntryNo >= TOTAL_CAM_ENTRY) { |
3b4140af | 117 | netdev_info(dev, "%s(): Invalid CAM entry\n", __func__); |
a9cf7250 DC |
118 | return; |
119 | } | |
94a79942 | 120 | |
0822339b | 121 | RT_TRACE(COMP_SEC, |
408bd7b7 | 122 | "====>to rtl92e_set_key(), dev:%p, EntryNo:%d, KeyIndex:%d,KeyType:%d, MacAddr %pM\n", |
0822339b | 123 | dev, EntryNo, KeyIndex, KeyType, MacAddr); |
94a79942 LF |
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++) { | |
b6da7313 | 132 | TargetCommand = i + CAM_CONTENT_COUNT * EntryNo; |
94a79942 LF |
133 | TargetCommand |= BIT31|BIT16; |
134 | ||
135 | if (i == 0) { | |
b6da7313 LF |
136 | TargetContent = (u32)(*(MacAddr+0)) << 16 | |
137 | (u32)(*(MacAddr+1)) << 24 | | |
94a79942 LF |
138 | (u32)usConfig; |
139 | ||
8ea54100 MK |
140 | rtl92e_writel(dev, WCAMI, TargetContent); |
141 | rtl92e_writel(dev, RWCAM, TargetCommand); | |
94a79942 | 142 | } else if (i == 1) { |
b6da7313 LF |
143 | TargetContent = (u32)(*(MacAddr+2)) | |
144 | (u32)(*(MacAddr+3)) << 8 | | |
145 | (u32)(*(MacAddr+4)) << 16 | | |
94a79942 | 146 | (u32)(*(MacAddr+5)) << 24; |
8ea54100 MK |
147 | rtl92e_writel(dev, WCAMI, TargetContent); |
148 | rtl92e_writel(dev, RWCAM, TargetCommand); | |
94a79942 LF |
149 | } else { |
150 | if (KeyContent != NULL) { | |
8ea54100 MK |
151 | rtl92e_writel(dev, WCAMI, |
152 | (u32)(*(KeyContent+i-2))); | |
153 | rtl92e_writel(dev, RWCAM, TargetCommand); | |
94a79942 | 154 | udelay(100); |
94a79942 LF |
155 | } |
156 | } | |
157 | } | |
b6da7313 | 158 | RT_TRACE(COMP_SEC, "=========>after set key, usconfig:%x\n", usConfig); |
94a79942 LF |
159 | } |
160 | ||
66497f02 | 161 | void rtl92e_cam_restore(struct net_device *dev) |
94a79942 LF |
162 | { |
163 | u8 EntryId = 0; | |
164 | struct r8192_priv *priv = rtllib_priv(dev); | |
b6da7313 | 165 | u8 *MacAddr = priv->rtllib->current_network.bssid; |
94a79942 LF |
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}, | |
b6da7313 LF |
171 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} |
172 | }; | |
173 | static u8 CAM_CONST_BROAD[] = { | |
174 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff | |
175 | }; | |
94a79942 | 176 | |
66497f02 | 177 | RT_TRACE(COMP_SEC, "rtl92e_cam_restore:\n"); |
94a79942 LF |
178 | |
179 | ||
b6da7313 LF |
180 | if ((priv->rtllib->pairwise_key_type == KEY_TYPE_WEP40) || |
181 | (priv->rtllib->pairwise_key_type == KEY_TYPE_WEP104)) { | |
94a79942 | 182 | |
b6da7313 LF |
183 | for (EntryId = 0; EntryId < 4; EntryId++) { |
184 | MacAddr = CAM_CONST_ADDR[EntryId]; | |
185 | if (priv->rtllib->swcamtable[EntryId].bused) { | |
408bd7b7 MK |
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])); | |
94a79942 LF |
191 | } |
192 | } | |
193 | ||
b6da7313 LF |
194 | } else if (priv->rtllib->pairwise_key_type == KEY_TYPE_TKIP) { |
195 | if (priv->rtllib->iw_mode == IW_MODE_ADHOC) { | |
408bd7b7 MK |
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])); | |
b6da7313 | 201 | } else { |
408bd7b7 MK |
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])); | |
94a79942 | 207 | } |
94a79942 | 208 | |
b6da7313 LF |
209 | } else if (priv->rtllib->pairwise_key_type == KEY_TYPE_CCMP) { |
210 | if (priv->rtllib->iw_mode == IW_MODE_ADHOC) { | |
408bd7b7 MK |
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])); | |
b6da7313 | 216 | } else { |
408bd7b7 MK |
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])); | |
94a79942 | 221 | } |
94a79942 LF |
222 | } |
223 | ||
b6da7313 | 224 | if (priv->rtllib->group_key_type == KEY_TYPE_TKIP) { |
94a79942 | 225 | MacAddr = CAM_CONST_BROAD; |
b6da7313 LF |
226 | for (EntryId = 1; EntryId < 4; EntryId++) { |
227 | if (priv->rtllib->swcamtable[EntryId].bused) { | |
408bd7b7 MK |
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])); | |
94a79942 LF |
232 | } |
233 | } | |
b6da7313 LF |
234 | if (priv->rtllib->iw_mode == IW_MODE_ADHOC) { |
235 | if (priv->rtllib->swcamtable[0].bused) { | |
408bd7b7 MK |
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])); | |
b6da7313 | 240 | } else { |
3b4140af MK |
241 | netdev_warn(dev, |
242 | "%s(): ADHOC TKIP: missing key entry.\n", | |
243 | __func__); | |
94a79942 LF |
244 | return; |
245 | } | |
246 | } | |
247 | } else if (priv->rtllib->group_key_type == KEY_TYPE_CCMP) { | |
248 | MacAddr = CAM_CONST_BROAD; | |
b6da7313 LF |
249 | for (EntryId = 1; EntryId < 4; EntryId++) { |
250 | if (priv->rtllib->swcamtable[EntryId].bused) { | |
408bd7b7 MK |
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])); | |
94a79942 LF |
255 | } |
256 | } | |
257 | ||
258 | if (priv->rtllib->iw_mode == IW_MODE_ADHOC) { | |
259 | if (priv->rtllib->swcamtable[0].bused) { | |
408bd7b7 MK |
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])); | |
94a79942 | 264 | } else { |
3b4140af MK |
265 | netdev_warn(dev, |
266 | "%s(): ADHOC CCMP: missing key entry.\n", | |
267 | __func__); | |
94a79942 LF |
268 | return; |
269 | } | |
270 | } | |
271 | } | |
272 | } |