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 <andreamrl@tiscali.it>, 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 31extern int hwwep; 32void CamResetAllEntry(struct net_device *dev) 33{ 34 u32 ulcommand = 0; 35 36 ulcommand |= BIT31|BIT30; 37 write_nic_dword(dev, RWCAM, ulcommand); 38} 39 40void write_cam(struct net_device *dev, u8 addr, u32 data) 41{ 42 write_nic_dword(dev, WCAMI, data); 43 write_nic_dword(dev, RWCAM, BIT31|BIT16|(addr&0xff)); 44} 45 46u32 read_cam(struct net_device *dev, u8 addr) 47{ 48 write_nic_dword(dev, RWCAM, 0x80000000|(addr&0xff)); 49 return read_nic_dword(dev, 0xa8); 50} 51 52void EnableHWSecurityConfig8192(struct net_device *dev) 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) && 64 (ieee->pairwise_key_type & (KEY_TYPE_CCMP | 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 83void 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 101void 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 168void 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 196void CamRestoreAllEntry(struct net_device *dev) 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} 305