1 /******************************************************************************
2 * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
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.
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
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
19 * The full GNU General Public License is included in this distribution in the
20 * file called LICENSE.
22 * Contact Information:
23 * wlanfae <wlanfae@realtek.com>
24 ******************************************************************************/
26 #include "r8192E_phy.h"
27 #include "r8192E_phyreg.h"
28 #include "r8190P_rtl8256.h" /* RTL8225 Radio frontend */
29 #include "r8192E_cmdpkt.h"
31 void CamResetAllEntry(struct net_device *dev)
35 ulcommand |= BIT31|BIT30;
36 write_nic_dword(dev, RWCAM, ulcommand);
39 void write_cam(struct net_device *dev, u8 addr, u32 data)
41 write_nic_dword(dev, WCAMI, data);
42 write_nic_dword(dev, RWCAM, BIT31|BIT16|(addr&0xff));
45 u32 read_cam(struct net_device *dev, u8 addr)
47 write_nic_dword(dev, RWCAM, 0x80000000|(addr&0xff));
48 return read_nic_dword(dev, 0xa8);
51 void EnableHWSecurityConfig8192(struct net_device *dev)
54 struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
55 struct rtllib_device *ieee = priv->rtllib;
56 SECR_value = SCR_TxEncEnable | SCR_RxDecEnable;
57 if (((KEY_TYPE_WEP40 == ieee->pairwise_key_type) ||
58 (KEY_TYPE_WEP104 == ieee->pairwise_key_type)) &&
59 (priv->rtllib->auth_mode != 2)) {
60 SECR_value |= SCR_RxUseDK;
61 SECR_value |= SCR_TxUseDK;
62 } else if ((ieee->iw_mode == IW_MODE_ADHOC) &&
63 (ieee->pairwise_key_type & (KEY_TYPE_CCMP |
65 SECR_value |= SCR_RxUseDK;
66 SECR_value |= SCR_TxUseDK;
70 ieee->hwsec_active = 1;
71 if ((ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE) || !hwwep) {
72 ieee->hwsec_active = 0;
73 SECR_value &= ~SCR_RxDecEnable;
76 RT_TRACE(COMP_SEC, "%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n",
77 __func__, ieee->hwsec_active, ieee->pairwise_key_type,
79 write_nic_byte(dev, SECR, SECR_value);
82 void set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
83 u8 *MacAddr, u8 DefaultKey, u32 *KeyContent, u8 is_mesh)
85 struct r8192_priv *priv = rtllib_priv(dev);
86 struct rtllib_device *ieee = priv->rtllib;
87 RT_TRACE(COMP_DBG, "===========>%s():EntryNo is %d,KeyIndex is "
88 "%d,KeyType is %d,is_mesh is %d\n", __func__, EntryNo,
89 KeyIndex, KeyType, is_mesh);
91 ieee->swcamtable[EntryNo].bused = true;
92 ieee->swcamtable[EntryNo].key_index = KeyIndex;
93 ieee->swcamtable[EntryNo].key_type = KeyType;
94 memcpy(ieee->swcamtable[EntryNo].macaddr, MacAddr, 6);
95 ieee->swcamtable[EntryNo].useDK = DefaultKey;
96 memcpy(ieee->swcamtable[EntryNo].key_buf, (u8 *)KeyContent, 16);
100 void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
101 u8 *MacAddr, u8 DefaultKey, u32 *KeyContent)
103 u32 TargetCommand = 0;
104 u32 TargetContent = 0;
107 struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
108 enum rt_rf_power_state rtState;
109 rtState = priv->rtllib->eRFPowerState;
110 if (priv->rtllib->PowerSaveControl.bInactivePs) {
111 if (rtState == eRfOff) {
112 if (priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS) {
113 RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",
117 down(&priv->rtllib->ips_sem);
119 up(&priv->rtllib->ips_sem);
123 priv->rtllib->is_set_key = true;
124 if (EntryNo >= TOTAL_CAM_ENTRY)
125 RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
127 RT_TRACE(COMP_SEC, "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d,"
128 "KeyType:%d, MacAddr %pM\n", dev, EntryNo, KeyIndex,
132 usConfig |= BIT15 | (KeyType<<2);
134 usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
137 for (i = 0; i < CAM_CONTENT_COUNT; i++) {
138 TargetCommand = i + CAM_CONTENT_COUNT * EntryNo;
139 TargetCommand |= BIT31|BIT16;
142 TargetContent = (u32)(*(MacAddr+0)) << 16 |
143 (u32)(*(MacAddr+1)) << 24 |
146 write_nic_dword(dev, WCAMI, TargetContent);
147 write_nic_dword(dev, RWCAM, TargetCommand);
149 TargetContent = (u32)(*(MacAddr+2)) |
150 (u32)(*(MacAddr+3)) << 8 |
151 (u32)(*(MacAddr+4)) << 16 |
152 (u32)(*(MacAddr+5)) << 24;
153 write_nic_dword(dev, WCAMI, TargetContent);
154 write_nic_dword(dev, RWCAM, TargetCommand);
156 if (KeyContent != NULL) {
157 write_nic_dword(dev, WCAMI,
158 (u32)(*(KeyContent+i-2)));
159 write_nic_dword(dev, RWCAM, TargetCommand);
164 RT_TRACE(COMP_SEC, "=========>after set key, usconfig:%x\n", usConfig);
167 void CAM_read_entry(struct net_device *dev, u32 iIndex)
169 u32 target_command = 0;
170 u32 target_content = 0;
174 for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
175 target_command = entry_i+CAM_CONTENT_COUNT*iIndex;
176 target_command = target_command | BIT31;
179 ulStatus = read_nic_dword(dev, RWCAM);
180 if (ulStatus & BIT31)
185 write_nic_dword(dev, RWCAM, target_command);
186 RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A0: %x\n",
188 target_content = read_nic_dword(dev, RCAMO);
189 RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A8: %x\n",
192 printk(KERN_INFO "\n");
195 void CamRestoreAllEntry(struct net_device *dev)
198 struct r8192_priv *priv = rtllib_priv(dev);
199 u8 *MacAddr = priv->rtllib->current_network.bssid;
201 static u8 CAM_CONST_ADDR[4][6] = {
202 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
203 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
204 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
205 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
207 static u8 CAM_CONST_BROAD[] = {
208 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
211 RT_TRACE(COMP_SEC, "CamRestoreAllEntry:\n");
214 if ((priv->rtllib->pairwise_key_type == KEY_TYPE_WEP40) ||
215 (priv->rtllib->pairwise_key_type == KEY_TYPE_WEP104)) {
217 for (EntryId = 0; EntryId < 4; EntryId++) {
218 MacAddr = CAM_CONST_ADDR[EntryId];
219 if (priv->rtllib->swcamtable[EntryId].bused) {
220 setKey(dev, EntryId , EntryId,
221 priv->rtllib->pairwise_key_type, MacAddr,
222 0, (u32 *)(&priv->rtllib->swcamtable
223 [EntryId].key_buf[0]));
227 } else if (priv->rtllib->pairwise_key_type == KEY_TYPE_TKIP) {
228 if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
229 setKey(dev, 4, 0, priv->rtllib->pairwise_key_type,
230 (u8 *)dev->dev_addr, 0,
231 (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0]));
233 setKey(dev, 4, 0, priv->rtllib->pairwise_key_type,
235 (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0]));
238 } else if (priv->rtllib->pairwise_key_type == KEY_TYPE_CCMP) {
239 if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
241 priv->rtllib->pairwise_key_type,
242 (u8 *)dev->dev_addr, 0,
243 (u32 *)(&priv->rtllib->swcamtable[4].
247 priv->rtllib->pairwise_key_type, MacAddr,
248 0, (u32 *)(&priv->rtllib->swcamtable[4].
253 if (priv->rtllib->group_key_type == KEY_TYPE_TKIP) {
254 MacAddr = CAM_CONST_BROAD;
255 for (EntryId = 1; EntryId < 4; EntryId++) {
256 if (priv->rtllib->swcamtable[EntryId].bused) {
257 setKey(dev, EntryId, EntryId,
258 priv->rtllib->group_key_type,
260 (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0])
264 if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
265 if (priv->rtllib->swcamtable[0].bused) {
267 priv->rtllib->group_key_type,
268 CAM_CONST_ADDR[0], 0,
269 (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0])
272 RT_TRACE(COMP_ERR, "===>%s():ERR!! ADHOC TKIP "
273 ",but 0 entry is have no data\n",
278 } else if (priv->rtllib->group_key_type == KEY_TYPE_CCMP) {
279 MacAddr = CAM_CONST_BROAD;
280 for (EntryId = 1; EntryId < 4; EntryId++) {
281 if (priv->rtllib->swcamtable[EntryId].bused) {
282 setKey(dev, EntryId , EntryId,
283 priv->rtllib->group_key_type,
285 (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0]));
289 if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
290 if (priv->rtllib->swcamtable[0].bused) {
292 priv->rtllib->group_key_type,
293 CAM_CONST_ADDR[0], 0,
294 (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0]));
296 RT_TRACE(COMP_ERR, "===>%s():ERR!! ADHOC CCMP ,"
297 "but 0 entry is have no data\n",