/****************************************************************************** * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. * * Based on the r8180 driver, which is: * Copyright 2004-2005 Andrea Merello , 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 ******************************************************************************/ #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) { 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); enum 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 %pM\n", dev, EntryNo, KeyIndex, KeyType, 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); udelay(100); } } } 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(KERN_INFO "\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; } } } }