Linux-libre 3.16.78-gnu
[librecmc/linux-libre.git] / drivers / staging / rtl8192e / rtl8192e / rtl_cam.c
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
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
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
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
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         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 |
64                    KEY_TYPE_TKIP))) {
65                 SECR_value |= SCR_RxUseDK;
66                 SECR_value |= SCR_TxUseDK;
67         }
68
69
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;
74         }
75
76         RT_TRACE(COMP_SEC, "%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n",
77                  __func__, ieee->hwsec_active, ieee->pairwise_key_type,
78                  SECR_value);
79         write_nic_byte(dev, SECR,  SECR_value);
80 }
81
82 void set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
83                u8 *MacAddr, u8 DefaultKey, u32 *KeyContent, u8 is_mesh)
84 {
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);
90         if (!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);
97         }
98 }
99
100 void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
101             u8 *MacAddr, u8 DefaultKey, u32 *KeyContent)
102 {
103         u32 TargetCommand = 0;
104         u32 TargetContent = 0;
105         u16 usConfig = 0;
106         u8 i;
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",
114                                         __func__);
115                                 return ;
116                         } else {
117                                 down(&priv->rtllib->ips_sem);
118                                 IPSLeave(dev);
119                                 up(&priv->rtllib->ips_sem);
120                         }
121                 }
122         }
123         priv->rtllib->is_set_key = true;
124         if (EntryNo >= TOTAL_CAM_ENTRY)
125                 RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
126
127         RT_TRACE(COMP_SEC, "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d,"
128                  "KeyType:%d, MacAddr %pM\n", dev, EntryNo, KeyIndex,
129                  KeyType, MacAddr);
130
131         if (DefaultKey)
132                 usConfig |= BIT15 | (KeyType<<2);
133         else
134                 usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
135
136
137         for (i = 0; i < CAM_CONTENT_COUNT; i++) {
138                 TargetCommand  = i + CAM_CONTENT_COUNT * EntryNo;
139                 TargetCommand |= BIT31|BIT16;
140
141                 if (i == 0) {
142                         TargetContent = (u32)(*(MacAddr+0)) << 16 |
143                                 (u32)(*(MacAddr+1)) << 24 |
144                                 (u32)usConfig;
145
146                         write_nic_dword(dev, WCAMI, TargetContent);
147                         write_nic_dword(dev, RWCAM, TargetCommand);
148                 } else if (i == 1) {
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);
155                 } else {
156                         if (KeyContent != NULL) {
157                                 write_nic_dword(dev, WCAMI,
158                                                 (u32)(*(KeyContent+i-2)));
159                                 write_nic_dword(dev, RWCAM, TargetCommand);
160                                 udelay(100);
161                         }
162                 }
163         }
164         RT_TRACE(COMP_SEC, "=========>after set key, usconfig:%x\n", usConfig);
165 }
166
167 void CAM_read_entry(struct net_device *dev, u32 iIndex)
168 {
169         u32 target_command = 0;
170         u32 target_content = 0;
171         u8 entry_i = 0;
172         u32 ulStatus;
173         s32 i = 100;
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;
177
178                 while ((i--) >= 0) {
179                         ulStatus = read_nic_dword(dev, RWCAM);
180                         if (ulStatus & BIT31)
181                                 continue;
182                         else
183                                 break;
184                 }
185                 write_nic_dword(dev, RWCAM, target_command);
186                 RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A0: %x\n",
187                          target_command);
188                 target_content = read_nic_dword(dev, RCAMO);
189                 RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A8: %x\n",
190                          target_content);
191         }
192         printk(KERN_INFO "\n");
193 }
194
195 void CamRestoreAllEntry(struct net_device *dev)
196 {
197         u8 EntryId = 0;
198         struct r8192_priv *priv = rtllib_priv(dev);
199         u8 *MacAddr = priv->rtllib->current_network.bssid;
200
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}
206         };
207         static u8       CAM_CONST_BROAD[] = {
208                 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
209         };
210
211         RT_TRACE(COMP_SEC, "CamRestoreAllEntry:\n");
212
213
214         if ((priv->rtllib->pairwise_key_type == KEY_TYPE_WEP40) ||
215             (priv->rtllib->pairwise_key_type == KEY_TYPE_WEP104)) {
216
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]));
224                         }
225                 }
226
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]));
232                 } else {
233                         setKey(dev, 4, 0, priv->rtllib->pairwise_key_type,
234                                MacAddr, 0,
235                                (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0]));
236                 }
237
238         } else if (priv->rtllib->pairwise_key_type == KEY_TYPE_CCMP) {
239                 if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
240                         setKey(dev, 4, 0,
241                                priv->rtllib->pairwise_key_type,
242                                (u8 *)dev->dev_addr, 0,
243                                (u32 *)(&priv->rtllib->swcamtable[4].
244                                key_buf[0]));
245                 } else {
246                         setKey(dev, 4, 0,
247                                priv->rtllib->pairwise_key_type, MacAddr,
248                                0, (u32 *)(&priv->rtllib->swcamtable[4].
249                                key_buf[0]));
250                         }
251         }
252
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,
259                                         MacAddr, 0,
260                                         (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0])
261                                      );
262                         }
263                 }
264                 if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
265                         if (priv->rtllib->swcamtable[0].bused) {
266                                 setKey(dev, 0, 0,
267                                        priv->rtllib->group_key_type,
268                                        CAM_CONST_ADDR[0], 0,
269                                        (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0])
270                                      );
271                         } else {
272                                 RT_TRACE(COMP_ERR, "===>%s():ERR!! ADHOC TKIP "
273                                          ",but 0 entry is have no data\n",
274                                          __func__);
275                                 return;
276                         }
277                 }
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,
284                                        MacAddr, 0,
285                                        (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0]));
286                         }
287                 }
288
289                 if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
290                         if (priv->rtllib->swcamtable[0].bused) {
291                                 setKey(dev, 0 , 0,
292                                         priv->rtllib->group_key_type,
293                                         CAM_CONST_ADDR[0], 0,
294                                         (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0]));
295                         } else {
296                                 RT_TRACE(COMP_ERR, "===>%s():ERR!! ADHOC CCMP ,"
297                                          "but 0 entry is have no data\n",
298                                          __func__);
299                                 return;
300                         }
301                 }
302         }
303 }