ar5210_keycache.c revision 185406
1132718Skan/*
2169699Skan * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
3132718Skan * Copyright (c) 2002-2004 Atheros Communications, Inc.
4132718Skan *
5132718Skan * Permission to use, copy, modify, and/or distribute this software for any
6132718Skan * purpose with or without fee is hereby granted, provided that the above
7132718Skan * copyright notice and this permission notice appear in all copies.
8132718Skan *
9132718Skan * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10169699Skan * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11132718Skan * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12132718Skan * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13132718Skan * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14132718Skan * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15169699Skan * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16132718Skan *
17132718Skan * $Id: ar5210_keycache.c,v 1.4 2008/11/10 04:08:02 sam Exp $
18169699Skan */
19169699Skan#include "opt_ah.h"
20132718Skan
21169699Skan#include "ah.h"
22132718Skan#include "ah_internal.h"
23169699Skan
24132718Skan#include "ar5210/ar5210.h"
25132718Skan#include "ar5210/ar5210reg.h"
26132718Skan
27132718Skan#define	AR_KEYTABLE_SIZE	64
28132718Skan#define	KEY_XOR			0xaa
29132718Skan
30132718Skan/*
31132718Skan * Return the size of the hardware key cache.
32132718Skan */
33132718Skanu_int
34132718Skanar5210GetKeyCacheSize(struct ath_hal *ah)
35132718Skan{
36132718Skan	return AR_KEYTABLE_SIZE;
37132718Skan}
38132718Skan
39132718Skan/*
40132718Skan * Return the size of the hardware key cache.
41132718Skan */
42132718SkanHAL_BOOL
43132718Skanar5210IsKeyCacheEntryValid(struct ath_hal *ah, uint16_t entry)
44132718Skan{
45132718Skan	if (entry < AR_KEYTABLE_SIZE) {
46132718Skan		uint32_t val = OS_REG_READ(ah, AR_KEYTABLE_MAC1(entry));
47132718Skan		if (val & AR_KEYTABLE_VALID)
48132718Skan			return AH_TRUE;
49132718Skan	}
50132718Skan	return AH_FALSE;
51132718Skan}
52132718Skan
53132718Skan/*
54132718Skan * Clear the specified key cache entry.
55132718Skan */
56132718SkanHAL_BOOL
57132718Skanar5210ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry)
58132718Skan{
59132718Skan	if (entry < AR_KEYTABLE_SIZE) {
60169699Skan		OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
61169699Skan		OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
62169699Skan		OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
63169699Skan		OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
64132718Skan		OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
65132718Skan		OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), 0);
66132718Skan		OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
67132718Skan		OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
68132718Skan		return AH_TRUE;
69132718Skan	}
70169699Skan	return AH_FALSE;
71132718Skan}
72132718Skan
73132718Skan/*
74132718Skan * Sets the mac part of the specified key cache entry and mark it valid.
75132718Skan */
76132718SkanHAL_BOOL
77132718Skanar5210SetKeyCacheEntryMac(struct ath_hal *ah, uint16_t entry, const uint8_t *mac)
78132718Skan{
79132718Skan	uint32_t macHi, macLo;
80132718Skan
81132718Skan	if (entry < AR_KEYTABLE_SIZE) {
82132718Skan		/*
83132718Skan		 * Set MAC address -- shifted right by 1.  MacLo is
84132718Skan		 * the 4 MSBs, and MacHi is the 2 LSBs.
85132718Skan		 */
86132718Skan		if (mac != AH_NULL) {
87132718Skan			macHi = (mac[5] << 8) | mac[4];
88132718Skan			macLo = (mac[3] << 24)| (mac[2] << 16)
89132718Skan			      | (mac[1] << 8) | mac[0];
90132718Skan			macLo >>= 1;
91132718Skan			macLo |= (macHi & 1) << 31;	/* carry */
92132718Skan			macHi >>= 1;
93132718Skan		} else {
94132718Skan			macLo = macHi = 0;
95132718Skan		}
96132718Skan
97132718Skan		OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo);
98132718Skan		OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry),
99132718Skan			macHi | AR_KEYTABLE_VALID);
100132718Skan		return AH_TRUE;
101132718Skan	}
102132718Skan	return AH_FALSE;
103132718Skan}
104132718Skan
105132718Skan/*
106132718Skan * Sets the contents of the specified key cache entry.
107132718Skan */
108132718SkanHAL_BOOL
109132718Skanar5210SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry,
110132718Skan                       const HAL_KEYVAL *k, const uint8_t *mac, int xorKey)
111132718Skan{
112132718Skan	uint32_t key0, key1, key2, key3, key4;
113132718Skan	uint32_t keyType;
114132718Skan	uint32_t xorMask= xorKey ?
115132718Skan		(KEY_XOR << 24 | KEY_XOR << 16 | KEY_XOR << 8 | KEY_XOR) : 0;
116132718Skan
117169699Skan	if (entry >= AR_KEYTABLE_SIZE)
118169699Skan		return AH_FALSE;
119132718Skan	if (k->kv_type != HAL_CIPHER_WEP) {
120169699Skan		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cipher %u not supported\n",
121169699Skan		    __func__, k->kv_type);
122169699Skan		return AH_FALSE;
123169699Skan	}
124132718Skan
125132718Skan	/* NB: only WEP supported */
126132718Skan	if (k->kv_len < 40 / NBBY)
127132718Skan		return AH_FALSE;
128169699Skan	if (k->kv_len <= 40 / NBBY)
129169699Skan		keyType = AR_KEYTABLE_TYPE_40;
130169699Skan	else if (k->kv_len <= 104 / NBBY)
131169699Skan		keyType = AR_KEYTABLE_TYPE_104;
132132718Skan	else
133169699Skan		keyType = AR_KEYTABLE_TYPE_128;
134132718Skan
135132718Skan	key0 = LE_READ_4(k->kv_val+0) ^ xorMask;
136169699Skan	key1 = (LE_READ_2(k->kv_val+4) ^ xorMask) & 0xffff;
137169699Skan	key2 = LE_READ_4(k->kv_val+6) ^ xorMask;
138169699Skan	key3 = (LE_READ_2(k->kv_val+10) ^ xorMask) & 0xffff;
139169699Skan	key4 = LE_READ_4(k->kv_val+12) ^ xorMask;
140169699Skan	if (k->kv_len <= 104 / NBBY)
141132718Skan		key4 &= 0xff;
142169699Skan
143132718Skan	/*
144132718Skan	 * Note: WEP key cache hardware requires that each double-word
145132718Skan	 * pair be written in even/odd order (since the destination is
146169699Skan	 * a 64-bit register).  Don't reorder these writes w/o
147132718Skan	 * understanding this!
148132718Skan	 */
149132718Skan	OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
150132718Skan	OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
151132718Skan	OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
152132718Skan	OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
153132718Skan	OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
154132718Skan	OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
155132718Skan	return ar5210SetKeyCacheEntryMac(ah, entry, mac);
156132718Skan}
157132718Skan