1 /******************************************************************************
3 * Copyright(c) 2009-2010 Realtek Corporation.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
18 * The full GNU General Public License is included in this distribution in the
19 * file called LICENSE.
21 * Contact Information:
22 * wlanfae <wlanfae@realtek.com>
23 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
24 * Hsinchu 300, Taiwan.
26 *****************************************************************************/
31 void rtl_cam_reset_sec_info(struct ieee80211_hw
*hw
)
33 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
35 rtlpriv
->sec
.use_defaultkey
= false;
36 rtlpriv
->sec
.pairwise_enc_algorithm
= NO_ENCRYPTION
;
37 rtlpriv
->sec
.group_enc_algorithm
= NO_ENCRYPTION
;
38 memset(rtlpriv
->sec
.key_buf
, 0, KEY_BUF_SIZE
* MAX_KEY_LEN
);
39 memset(rtlpriv
->sec
.key_len
, 0, KEY_BUF_SIZE
);
40 rtlpriv
->sec
.pairwise_key
= NULL
;
43 static void rtl_cam_program_entry(struct ieee80211_hw
*hw
, u32 entry_no
,
44 u8
*mac_addr
, u8
*key_cont_128
, u16 us_config
)
46 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
49 u32 target_content
= 0;
52 RT_TRACE(rtlpriv
, COMP_SEC
, DBG_DMESG
,
53 ("key_cont_128:\n %x:%x:%x:%x:%x:%x\n",
54 key_cont_128
[0], key_cont_128
[1],
55 key_cont_128
[2], key_cont_128
[3],
56 key_cont_128
[4], key_cont_128
[5]));
58 for (entry_i
= 0; entry_i
< CAM_CONTENT_COUNT
; entry_i
++) {
59 target_command
= entry_i
+ CAM_CONTENT_COUNT
* entry_no
;
60 target_command
= target_command
| BIT(31) | BIT(16);
63 target_content
= (u32
) (*(mac_addr
+ 0)) << 16 |
64 (u32
) (*(mac_addr
+ 1)) << 24 | (u32
) us_config
;
66 rtl_write_dword(rtlpriv
, rtlpriv
->cfg
->maps
[WCAMI
],
68 rtl_write_dword(rtlpriv
, rtlpriv
->cfg
->maps
[RWCAM
],
71 RT_TRACE(rtlpriv
, COMP_SEC
, DBG_DMESG
,
72 ("rtl_cam_program_entry(): "
74 rtlpriv
->cfg
->maps
[WCAMI
], target_content
));
75 RT_TRACE(rtlpriv
, COMP_SEC
, DBG_DMESG
,
76 ("The Key ID is %d\n", entry_no
));
77 RT_TRACE(rtlpriv
, COMP_SEC
, DBG_DMESG
,
78 ("rtl_cam_program_entry(): "
80 rtlpriv
->cfg
->maps
[RWCAM
], target_command
));
82 } else if (entry_i
== 1) {
84 target_content
= (u32
) (*(mac_addr
+ 5)) << 24 |
85 (u32
) (*(mac_addr
+ 4)) << 16 |
86 (u32
) (*(mac_addr
+ 3)) << 8 |
87 (u32
) (*(mac_addr
+ 2));
89 rtl_write_dword(rtlpriv
, rtlpriv
->cfg
->maps
[WCAMI
],
91 rtl_write_dword(rtlpriv
, rtlpriv
->cfg
->maps
[RWCAM
],
94 RT_TRACE(rtlpriv
, COMP_SEC
, DBG_DMESG
,
95 ("rtl_cam_program_entry(): WRITE A4: %x\n",
97 RT_TRACE(rtlpriv
, COMP_SEC
, DBG_DMESG
,
98 ("rtl_cam_program_entry(): WRITE A0: %x\n",
104 (u32
) (*(key_cont_128
+ (entry_i
* 4 - 8) + 3)) <<
105 24 | (u32
) (*(key_cont_128
+ (entry_i
* 4 - 8) + 2))
107 (u32
) (*(key_cont_128
+ (entry_i
* 4 - 8) + 1)) << 8
108 | (u32
) (*(key_cont_128
+ (entry_i
* 4 - 8) + 0));
110 rtl_write_dword(rtlpriv
, rtlpriv
->cfg
->maps
[WCAMI
],
112 rtl_write_dword(rtlpriv
, rtlpriv
->cfg
->maps
[RWCAM
],
116 RT_TRACE(rtlpriv
, COMP_SEC
, DBG_DMESG
,
117 ("rtl_cam_program_entry(): WRITE A4: %x\n",
119 RT_TRACE(rtlpriv
, COMP_SEC
, DBG_DMESG
,
120 ("rtl_cam_program_entry(): WRITE A0: %x\n",
125 RT_TRACE(rtlpriv
, COMP_SEC
, DBG_DMESG
,
126 ("after set key, usconfig:%x\n", us_config
));
129 u8
rtl_cam_add_one_entry(struct ieee80211_hw
*hw
, u8
*mac_addr
,
130 u32 ul_key_id
, u32 ul_entry_idx
, u32 ul_enc_alg
,
131 u32 ul_default_key
, u8
*key_content
)
134 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
136 RT_TRACE(rtlpriv
, COMP_SEC
, DBG_DMESG
,
137 ("EntryNo:%x, ulKeyId=%x, ulEncAlg=%x, "
138 "ulUseDK=%x MacAddr" MAC_FMT
"\n",
139 ul_entry_idx
, ul_key_id
, ul_enc_alg
,
140 ul_default_key
, MAC_ARG(mac_addr
)));
142 if (ul_key_id
== TOTAL_CAM_ENTRY
) {
143 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_WARNING
,
144 ("<=== ulKeyId exceed!\n"));
148 if (ul_default_key
== 1) {
149 us_config
= CFG_VALID
| ((u16
) (ul_enc_alg
) << 2);
151 us_config
= CFG_VALID
| ((ul_enc_alg
) << 2) | ul_key_id
;
154 rtl_cam_program_entry(hw
, ul_entry_idx
, mac_addr
,
155 (u8
*) key_content
, us_config
);
157 RT_TRACE(rtlpriv
, COMP_SEC
, DBG_DMESG
, ("<===\n"));
162 EXPORT_SYMBOL(rtl_cam_add_one_entry
);
164 int rtl_cam_delete_one_entry(struct ieee80211_hw
*hw
,
165 u8
*mac_addr
, u32 ul_key_id
)
168 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
170 RT_TRACE(rtlpriv
, COMP_SEC
, DBG_DMESG
, ("key_idx:%d\n", ul_key_id
));
172 ul_command
= ul_key_id
* CAM_CONTENT_COUNT
;
173 ul_command
= ul_command
| BIT(31) | BIT(16);
175 rtl_write_dword(rtlpriv
, rtlpriv
->cfg
->maps
[WCAMI
], 0);
176 rtl_write_dword(rtlpriv
, rtlpriv
->cfg
->maps
[RWCAM
], ul_command
);
178 RT_TRACE(rtlpriv
, COMP_SEC
, DBG_DMESG
,
179 ("rtl_cam_delete_one_entry(): WRITE A4: %x\n", 0));
180 RT_TRACE(rtlpriv
, COMP_SEC
, DBG_DMESG
,
181 ("rtl_cam_delete_one_entry(): WRITE A0: %x\n", ul_command
));
186 EXPORT_SYMBOL(rtl_cam_delete_one_entry
);
188 void rtl_cam_reset_all_entry(struct ieee80211_hw
*hw
)
191 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
193 ul_command
= BIT(31) | BIT(30);
194 rtl_write_dword(rtlpriv
, rtlpriv
->cfg
->maps
[RWCAM
], ul_command
);
196 EXPORT_SYMBOL(rtl_cam_reset_all_entry
);
198 void rtl_cam_mark_invalid(struct ieee80211_hw
*hw
, u8 uc_index
)
200 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
204 u32 ul_enc_algo
= rtlpriv
->cfg
->maps
[SEC_CAM_AES
];
206 switch (rtlpriv
->sec
.pairwise_enc_algorithm
) {
207 case WEP40_ENCRYPTION
:
208 ul_enc_algo
= rtlpriv
->cfg
->maps
[SEC_CAM_WEP40
];
210 case WEP104_ENCRYPTION
:
211 ul_enc_algo
= rtlpriv
->cfg
->maps
[SEC_CAM_WEP104
];
213 case TKIP_ENCRYPTION
:
214 ul_enc_algo
= rtlpriv
->cfg
->maps
[SEC_CAM_TKIP
];
216 case AESCCMP_ENCRYPTION
:
217 ul_enc_algo
= rtlpriv
->cfg
->maps
[SEC_CAM_AES
];
220 ul_enc_algo
= rtlpriv
->cfg
->maps
[SEC_CAM_AES
];
223 ul_content
= (uc_index
& 3) | ((u16
) (ul_enc_algo
) << 2);
225 ul_content
|= BIT(15);
226 ul_command
= CAM_CONTENT_COUNT
* uc_index
;
227 ul_command
= ul_command
| BIT(31) | BIT(16);
229 rtl_write_dword(rtlpriv
, rtlpriv
->cfg
->maps
[WCAMI
], ul_content
);
230 rtl_write_dword(rtlpriv
, rtlpriv
->cfg
->maps
[RWCAM
], ul_command
);
232 RT_TRACE(rtlpriv
, COMP_SEC
, DBG_DMESG
,
233 ("rtl_cam_mark_invalid(): WRITE A4: %x\n", ul_content
));
234 RT_TRACE(rtlpriv
, COMP_SEC
, DBG_DMESG
,
235 ("rtl_cam_mark_invalid(): WRITE A0: %x\n", ul_command
));
237 EXPORT_SYMBOL(rtl_cam_mark_invalid
);
239 void rtl_cam_empty_entry(struct ieee80211_hw
*hw
, u8 uc_index
)
241 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
245 u32 ul_encalgo
= rtlpriv
->cfg
->maps
[SEC_CAM_AES
];
248 switch (rtlpriv
->sec
.pairwise_enc_algorithm
) {
249 case WEP40_ENCRYPTION
:
250 ul_encalgo
= rtlpriv
->cfg
->maps
[SEC_CAM_WEP40
];
252 case WEP104_ENCRYPTION
:
253 ul_encalgo
= rtlpriv
->cfg
->maps
[SEC_CAM_WEP104
];
255 case TKIP_ENCRYPTION
:
256 ul_encalgo
= rtlpriv
->cfg
->maps
[SEC_CAM_TKIP
];
258 case AESCCMP_ENCRYPTION
:
259 ul_encalgo
= rtlpriv
->cfg
->maps
[SEC_CAM_AES
];
262 ul_encalgo
= rtlpriv
->cfg
->maps
[SEC_CAM_AES
];
265 for (entry_i
= 0; entry_i
< CAM_CONTENT_COUNT
; entry_i
++) {
269 (uc_index
& 0x03) | ((u16
) (ul_encalgo
) << 2);
270 ul_content
|= BIT(15);
276 ul_command
= CAM_CONTENT_COUNT
* uc_index
+ entry_i
;
277 ul_command
= ul_command
| BIT(31) | BIT(16);
279 rtl_write_dword(rtlpriv
, rtlpriv
->cfg
->maps
[WCAMI
], ul_content
);
280 rtl_write_dword(rtlpriv
, rtlpriv
->cfg
->maps
[RWCAM
], ul_command
);
282 RT_TRACE(rtlpriv
, COMP_SEC
, DBG_LOUD
,
283 ("rtl_cam_empty_entry(): WRITE A4: %x\n",
285 RT_TRACE(rtlpriv
, COMP_SEC
, DBG_LOUD
,
286 ("rtl_cam_empty_entry(): WRITE A0: %x\n",
291 EXPORT_SYMBOL(rtl_cam_empty_entry
);