1*6e778a7eSPedro F. Giffuni /*-
2*6e778a7eSPedro F. Giffuni * SPDX-License-Identifier: ISC
3*6e778a7eSPedro F. Giffuni *
414779705SSam Leffler * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
514779705SSam Leffler * Copyright (c) 2002-2004 Atheros Communications, Inc.
614779705SSam Leffler *
714779705SSam Leffler * Permission to use, copy, modify, and/or distribute this software for any
814779705SSam Leffler * purpose with or without fee is hereby granted, provided that the above
914779705SSam Leffler * copyright notice and this permission notice appear in all copies.
1014779705SSam Leffler *
1114779705SSam Leffler * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1214779705SSam Leffler * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1314779705SSam Leffler * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1414779705SSam Leffler * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1514779705SSam Leffler * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1614779705SSam Leffler * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1714779705SSam Leffler * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1814779705SSam Leffler */
1914779705SSam Leffler #include "opt_ah.h"
2014779705SSam Leffler
2114779705SSam Leffler #include "ah.h"
2214779705SSam Leffler #include "ah_internal.h"
2314779705SSam Leffler
2414779705SSam Leffler #include "ar5210/ar5210.h"
2514779705SSam Leffler #include "ar5210/ar5210reg.h"
2614779705SSam Leffler
2714779705SSam Leffler #define AR_KEYTABLE_SIZE 64
2814779705SSam Leffler #define KEY_XOR 0xaa
2914779705SSam Leffler
3014779705SSam Leffler /*
3114779705SSam Leffler * Return the size of the hardware key cache.
3214779705SSam Leffler */
3314779705SSam Leffler u_int
ar5210GetKeyCacheSize(struct ath_hal * ah)3414779705SSam Leffler ar5210GetKeyCacheSize(struct ath_hal *ah)
3514779705SSam Leffler {
3614779705SSam Leffler return AR_KEYTABLE_SIZE;
3714779705SSam Leffler }
3814779705SSam Leffler
3914779705SSam Leffler /*
4014779705SSam Leffler * Return the size of the hardware key cache.
4114779705SSam Leffler */
4214779705SSam Leffler HAL_BOOL
ar5210IsKeyCacheEntryValid(struct ath_hal * ah,uint16_t entry)4314779705SSam Leffler ar5210IsKeyCacheEntryValid(struct ath_hal *ah, uint16_t entry)
4414779705SSam Leffler {
4514779705SSam Leffler if (entry < AR_KEYTABLE_SIZE) {
4614779705SSam Leffler uint32_t val = OS_REG_READ(ah, AR_KEYTABLE_MAC1(entry));
4714779705SSam Leffler if (val & AR_KEYTABLE_VALID)
4814779705SSam Leffler return AH_TRUE;
4914779705SSam Leffler }
5014779705SSam Leffler return AH_FALSE;
5114779705SSam Leffler }
5214779705SSam Leffler
5314779705SSam Leffler /*
5414779705SSam Leffler * Clear the specified key cache entry.
5514779705SSam Leffler */
5614779705SSam Leffler HAL_BOOL
ar5210ResetKeyCacheEntry(struct ath_hal * ah,uint16_t entry)5714779705SSam Leffler ar5210ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry)
5814779705SSam Leffler {
5914779705SSam Leffler if (entry < AR_KEYTABLE_SIZE) {
6014779705SSam Leffler OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
6114779705SSam Leffler OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
6214779705SSam Leffler OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
6314779705SSam Leffler OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
6414779705SSam Leffler OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
6514779705SSam Leffler OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), 0);
6614779705SSam Leffler OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
6714779705SSam Leffler OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
6814779705SSam Leffler return AH_TRUE;
6914779705SSam Leffler }
7014779705SSam Leffler return AH_FALSE;
7114779705SSam Leffler }
7214779705SSam Leffler
7314779705SSam Leffler /*
7414779705SSam Leffler * Sets the mac part of the specified key cache entry and mark it valid.
7514779705SSam Leffler */
7614779705SSam Leffler HAL_BOOL
ar5210SetKeyCacheEntryMac(struct ath_hal * ah,uint16_t entry,const uint8_t * mac)7714779705SSam Leffler ar5210SetKeyCacheEntryMac(struct ath_hal *ah, uint16_t entry, const uint8_t *mac)
7814779705SSam Leffler {
7914779705SSam Leffler uint32_t macHi, macLo;
8014779705SSam Leffler
8114779705SSam Leffler if (entry < AR_KEYTABLE_SIZE) {
8214779705SSam Leffler /*
8314779705SSam Leffler * Set MAC address -- shifted right by 1. MacLo is
8414779705SSam Leffler * the 4 MSBs, and MacHi is the 2 LSBs.
8514779705SSam Leffler */
8614779705SSam Leffler if (mac != AH_NULL) {
8714779705SSam Leffler macHi = (mac[5] << 8) | mac[4];
8814779705SSam Leffler macLo = (mac[3] << 24)| (mac[2] << 16)
8914779705SSam Leffler | (mac[1] << 8) | mac[0];
9014779705SSam Leffler macLo >>= 1;
9114779705SSam Leffler macLo |= (macHi & 1) << 31; /* carry */
9214779705SSam Leffler macHi >>= 1;
9314779705SSam Leffler } else {
9414779705SSam Leffler macLo = macHi = 0;
9514779705SSam Leffler }
9614779705SSam Leffler
9714779705SSam Leffler OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo);
9814779705SSam Leffler OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry),
9914779705SSam Leffler macHi | AR_KEYTABLE_VALID);
10014779705SSam Leffler return AH_TRUE;
10114779705SSam Leffler }
10214779705SSam Leffler return AH_FALSE;
10314779705SSam Leffler }
10414779705SSam Leffler
10514779705SSam Leffler /*
10614779705SSam Leffler * Sets the contents of the specified key cache entry.
10714779705SSam Leffler */
10814779705SSam Leffler HAL_BOOL
ar5210SetKeyCacheEntry(struct ath_hal * ah,uint16_t entry,const HAL_KEYVAL * k,const uint8_t * mac,int xorKey)10914779705SSam Leffler ar5210SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry,
11014779705SSam Leffler const HAL_KEYVAL *k, const uint8_t *mac, int xorKey)
11114779705SSam Leffler {
11214779705SSam Leffler uint32_t key0, key1, key2, key3, key4;
11314779705SSam Leffler uint32_t keyType;
11414779705SSam Leffler uint32_t xorMask= xorKey ?
11514779705SSam Leffler (KEY_XOR << 24 | KEY_XOR << 16 | KEY_XOR << 8 | KEY_XOR) : 0;
11614779705SSam Leffler
11714779705SSam Leffler if (entry >= AR_KEYTABLE_SIZE)
11814779705SSam Leffler return AH_FALSE;
11914779705SSam Leffler if (k->kv_type != HAL_CIPHER_WEP) {
12014779705SSam Leffler HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cipher %u not supported\n",
12114779705SSam Leffler __func__, k->kv_type);
12214779705SSam Leffler return AH_FALSE;
12314779705SSam Leffler }
12414779705SSam Leffler
12514779705SSam Leffler /* NB: only WEP supported */
12614779705SSam Leffler if (k->kv_len < 40 / NBBY)
12714779705SSam Leffler return AH_FALSE;
12814779705SSam Leffler if (k->kv_len <= 40 / NBBY)
12914779705SSam Leffler keyType = AR_KEYTABLE_TYPE_40;
13014779705SSam Leffler else if (k->kv_len <= 104 / NBBY)
13114779705SSam Leffler keyType = AR_KEYTABLE_TYPE_104;
13214779705SSam Leffler else
13314779705SSam Leffler keyType = AR_KEYTABLE_TYPE_128;
13414779705SSam Leffler
13514779705SSam Leffler key0 = LE_READ_4(k->kv_val+0) ^ xorMask;
13614779705SSam Leffler key1 = (LE_READ_2(k->kv_val+4) ^ xorMask) & 0xffff;
13714779705SSam Leffler key2 = LE_READ_4(k->kv_val+6) ^ xorMask;
13814779705SSam Leffler key3 = (LE_READ_2(k->kv_val+10) ^ xorMask) & 0xffff;
13914779705SSam Leffler key4 = LE_READ_4(k->kv_val+12) ^ xorMask;
14014779705SSam Leffler if (k->kv_len <= 104 / NBBY)
14114779705SSam Leffler key4 &= 0xff;
14214779705SSam Leffler
14314779705SSam Leffler /*
14414779705SSam Leffler * Note: WEP key cache hardware requires that each double-word
14514779705SSam Leffler * pair be written in even/odd order (since the destination is
14614779705SSam Leffler * a 64-bit register). Don't reorder these writes w/o
14714779705SSam Leffler * understanding this!
14814779705SSam Leffler */
14914779705SSam Leffler OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
15014779705SSam Leffler OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
15114779705SSam Leffler OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
15214779705SSam Leffler OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
15314779705SSam Leffler OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
15414779705SSam Leffler OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
15514779705SSam Leffler return ar5210SetKeyCacheEntryMac(ah, entry, mac);
15614779705SSam Leffler }
157