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 * 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
  31void CamResetAllEntry(struct net_device *dev)
  32{
  33        u32 ulcommand = 0;
  34
  35        ulcommand |= BIT31|BIT30;
  36        write_nic_dword(dev, RWCAM, ulcommand);
  37}
  38
  39void write_cam(struct net_device *dev, u8 addr, u32 data)
  40{
  41        write_nic_dword(dev, WCAMI, data);
  42        write_nic_dword(dev, RWCAM, BIT31|BIT16|(addr&0xff));
  43}
  44
  45u32 read_cam(struct net_device *dev, u8 addr)
  46{
  47        write_nic_dword(dev, RWCAM, 0x80000000|(addr&0xff));
  48        return read_nic_dword(dev, 0xa8);
  49}
  50
  51void EnableHWSecurityConfig8192(struct net_device *dev)
  52{
  53        u8 SECR_value = 0x0;
  54        struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
  55        struct rtllib_device *ieee = priv->rtllib;
  56
  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
  89        RT_TRACE(COMP_DBG, "===========>%s():EntryNo is %d,KeyIndex is "
  90                 "%d,KeyType is %d,is_mesh is %d\n", __func__, EntryNo,
  91                 KeyIndex, KeyType, is_mesh);
  92        if (!is_mesh) {
  93                ieee->swcamtable[EntryNo].bused = true;
  94                ieee->swcamtable[EntryNo].key_index = KeyIndex;
  95                ieee->swcamtable[EntryNo].key_type = KeyType;
  96                memcpy(ieee->swcamtable[EntryNo].macaddr, MacAddr, 6);
  97                ieee->swcamtable[EntryNo].useDK = DefaultKey;
  98                memcpy(ieee->swcamtable[EntryNo].key_buf, (u8 *)KeyContent, 16);
  99        }
 100}
 101
 102void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
 103            u8 *MacAddr, u8 DefaultKey, u32 *KeyContent)
 104{
 105        u32 TargetCommand = 0;
 106        u32 TargetContent = 0;
 107        u16 usConfig = 0;
 108        u8 i;
 109        struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
 110        enum rt_rf_power_state rtState;
 111
 112        rtState = priv->rtllib->eRFPowerState;
 113        if (priv->rtllib->PowerSaveControl.bInactivePs) {
 114                if (rtState == eRfOff) {
 115                        if (priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS) {
 116                                RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",
 117                                        __func__);
 118                                return ;
 119                        } else {
 120                                down(&priv->rtllib->ips_sem);
 121                                IPSLeave(dev);
 122                                up(&priv->rtllib->ips_sem);
 123                        }
 124                }
 125        }
 126        priv->rtllib->is_set_key = true;
 127        if (EntryNo >= TOTAL_CAM_ENTRY)
 128                RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
 129
 130        RT_TRACE(COMP_SEC, "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d,"
 131                 "KeyType:%d, MacAddr %pM\n", dev, EntryNo, KeyIndex,
 132                 KeyType, MacAddr);
 133
 134        if (DefaultKey)
 135                usConfig |= BIT15 | (KeyType<<2);
 136        else
 137                usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
 138
 139
 140        for (i = 0; i < CAM_CONTENT_COUNT; i++) {
 141                TargetCommand  = i + CAM_CONTENT_COUNT * EntryNo;
 142                TargetCommand |= BIT31|BIT16;
 143
 144                if (i == 0) {
 145                        TargetContent = (u32)(*(MacAddr+0)) << 16 |
 146                                (u32)(*(MacAddr+1)) << 24 |
 147                                (u32)usConfig;
 148
 149                        write_nic_dword(dev, WCAMI, TargetContent);
 150                        write_nic_dword(dev, RWCAM, TargetCommand);
 151                } else if (i == 1) {
 152                        TargetContent = (u32)(*(MacAddr+2)) |
 153                                (u32)(*(MacAddr+3)) <<  8 |
 154                                (u32)(*(MacAddr+4)) << 16 |
 155                                (u32)(*(MacAddr+5)) << 24;
 156                        write_nic_dword(dev, WCAMI, TargetContent);
 157                        write_nic_dword(dev, RWCAM, TargetCommand);
 158                } else {
 159                        if (KeyContent != NULL) {
 160                                write_nic_dword(dev, WCAMI,
 161                                                (u32)(*(KeyContent+i-2)));
 162                                write_nic_dword(dev, RWCAM, TargetCommand);
 163                                udelay(100);
 164                        }
 165                }
 166        }
 167        RT_TRACE(COMP_SEC, "=========>after set key, usconfig:%x\n", usConfig);
 168}
 169
 170void CAM_read_entry(struct net_device *dev, u32 iIndex)
 171{
 172        u32 target_command = 0;
 173        u32 target_content = 0;
 174        u8 entry_i = 0;
 175        u32 ulStatus;
 176        s32 i = 100;
 177
 178        for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
 179                target_command = entry_i+CAM_CONTENT_COUNT*iIndex;
 180                target_command = target_command | BIT31;
 181
 182                while ((i--) >= 0) {
 183                        ulStatus = read_nic_dword(dev, RWCAM);
 184                        if (ulStatus & BIT31)
 185                                continue;
 186                        else
 187                                break;
 188                }
 189                write_nic_dword(dev, RWCAM, target_command);
 190                RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A0: %x\n",
 191                         target_command);
 192                target_content = read_nic_dword(dev, RCAMO);
 193                RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A8: %x\n",
 194                         target_content);
 195        }
 196        printk(KERN_INFO "\n");
 197}
 198
 199void CamRestoreAllEntry(struct net_device *dev)
 200{
 201        u8 EntryId = 0;
 202        struct r8192_priv *priv = rtllib_priv(dev);
 203        u8 *MacAddr = priv->rtllib->current_network.bssid;
 204
 205        static u8       CAM_CONST_ADDR[4][6] = {
 206                {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
 207                {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
 208                {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
 209                {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
 210        };
 211        static u8       CAM_CONST_BROAD[] = {
 212                0xff, 0xff, 0xff, 0xff, 0xff, 0xff
 213        };
 214
 215        RT_TRACE(COMP_SEC, "CamRestoreAllEntry:\n");
 216
 217
 218        if ((priv->rtllib->pairwise_key_type == KEY_TYPE_WEP40) ||
 219            (priv->rtllib->pairwise_key_type == KEY_TYPE_WEP104)) {
 220
 221                for (EntryId = 0; EntryId < 4; EntryId++) {
 222                        MacAddr = CAM_CONST_ADDR[EntryId];
 223                        if (priv->rtllib->swcamtable[EntryId].bused) {
 224                                setKey(dev, EntryId , EntryId,
 225                                       priv->rtllib->pairwise_key_type, MacAddr,
 226                                       0, (u32 *)(&priv->rtllib->swcamtable
 227                                      [EntryId].key_buf[0]));
 228                        }
 229                }
 230
 231        } else if (priv->rtllib->pairwise_key_type == KEY_TYPE_TKIP) {
 232                if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
 233                        setKey(dev, 4, 0, priv->rtllib->pairwise_key_type,
 234                               (u8 *)dev->dev_addr, 0,
 235                               (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0]));
 236                } else {
 237                        setKey(dev, 4, 0, priv->rtllib->pairwise_key_type,
 238                               MacAddr, 0,
 239                               (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0]));
 240                }
 241
 242        } else if (priv->rtllib->pairwise_key_type == KEY_TYPE_CCMP) {
 243                if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
 244                        setKey(dev, 4, 0,
 245                               priv->rtllib->pairwise_key_type,
 246                               (u8 *)dev->dev_addr, 0,
 247                               (u32 *)(&priv->rtllib->swcamtable[4].
 248                               key_buf[0]));
 249                } else {
 250                        setKey(dev, 4, 0,
 251                               priv->rtllib->pairwise_key_type, MacAddr,
 252                               0, (u32 *)(&priv->rtllib->swcamtable[4].
 253                               key_buf[0]));
 254                        }
 255        }
 256
 257        if (priv->rtllib->group_key_type == KEY_TYPE_TKIP) {
 258                MacAddr = CAM_CONST_BROAD;
 259                for (EntryId = 1; EntryId < 4; EntryId++) {
 260                        if (priv->rtllib->swcamtable[EntryId].bused) {
 261                                setKey(dev, EntryId, EntryId,
 262                                        priv->rtllib->group_key_type,
 263                                        MacAddr, 0,
 264                                        (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0])
 265                                     );
 266                        }
 267                }
 268                if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
 269                        if (priv->rtllib->swcamtable[0].bused) {
 270                                setKey(dev, 0, 0,
 271                                       priv->rtllib->group_key_type,
 272                                       CAM_CONST_ADDR[0], 0,
 273                                       (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0])
 274                                     );
 275                        } else {
 276                                RT_TRACE(COMP_ERR, "===>%s():ERR!! ADHOC TKIP "
 277                                         ",but 0 entry is have no data\n",
 278                                         __func__);
 279                                return;
 280                        }
 281                }
 282        } else if (priv->rtllib->group_key_type == KEY_TYPE_CCMP) {
 283                MacAddr = CAM_CONST_BROAD;
 284                for (EntryId = 1; EntryId < 4; EntryId++) {
 285                        if (priv->rtllib->swcamtable[EntryId].bused) {
 286                                setKey(dev, EntryId , EntryId,
 287                                       priv->rtllib->group_key_type,
 288                                       MacAddr, 0,
 289                                       (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0]));
 290                        }
 291                }
 292
 293                if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
 294                        if (priv->rtllib->swcamtable[0].bused) {
 295                                setKey(dev, 0 , 0,
 296                                        priv->rtllib->group_key_type,
 297                                        CAM_CONST_ADDR[0], 0,
 298                                        (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0]));
 299                        } else {
 300                                RT_TRACE(COMP_ERR, "===>%s():ERR!! ADHOC CCMP ,"
 301                                         "but 0 entry is have no data\n",
 302                                         __func__);
 303                                return;
 304                        }
 305                }
 306        }
 307}
 308