| /****************************************************************************** |
| * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. |
| * |
| * Based on the r8180 driver, which is: |
| * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, 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. |
| * |
| * 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" |
| |
| void rtl92e_cam_reset(struct net_device *dev) |
| { |
| u32 ulcommand = 0; |
| |
| ulcommand |= BIT31|BIT30; |
| rtl92e_writel(dev, RWCAM, ulcommand); |
| } |
| |
| void rtl92e_enable_hw_security_config(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 (((ieee->pairwise_key_type == KEY_TYPE_WEP40) || |
| (ieee->pairwise_key_type == KEY_TYPE_WEP104)) && |
| (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); |
| rtl92e_writeb(dev, SECR, SECR_value); |
| } |
| |
| void rtl92e_set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex, |
| u16 KeyType, const 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 (EntryNo >= TOTAL_CAM_ENTRY) |
| return; |
| |
| 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 rtl92e_set_key(struct net_device *dev, u8 EntryNo, u8 KeyIndex, |
| u16 KeyType, const 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) { |
| netdev_warn(dev, "%s(): RF is OFF.\n", |
| __func__); |
| return; |
| } |
| down(&priv->rtllib->ips_sem); |
| rtl92e_ips_leave(dev); |
| up(&priv->rtllib->ips_sem); |
| } |
| } |
| priv->rtllib->is_set_key = true; |
| if (EntryNo >= TOTAL_CAM_ENTRY) { |
| netdev_info(dev, "%s(): Invalid CAM entry\n", __func__); |
| return; |
| } |
| |
| RT_TRACE(COMP_SEC, |
| "====>to rtl92e_set_key(), 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; |
| |
| rtl92e_writel(dev, WCAMI, TargetContent); |
| rtl92e_writel(dev, RWCAM, TargetCommand); |
| } else if (i == 1) { |
| TargetContent = (u32)(*(MacAddr+2)) | |
| (u32)(*(MacAddr+3)) << 8 | |
| (u32)(*(MacAddr+4)) << 16 | |
| (u32)(*(MacAddr+5)) << 24; |
| rtl92e_writel(dev, WCAMI, TargetContent); |
| rtl92e_writel(dev, RWCAM, TargetCommand); |
| } else { |
| if (KeyContent != NULL) { |
| rtl92e_writel(dev, WCAMI, |
| (u32)(*(KeyContent+i-2))); |
| rtl92e_writel(dev, RWCAM, TargetCommand); |
| udelay(100); |
| } |
| } |
| } |
| RT_TRACE(COMP_SEC, "=========>after set key, usconfig:%x\n", usConfig); |
| } |
| |
| void rtl92e_cam_restore(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, "rtl92e_cam_restore:\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) { |
| rtl92e_set_key(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) { |
| rtl92e_set_key(dev, 4, 0, |
| priv->rtllib->pairwise_key_type, |
| (u8 *)dev->dev_addr, 0, |
| (u32 *)(&priv->rtllib->swcamtable[4]. |
| key_buf[0])); |
| } else { |
| rtl92e_set_key(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) { |
| rtl92e_set_key(dev, 4, 0, |
| priv->rtllib->pairwise_key_type, |
| (u8 *)dev->dev_addr, 0, |
| (u32 *)(&priv->rtllib->swcamtable[4]. |
| key_buf[0])); |
| } else { |
| rtl92e_set_key(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) { |
| rtl92e_set_key(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) { |
| rtl92e_set_key(dev, 0, 0, |
| priv->rtllib->group_key_type, |
| CAM_CONST_ADDR[0], 0, |
| (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0])); |
| } else { |
| netdev_warn(dev, |
| "%s(): ADHOC TKIP: missing key entry.\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) { |
| rtl92e_set_key(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) { |
| rtl92e_set_key(dev, 0, 0, |
| priv->rtllib->group_key_type, |
| CAM_CONST_ADDR[0], 0, |
| (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0])); |
| } else { |
| netdev_warn(dev, |
| "%s(): ADHOC CCMP: missing key entry.\n", |
| __func__); |
| return; |
| } |
| } |
| } |
| } |