Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rtl_cam.c
Go to the documentation of this file.
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 <[email protected]>, 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 <[email protected]>
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;
33 {
34  u32 ulcommand = 0;
35 
36  ulcommand |= BIT31|BIT30;
37  write_nic_dword(dev, RWCAM, ulcommand);
38 }
39 
41 {
42  write_nic_dword(dev, WCAMI, data);
43  write_nic_dword(dev, RWCAM, BIT31|BIT16|(addr&0xff));
44 }
45 
47 {
48  write_nic_dword(dev, RWCAM, 0x80000000|(addr&0xff));
49  return read_nic_dword(dev, 0xa8);
50 }
51 
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) &&
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 
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 
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 
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 
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 }