When rtw_enable is called, power may have been removed and re-applied,

so invalidate the WEP key registers to force us to write the keys
back to the hardware.

Revamp key handling: use the hardware WEP engine for 40-bit and
104-bit keys, only; use software WEP for all other key lengths.
Set the hardware key length to the length of the default Tx key,
or if there is no default Tx key, use the length of the longest
WEP key.
This commit is contained in:
dyoung 2006-02-19 08:10:06 +00:00
parent e1a75e8134
commit a43fc3c20c
1 changed files with 24 additions and 19 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: rtw.c,v 1.65 2006/02/04 23:22:27 dyoung Exp $ */ /* $NetBSD: rtw.c,v 1.66 2006/02/19 08:10:06 dyoung Exp $ */
/*- /*-
* Copyright (c) 2004, 2005 David Young. All rights reserved. * Copyright (c) 2004, 2005 David Young. All rights reserved.
* *
@ -34,7 +34,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: rtw.c,v 1.65 2006/02/04 23:22:27 dyoung Exp $"); __KERNEL_RCSID(0, "$NetBSD: rtw.c,v 1.66 2006/02/19 08:10:06 dyoung Exp $");
#include "bpfilter.h" #include "bpfilter.h"
@ -648,7 +648,7 @@ static void
rtw_wep_setkeys(struct rtw_softc *sc, struct ieee80211_key *wk, int txkey) rtw_wep_setkeys(struct rtw_softc *sc, struct ieee80211_key *wk, int txkey)
{ {
uint8_t psr, scr; uint8_t psr, scr;
int i, tx_key_len; int i, keylen;
struct rtw_regs *regs; struct rtw_regs *regs;
union rtw_keys *rk; union rtw_keys *rk;
@ -672,26 +672,23 @@ rtw_wep_setkeys(struct rtw_softc *sc, struct ieee80211_key *wk, int txkey)
if ((sc->sc_ic.ic_flags & IEEE80211_F_PRIVACY) == 0) if ((sc->sc_ic.ic_flags & IEEE80211_F_PRIVACY) == 0)
goto out; goto out;
if (!rtw_key_hwsupp(sc->sc_flags, &wk[txkey])) for (keylen = i = 0; i < IEEE80211_WEP_NKID; i++) {
goto out; if (!rtw_key_hwsupp(sc->sc_flags, &wk[i]))
continue;
tx_key_len = wk[txkey].wk_keylen; if (i == txkey) {
keylen = wk[i].wk_keylen;
switch (tx_key_len) {
case 5:
scr |= RTW_SCR_KM_WEP40;
break; break;
case 13: }
scr |= RTW_SCR_KM_WEP104; keylen = MAX(keylen, wk[i].wk_keylen);
break;
default:
goto out;
} }
scr |= RTW_SCR_RXSECON; if (keylen == 5)
scr |= RTW_SCR_KM_WEP40 | RTW_SCR_RXSECON;
else if (keylen == 13)
scr |= RTW_SCR_KM_WEP104 | RTW_SCR_RXSECON;
for (i = 0; i < IEEE80211_WEP_NKID; i++) { for (i = 0; i < IEEE80211_WEP_NKID; i++) {
if (wk[i].wk_keylen != tx_key_len || if (wk[i].wk_keylen != keylen ||
wk[i].wk_cipher->ic_cipher != IEEE80211_CIPHER_WEP) wk[i].wk_cipher->ic_cipher != IEEE80211_CIPHER_WEP)
continue; continue;
/* h/w will decrypt, s/w still strips headers */ /* h/w will decrypt, s/w still strips headers */
@ -2515,6 +2512,10 @@ rtw_enable(struct rtw_softc *sc)
return (EIO); return (EIO);
} }
sc->sc_flags |= RTW_F_ENABLED; sc->sc_flags |= RTW_F_ENABLED;
/* Power may have been removed, and WEP keys thus
* reset.
*/
sc->sc_flags &= ~RTW_F_DK_VALID;
} }
return (0); return (0);
} }
@ -3321,6 +3322,10 @@ rtw_start(struct ifnet *ifp)
if (m0->m_pkthdr.len > ic->ic_rtsthreshold) if (m0->m_pkthdr.len > ic->ic_rtsthreshold)
ctl0 |= RTW_TXCTL0_RTSEN; ctl0 |= RTW_TXCTL0_RTSEN;
/* XXX Sometimes writes a bogus keyid; h/w doesn't
* seem to care, since we don't activate h/w Tx
* encryption.
*/
if (k != NULL) { if (k != NULL) {
ctl0 |= LSHIFT(k->wk_keyix, RTW_TXCTL0_KEYID_MASK) & ctl0 |= LSHIFT(k->wk_keyix, RTW_TXCTL0_KEYID_MASK) &
RTW_TXCTL0_KEYID_MASK; RTW_TXCTL0_KEYID_MASK;