ar5211_keycache.c revision 204644
174462Salfred/* 274462Salfred * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 374462Salfred * Copyright (c) 2002-2006 Atheros Communications, Inc. 474462Salfred * 574462Salfred * Permission to use, copy, modify, and/or distribute this software for any 674462Salfred * purpose with or without fee is hereby granted, provided that the above 774462Salfred * copyright notice and this permission notice appear in all copies. 874462Salfred * 974462Salfred * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1074462Salfred * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1174462Salfred * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1274462Salfred * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1374462Salfred * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1474462Salfred * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1574462Salfred * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1674462Salfred * 1774462Salfred * $FreeBSD: head/sys/dev/ath/ath_hal/ar5211/ar5211_keycache.c 204644 2010-03-03 17:32:32Z rpaulo $ 1874462Salfred */ 1974462Salfred#include "opt_ah.h" 2074462Salfred 2174462Salfred#include "ah.h" 2274462Salfred#include "ah_internal.h" 2374462Salfred 2474462Salfred#include "ar5211/ar5211.h" 2574462Salfred#include "ar5211/ar5211reg.h" 2674462Salfred 2774462Salfred/* 2874462Salfred * Chips-specific key cache routines. 2974462Salfred */ 3074462Salfred 3174462Salfred#define AR_KEYTABLE_SIZE 128 3274462Salfred#define KEY_XOR 0xaa 3374462Salfred 3474462Salfred/* 3574462Salfred * Return the size of the hardware key cache. 36136581Sobrien */ 37136581Sobrienuint32_t 3874462Salfredar5211GetKeyCacheSize(struct ath_hal *ah) 3974462Salfred{ 4092990Sobrien return AR_KEYTABLE_SIZE; 4192990Sobrien} 4274462Salfred 4374462Salfred/* 4474462Salfred * Return true if the specific key cache entry is valid. 4574462Salfred */ 4674462SalfredHAL_BOOL 4774462Salfredar5211IsKeyCacheEntryValid(struct ath_hal *ah, uint16_t entry) 4875094Siedowse{ 4974462Salfred if (entry < AR_KEYTABLE_SIZE) { 5074462Salfred uint32_t val = OS_REG_READ(ah, AR_KEYTABLE_MAC1(entry)); 5174462Salfred if (val & AR_KEYTABLE_VALID) 5274462Salfred return AH_TRUE; 5374462Salfred } 5474462Salfred return AH_FALSE; 5574462Salfred} 5674462Salfred 5774462Salfred/* 5874462Salfred * Clear the specified key cache entry 5974462Salfred */ 6074462SalfredHAL_BOOL 6174462Salfredar5211ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry) 6274462Salfred{ 6374462Salfred if (entry < AR_KEYTABLE_SIZE) { 64156090Sdeischen OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0); 6574462Salfred OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0); 6692905Sobrien OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0); 6774462Salfred OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0); 6874462Salfred OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0); 6974462Salfred OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), 0); 7074462Salfred OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0); 7174462Salfred OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0); 7274462Salfred return AH_TRUE; 7374462Salfred } 7474462Salfred return AH_FALSE; 7574462Salfred} 7674462Salfred 7774462Salfred/* 7874462Salfred * Sets the mac part of the specified key cache entry and mark it valid. 7992905Sobrien */ 8074462SalfredHAL_BOOL 8174462Salfredar5211SetKeyCacheEntryMac(struct ath_hal *ah, uint16_t entry, const uint8_t *mac) 8274462Salfred{ 8374462Salfred uint32_t macHi, macLo; 8474462Salfred 8574462Salfred if (entry >= AR_KEYTABLE_SIZE) { 8674462Salfred HALDEBUG(ah, HAL_DEBUG_ANY, "%s: entry %u out of range\n", 8774462Salfred __func__, entry); 8874462Salfred return AH_FALSE; 8974462Salfred } 9074462Salfred 9174462Salfred /* 9274462Salfred * Set MAC address -- shifted right by 1. MacLo is 9374462Salfred * the 4 MSBs, and MacHi is the 2 LSBs. 9474462Salfred */ 9574462Salfred if (mac != AH_NULL) { 9674462Salfred macHi = (mac[5] << 8) | mac[4]; 9774462Salfred macLo = (mac[3] << 24)| (mac[2] << 16) 9874462Salfred | (mac[1] << 8) | mac[0]; 9974462Salfred macLo >>= 1; 10074462Salfred macLo |= (macHi & 1) << 31; /* carry */ 10174462Salfred macHi >>= 1; 10274462Salfred } else { 10374462Salfred macLo = macHi = 0; 10474462Salfred } 10574462Salfred 10674462Salfred OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo); 10774462Salfred OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | AR_KEYTABLE_VALID); 10874462Salfred return AH_TRUE; 10974462Salfred} 11074462Salfred 11174462Salfred/* 11274462Salfred * Sets the contents of the specified key cache entry. 11374462Salfred */ 11474462SalfredHAL_BOOL 11574462Salfredar5211SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry, 11674462Salfred const HAL_KEYVAL *k, const uint8_t *mac, 11774462Salfred int xorKey) 11874462Salfred{ 11974462Salfred uint32_t key0, key1, key2, key3, key4; 12074462Salfred uint32_t keyType; 12174462Salfred uint32_t xorMask= xorKey ? 12274462Salfred (KEY_XOR << 24 | KEY_XOR << 16 | KEY_XOR << 8 | KEY_XOR) : 0; 12374462Salfred 12474462Salfred if (entry >= AR_KEYTABLE_SIZE) { 12574462Salfred HALDEBUG(ah, HAL_DEBUG_ANY, "%s: entry %u out of range\n", 12674462Salfred __func__, entry); 12774462Salfred return AH_FALSE; 12874462Salfred } 12974462Salfred switch (k->kv_type) { 13074462Salfred case HAL_CIPHER_AES_OCB: 13174462Salfred keyType = AR_KEYTABLE_TYPE_AES; 13274462Salfred break; 13374462Salfred case HAL_CIPHER_WEP: 13474462Salfred if (k->kv_len < 40 / NBBY) { 13574462Salfred HALDEBUG(ah, HAL_DEBUG_ANY, 13674462Salfred "%s: WEP key length %u too small\n", 13774462Salfred __func__, k->kv_len); 13874462Salfred return AH_FALSE; 13974462Salfred } 14074462Salfred if (k->kv_len <= 40 / NBBY) 14174462Salfred keyType = AR_KEYTABLE_TYPE_40; 14274462Salfred else if (k->kv_len <= 104 / NBBY) 14374462Salfred keyType = AR_KEYTABLE_TYPE_104; 14474462Salfred else 14574462Salfred keyType = AR_KEYTABLE_TYPE_128; 14674462Salfred break; 14774462Salfred case HAL_CIPHER_CLR: 14874462Salfred keyType = AR_KEYTABLE_TYPE_CLR; 14974462Salfred break; 15092905Sobrien default: 15174462Salfred HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cipher %u not supported\n", 15274462Salfred __func__, k->kv_type); 15374462Salfred return AH_FALSE; 15474462Salfred } 15574462Salfred 15674462Salfred key0 = LE_READ_4(k->kv_val+0) ^ xorMask; 15774462Salfred key1 = (LE_READ_2(k->kv_val+4) ^ xorMask) & 0xffff; 15874462Salfred key2 = LE_READ_4(k->kv_val+6) ^ xorMask; 15974462Salfred key3 = (LE_READ_2(k->kv_val+10) ^ xorMask) & 0xffff; 16074462Salfred key4 = LE_READ_4(k->kv_val+12) ^ xorMask; 16174462Salfred if (k->kv_len <= 104 / NBBY) 16274462Salfred key4 &= 0xff; 16374462Salfred 16474462Salfred 16574462Salfred /* 16674462Salfred * Note: WEP key cache hardware requires that each double-word 16774462Salfred * pair be written in even/odd order (since the destination is 16874462Salfred * a 64-bit register). Don't reorder these writes w/o 16974462Salfred * understanding this! 17074462Salfred */ 17174462Salfred OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); 17274462Salfred OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); 17374462Salfred OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); 17474462Salfred OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); 17574462Salfred OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); 17674462Salfred OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); 17774462Salfred return ar5211SetKeyCacheEntryMac(ah, entry, mac); 17874462Salfred} 17974462Salfred