linux/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c
<<
>>
Prefs
   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 * The full GNU General Public License is included in this distribution in the
  16 * file called LICENSE.
  17 *
  18 * Contact Information:
  19 * wlanfae <wlanfae@realtek.com>
  20 *****************************************************************************/
  21#include "rtl_core.h"
  22#include "r8192E_phy.h"
  23#include "r8192E_phyreg.h"
  24#include "r8190P_rtl8256.h" /* RTL8225 Radio frontend */
  25#include "r8192E_cmdpkt.h"
  26
  27void rtl92e_cam_reset(struct net_device *dev)
  28{
  29        u32 ulcommand = 0;
  30
  31        ulcommand |= BIT31|BIT30;
  32        rtl92e_writel(dev, RWCAM, ulcommand);
  33}
  34
  35void rtl92e_enable_hw_security_config(struct net_device *dev)
  36{
  37        u8 SECR_value = 0x0;
  38        struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
  39        struct rtllib_device *ieee = priv->rtllib;
  40
  41        SECR_value = SCR_TxEncEnable | SCR_RxDecEnable;
  42        if (((ieee->pairwise_key_type == KEY_TYPE_WEP40) ||
  43             (ieee->pairwise_key_type == KEY_TYPE_WEP104)) &&
  44             (priv->rtllib->auth_mode != 2)) {
  45                SECR_value |= SCR_RxUseDK;
  46                SECR_value |= SCR_TxUseDK;
  47        } else if ((ieee->iw_mode == IW_MODE_ADHOC) &&
  48                   (ieee->pairwise_key_type & (KEY_TYPE_CCMP |
  49                   KEY_TYPE_TKIP))) {
  50                SECR_value |= SCR_RxUseDK;
  51                SECR_value |= SCR_TxUseDK;
  52        }
  53
  54
  55        ieee->hwsec_active = 1;
  56        if ((ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE) || !hwwep) {
  57                ieee->hwsec_active = 0;
  58                SECR_value &= ~SCR_RxDecEnable;
  59        }
  60
  61        RT_TRACE(COMP_SEC, "%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n",
  62                 __func__, ieee->hwsec_active, ieee->pairwise_key_type,
  63                 SECR_value);
  64        rtl92e_writeb(dev, SECR, SECR_value);
  65}
  66
  67void rtl92e_set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex,
  68                      u16 KeyType, const u8 *MacAddr, u8 DefaultKey,
  69                      u32 *KeyContent, u8 is_mesh)
  70{
  71        struct r8192_priv *priv = rtllib_priv(dev);
  72        struct rtllib_device *ieee = priv->rtllib;
  73
  74        RT_TRACE(COMP_DBG,
  75                 "===========>%s():EntryNo is %d,KeyIndex is %d,KeyType is %d,is_mesh is %d\n",
  76                 __func__, EntryNo, KeyIndex, KeyType, is_mesh);
  77
  78        if (EntryNo >= TOTAL_CAM_ENTRY)
  79                return;
  80
  81        if (!is_mesh) {
  82                ieee->swcamtable[EntryNo].bused = true;
  83                ieee->swcamtable[EntryNo].key_index = KeyIndex;
  84                ieee->swcamtable[EntryNo].key_type = KeyType;
  85                memcpy(ieee->swcamtable[EntryNo].macaddr, MacAddr, 6);
  86                ieee->swcamtable[EntryNo].useDK = DefaultKey;
  87                memcpy(ieee->swcamtable[EntryNo].key_buf, (u8 *)KeyContent, 16);
  88        }
  89}
  90
  91void rtl92e_set_key(struct net_device *dev, u8 EntryNo, u8 KeyIndex,
  92                    u16 KeyType, const u8 *MacAddr, u8 DefaultKey,
  93                    u32 *KeyContent)
  94{
  95        u32 TargetCommand = 0;
  96        u32 TargetContent = 0;
  97        u16 usConfig = 0;
  98        u8 i;
  99        struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
 100        enum rt_rf_power_state rtState;
 101
 102        rtState = priv->rtllib->eRFPowerState;
 103        if (priv->rtllib->PowerSaveControl.bInactivePs) {
 104                if (rtState == eRfOff) {
 105                        if (priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS) {
 106                                netdev_warn(dev, "%s(): RF is OFF.\n",
 107                                            __func__);
 108                                return;
 109                        }
 110                        mutex_lock(&priv->rtllib->ips_mutex);
 111                        rtl92e_ips_leave(dev);
 112                        mutex_unlock(&priv->rtllib->ips_mutex);
 113                }
 114        }
 115        priv->rtllib->is_set_key = true;
 116        if (EntryNo >= TOTAL_CAM_ENTRY) {
 117                netdev_info(dev, "%s(): Invalid CAM entry\n", __func__);
 118                return;
 119        }
 120
 121        RT_TRACE(COMP_SEC,
 122                 "====>to rtl92e_set_key(), dev:%p, EntryNo:%d, KeyIndex:%d,KeyType:%d, MacAddr %pM\n",
 123                 dev, EntryNo, KeyIndex, KeyType, MacAddr);
 124
 125        if (DefaultKey)
 126                usConfig |= BIT15 | (KeyType<<2);
 127        else
 128                usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
 129
 130
 131        for (i = 0; i < CAM_CONTENT_COUNT; i++) {
 132                TargetCommand  = i + CAM_CONTENT_COUNT * EntryNo;
 133                TargetCommand |= BIT31|BIT16;
 134
 135                if (i == 0) {
 136                        TargetContent = (u32)(*(MacAddr+0)) << 16 |
 137                                (u32)(*(MacAddr+1)) << 24 |
 138                                (u32)usConfig;
 139
 140                        rtl92e_writel(dev, WCAMI, TargetContent);
 141                        rtl92e_writel(dev, RWCAM, TargetCommand);
 142                } else if (i == 1) {
 143                        TargetContent = (u32)(*(MacAddr+2)) |
 144                                (u32)(*(MacAddr+3)) <<  8 |
 145                                (u32)(*(MacAddr+4)) << 16 |
 146                                (u32)(*(MacAddr+5)) << 24;
 147                        rtl92e_writel(dev, WCAMI, TargetContent);
 148                        rtl92e_writel(dev, RWCAM, TargetCommand);
 149                } else {
 150                        if (KeyContent != NULL) {
 151                                rtl92e_writel(dev, WCAMI,
 152                                              (u32)(*(KeyContent+i-2)));
 153                                rtl92e_writel(dev, RWCAM, TargetCommand);
 154                                udelay(100);
 155                        }
 156                }
 157        }
 158        RT_TRACE(COMP_SEC, "=========>after set key, usconfig:%x\n", usConfig);
 159}
 160
 161void rtl92e_cam_restore(struct net_device *dev)
 162{
 163        u8 EntryId = 0;
 164        struct r8192_priv *priv = rtllib_priv(dev);
 165        u8 *MacAddr = priv->rtllib->current_network.bssid;
 166
 167        static u8       CAM_CONST_ADDR[4][6] = {
 168                {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
 169                {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
 170                {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
 171                {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
 172        };
 173        static u8       CAM_CONST_BROAD[] = {
 174                0xff, 0xff, 0xff, 0xff, 0xff, 0xff
 175        };
 176
 177        RT_TRACE(COMP_SEC, "rtl92e_cam_restore:\n");
 178
 179
 180        if ((priv->rtllib->pairwise_key_type == KEY_TYPE_WEP40) ||
 181            (priv->rtllib->pairwise_key_type == KEY_TYPE_WEP104)) {
 182
 183                for (EntryId = 0; EntryId < 4; EntryId++) {
 184                        MacAddr = CAM_CONST_ADDR[EntryId];
 185                        if (priv->rtllib->swcamtable[EntryId].bused) {
 186                                rtl92e_set_key(dev, EntryId, EntryId,
 187                                               priv->rtllib->pairwise_key_type,
 188                                               MacAddr, 0,
 189                                               (u32 *)(&priv->rtllib->swcamtable
 190                                                       [EntryId].key_buf[0]));
 191                        }
 192                }
 193
 194        } else if (priv->rtllib->pairwise_key_type == KEY_TYPE_TKIP) {
 195                if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
 196                        rtl92e_set_key(dev, 4, 0,
 197                                       priv->rtllib->pairwise_key_type,
 198                                       (u8 *)dev->dev_addr, 0,
 199                                       (u32 *)(&priv->rtllib->swcamtable[4].
 200                                       key_buf[0]));
 201                } else {
 202                        rtl92e_set_key(dev, 4, 0,
 203                                       priv->rtllib->pairwise_key_type,
 204                                       MacAddr, 0,
 205                                       (u32 *)(&priv->rtllib->swcamtable[4].
 206                                       key_buf[0]));
 207                }
 208
 209        } else if (priv->rtllib->pairwise_key_type == KEY_TYPE_CCMP) {
 210                if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
 211                        rtl92e_set_key(dev, 4, 0,
 212                                       priv->rtllib->pairwise_key_type,
 213                                       (u8 *)dev->dev_addr, 0,
 214                                       (u32 *)(&priv->rtllib->swcamtable[4].
 215                                       key_buf[0]));
 216                } else {
 217                        rtl92e_set_key(dev, 4, 0,
 218                                       priv->rtllib->pairwise_key_type, MacAddr,
 219                                       0, (u32 *)(&priv->rtllib->swcamtable[4].
 220                                       key_buf[0]));
 221                        }
 222        }
 223
 224        if (priv->rtllib->group_key_type == KEY_TYPE_TKIP) {
 225                MacAddr = CAM_CONST_BROAD;
 226                for (EntryId = 1; EntryId < 4; EntryId++) {
 227                        if (priv->rtllib->swcamtable[EntryId].bused) {
 228                                rtl92e_set_key(dev, EntryId, EntryId,
 229                                               priv->rtllib->group_key_type,
 230                                               MacAddr, 0,
 231                                               (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0]));
 232                        }
 233                }
 234                if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
 235                        if (priv->rtllib->swcamtable[0].bused) {
 236                                rtl92e_set_key(dev, 0, 0,
 237                                               priv->rtllib->group_key_type,
 238                                               CAM_CONST_ADDR[0], 0,
 239                                               (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0]));
 240                        } else {
 241                                netdev_warn(dev,
 242                                            "%s(): ADHOC TKIP: missing key entry.\n",
 243                                            __func__);
 244                                return;
 245                        }
 246                }
 247        } else if (priv->rtllib->group_key_type == KEY_TYPE_CCMP) {
 248                MacAddr = CAM_CONST_BROAD;
 249                for (EntryId = 1; EntryId < 4; EntryId++) {
 250                        if (priv->rtllib->swcamtable[EntryId].bused) {
 251                                rtl92e_set_key(dev, EntryId, EntryId,
 252                                               priv->rtllib->group_key_type,
 253                                               MacAddr, 0,
 254                                               (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0]));
 255                        }
 256                }
 257
 258                if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
 259                        if (priv->rtllib->swcamtable[0].bused) {
 260                                rtl92e_set_key(dev, 0, 0,
 261                                               priv->rtllib->group_key_type,
 262                                               CAM_CONST_ADDR[0], 0,
 263                                               (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0]));
 264                        } else {
 265                                netdev_warn(dev,
 266                                            "%s(): ADHOC CCMP: missing key entry.\n",
 267                                            __func__);
 268                                return;
 269                        }
 270                }
 271        }
 272}
 273