summaryrefslogtreecommitdiffstats
path: root/drivers/staging/rtl8192e/rtl_cam.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/rtl8192e/rtl_cam.c')
-rw-r--r--drivers/staging/rtl8192e/rtl_cam.c379
1 files changed, 379 insertions, 0 deletions
diff --git a/drivers/staging/rtl8192e/rtl_cam.c b/drivers/staging/rtl8192e/rtl_cam.c
new file mode 100644
index 000000000000..c2d51bc5a878
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl_cam.c
@@ -0,0 +1,379 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#include "rtl_core.h"
+#include "r8192E_phy.h"
+#include "r8192E_phyreg.h"
+#include "r8190P_rtl8256.h" /* RTL8225 Radio frontend */
+#include "r8192E_cmdpkt.h"
+
+extern int hwwep;
+void CamResetAllEntry(struct net_device *dev)
+{
+ u32 ulcommand = 0;
+
+ ulcommand |= BIT31|BIT30;
+ write_nic_dword(dev, RWCAM, ulcommand);
+}
+
+void write_cam(struct net_device *dev, u8 addr, u32 data)
+{
+ write_nic_dword(dev, WCAMI, data);
+ write_nic_dword(dev, RWCAM, BIT31|BIT16|(addr&0xff) );
+}
+
+u32 read_cam(struct net_device *dev, u8 addr)
+{
+ write_nic_dword(dev, RWCAM, 0x80000000|(addr&0xff) );
+ return read_nic_dword(dev, 0xa8);
+}
+
+void EnableHWSecurityConfig8192(struct net_device *dev)
+{
+ u8 SECR_value = 0x0;
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+ struct rtllib_device* ieee = priv->rtllib;
+ SECR_value = SCR_TxEncEnable | SCR_RxDecEnable;
+ if (((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type)) && (priv->rtllib->auth_mode != 2))
+ {
+ SECR_value |= SCR_RxUseDK;
+ SECR_value |= SCR_TxUseDK;
+ }
+ else if ((ieee->iw_mode == IW_MODE_ADHOC) && (ieee->pairwise_key_type & (KEY_TYPE_CCMP | KEY_TYPE_TKIP)))
+ {
+ SECR_value |= SCR_RxUseDK;
+ SECR_value |= SCR_TxUseDK;
+ }
+
+
+ ieee->hwsec_active = 1;
+ if ((ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE) || !hwwep)
+ {
+ ieee->hwsec_active = 0;
+ SECR_value &= ~SCR_RxDecEnable;
+ }
+
+ RT_TRACE(COMP_SEC,"%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n", __func__, \
+ ieee->hwsec_active, ieee->pairwise_key_type, SECR_value);
+ {
+ write_nic_byte(dev, SECR, SECR_value);
+ }
+}
+
+void set_swcam(struct net_device *dev,
+ u8 EntryNo,
+ u8 KeyIndex,
+ u16 KeyType,
+ u8 *MacAddr,
+ u8 DefaultKey,
+ u32 *KeyContent,
+ u8 is_mesh)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rtllib_device *ieee = priv->rtllib;
+ RT_TRACE(COMP_DBG, "===========>%s():EntryNo is %d,KeyIndex is "
+ "%d,KeyType is %d,is_mesh is %d\n", __func__, EntryNo,
+ KeyIndex, KeyType, is_mesh);
+ if (is_mesh){
+ } else {
+ ieee->swcamtable[EntryNo].bused=true;
+ ieee->swcamtable[EntryNo].key_index=KeyIndex;
+ ieee->swcamtable[EntryNo].key_type=KeyType;
+ memcpy(ieee->swcamtable[EntryNo].macaddr,MacAddr,6);
+ ieee->swcamtable[EntryNo].useDK=DefaultKey;
+ memcpy(ieee->swcamtable[EntryNo].key_buf,(u8*)KeyContent,16);
+ }
+}
+
+void setKey(struct net_device *dev,
+ u8 EntryNo,
+ u8 KeyIndex,
+ u16 KeyType,
+ u8 *MacAddr,
+ u8 DefaultKey,
+ u32 *KeyContent )
+{
+ u32 TargetCommand = 0;
+ u32 TargetContent = 0;
+ u16 usConfig = 0;
+ u8 i;
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+ RT_RF_POWER_STATE rtState;
+ rtState = priv->rtllib->eRFPowerState;
+ if (priv->rtllib->PowerSaveControl.bInactivePs){
+ if (rtState == eRfOff){
+ if (priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS)
+ {
+ RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__func__);
+ return ;
+ }
+ else{
+ down(&priv->rtllib->ips_sem);
+ IPSLeave(dev);
+ up(&priv->rtllib->ips_sem); }
+ }
+ }
+ priv->rtllib->is_set_key = true;
+ if (EntryNo >= TOTAL_CAM_ENTRY)
+ RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
+
+ RT_TRACE(COMP_SEC, "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d,"
+ "KeyType:%d, MacAddr"MAC_FMT"\n", dev,EntryNo, KeyIndex,
+ KeyType, MAC_ARG(MacAddr));
+
+ if (DefaultKey)
+ usConfig |= BIT15 | (KeyType<<2);
+ else
+ usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
+
+
+ for (i = 0; i < CAM_CONTENT_COUNT; i++) {
+ TargetCommand = i+CAM_CONTENT_COUNT*EntryNo;
+ TargetCommand |= BIT31|BIT16;
+
+ if (i == 0) {
+ TargetContent = (u32)(*(MacAddr+0)) << 16|
+ (u32)(*(MacAddr+1)) << 24|
+ (u32)usConfig;
+
+ write_nic_dword(dev, WCAMI, TargetContent);
+ write_nic_dword(dev, RWCAM, TargetCommand);
+ } else if (i == 1) {
+ TargetContent = (u32)(*(MacAddr+2)) |
+ (u32)(*(MacAddr+3)) << 8|
+ (u32)(*(MacAddr+4)) << 16|
+ (u32)(*(MacAddr+5)) << 24;
+ write_nic_dword(dev, WCAMI, TargetContent);
+ write_nic_dword(dev, RWCAM, TargetCommand);
+ } else {
+ if (KeyContent != NULL) {
+ write_nic_dword(dev, WCAMI, (u32)(*(KeyContent+i-2)) );
+ write_nic_dword(dev, RWCAM, TargetCommand);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31))
+ udelay(100);
+#endif
+ }
+ }
+ }
+ RT_TRACE(COMP_SEC,"=========>after set key, usconfig:%x\n", usConfig);
+}
+
+void CAM_read_entry(struct net_device *dev, u32 iIndex)
+{
+ u32 target_command=0;
+ u32 target_content=0;
+ u8 entry_i=0;
+ u32 ulStatus;
+ s32 i=100;
+ for (entry_i=0;entry_i<CAM_CONTENT_COUNT;entry_i++)
+ {
+ target_command= entry_i+CAM_CONTENT_COUNT*iIndex;
+ target_command= target_command | BIT31;
+
+ while((i--)>=0)
+ {
+ ulStatus = read_nic_dword(dev, RWCAM);
+ if (ulStatus & BIT31){
+ continue;
+ }
+ else{
+ break;
+ }
+ }
+ write_nic_dword(dev, RWCAM, target_command);
+ RT_TRACE(COMP_SEC,"CAM_read_entry(): WRITE A0: %x \n",target_command);
+ target_content = read_nic_dword(dev, RCAMO);
+ RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A8: %x \n",target_content);
+ }
+ printk("\n");
+}
+
+void CamRestoreAllEntry( struct net_device *dev)
+{
+ u8 EntryId = 0;
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u8* MacAddr = priv->rtllib->current_network.bssid;
+
+ static u8 CAM_CONST_ADDR[4][6] = {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}};
+ static u8 CAM_CONST_BROAD[] =
+ {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+ RT_TRACE(COMP_SEC, "CamRestoreAllEntry: \n");
+
+
+ if ((priv->rtllib->pairwise_key_type == KEY_TYPE_WEP40)||
+ (priv->rtllib->pairwise_key_type == KEY_TYPE_WEP104))
+ {
+
+ for (EntryId=0; EntryId<4; EntryId++)
+ {
+ {
+ MacAddr = CAM_CONST_ADDR[EntryId];
+ if (priv->rtllib->swcamtable[EntryId].bused )
+ {
+ setKey(dev,
+ EntryId ,
+ EntryId,
+ priv->rtllib->pairwise_key_type,
+ MacAddr,
+ 0,
+ (u32*)(&priv->rtllib->swcamtable[EntryId].key_buf[0])
+ );
+ }
+ }
+ }
+
+ }
+ else if (priv->rtllib->pairwise_key_type == KEY_TYPE_TKIP)
+ {
+
+ {
+ if (priv->rtllib->iw_mode == IW_MODE_ADHOC)
+ {
+ setKey(dev,
+ 4,
+ 0,
+ priv->rtllib->pairwise_key_type,
+ (u8*)dev->dev_addr,
+ 0,
+ (u32*)(&priv->rtllib->swcamtable[4].key_buf[0])
+ );
+ }
+ else
+ {
+ setKey(dev,
+ 4,
+ 0,
+ priv->rtllib->pairwise_key_type,
+ MacAddr,
+ 0,
+ (u32*)(&priv->rtllib->swcamtable[4].key_buf[0])
+ );
+ }
+
+ }
+ }
+ else if (priv->rtllib->pairwise_key_type == KEY_TYPE_CCMP)
+ {
+
+ {
+ if (priv->rtllib->iw_mode == IW_MODE_ADHOC)
+ {
+ setKey(dev,
+ 4,
+ 0,
+ priv->rtllib->pairwise_key_type,
+ (u8*)dev->dev_addr,
+ 0,
+ (u32*)(&priv->rtllib->swcamtable[4].key_buf[0])
+ );
+ }
+ else
+ {
+ setKey(dev,
+ 4,
+ 0,
+ priv->rtllib->pairwise_key_type,
+ MacAddr,
+ 0,
+ (u32*)(&priv->rtllib->swcamtable[4].key_buf[0])
+ );
+ }
+ }
+ }
+
+
+
+ if (priv->rtllib->group_key_type == KEY_TYPE_TKIP)
+ {
+ MacAddr = CAM_CONST_BROAD;
+ for (EntryId=1 ; EntryId<4 ; EntryId++)
+ {
+ if (priv->rtllib->swcamtable[EntryId].bused )
+ {
+ setKey(dev,
+ EntryId,
+ EntryId,
+ priv->rtllib->group_key_type,
+ MacAddr,
+ 0,
+ (u32*)(&priv->rtllib->swcamtable[EntryId].key_buf[0])
+ );
+ }
+ }
+ if (priv->rtllib->iw_mode == IW_MODE_ADHOC)
+ {
+ if (priv->rtllib->swcamtable[0].bused ){
+ setKey(dev,
+ 0,
+ 0,
+ priv->rtllib->group_key_type,
+ CAM_CONST_ADDR[0],
+ 0,
+ (u32*)(&priv->rtllib->swcamtable[0].key_buf[0])
+ );
+ }
+ else
+ {
+ RT_TRACE(COMP_ERR,"===>%s():ERR!! ADHOC TKIP ,but 0 entry is have no data\n",__func__);
+ return;
+ }
+ }
+ } else if (priv->rtllib->group_key_type == KEY_TYPE_CCMP) {
+ MacAddr = CAM_CONST_BROAD;
+ for (EntryId=1; EntryId<4 ; EntryId++)
+ {
+ if (priv->rtllib->swcamtable[EntryId].bused )
+ {
+ setKey(dev,
+ EntryId ,
+ EntryId,
+ priv->rtllib->group_key_type,
+ MacAddr,
+ 0,
+ (u32*)(&priv->rtllib->swcamtable[EntryId].key_buf[0]));
+ }
+ }
+
+ if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
+ if (priv->rtllib->swcamtable[0].bused) {
+ setKey(dev,
+ 0 ,
+ 0,
+ priv->rtllib->group_key_type,
+ CAM_CONST_ADDR[0],
+ 0,
+ (u32*)(&priv->rtllib->swcamtable[0].key_buf[0]));
+ } else {
+ RT_TRACE(COMP_ERR,"===>%s():ERR!! ADHOC CCMP ,but 0 entry is have no data\n",
+ __func__);
+ return;
+ }
+ }
+ }
+}