rum(4): add support for hardware encryption (WEP, TKIP and CCMP).
This diff includes: * Transmitter Addresses, Keys and TKIP MIC addition to the Security Key Table. * Proper SEC Control Registers initialization and maintenance. * Additional flags and values in TX descriptor, which are required for encryption support. * Error checking in RX path. Tested: * Tested on WUSB54GC, STA (WEP, TKIP, CCMP), HOSTAP (CCMP) and IBSS (CCMP, WPA-None) modes. * rum0: MAC/BBP RT2573 (rev 0x2573a), RF RT2528, STA mode (CCMP+TKIP) Submitted by: <s3erios@gmail.com> Differential Revision: https://reviews.freebsd.org/D3640
This commit is contained in:
parent
0e3b4c60e4
commit
2cb9ef8d38
@ -166,9 +166,13 @@ static void rum_setup_tx_list(struct rum_softc *);
|
||||
static void rum_unsetup_tx_list(struct rum_softc *);
|
||||
static int rum_newstate(struct ieee80211vap *,
|
||||
enum ieee80211_state, int);
|
||||
static uint8_t rum_crypto_mode(struct rum_softc *, u_int, int);
|
||||
static void rum_setup_tx_desc(struct rum_softc *,
|
||||
struct rum_tx_desc *, uint32_t, uint16_t, int,
|
||||
int);
|
||||
struct rum_tx_desc *, struct ieee80211_key *,
|
||||
uint32_t, uint8_t, int, int, int);
|
||||
static uint32_t rum_tx_crypto_flags(struct rum_softc *,
|
||||
struct ieee80211_node *,
|
||||
const struct ieee80211_key *);
|
||||
static int rum_tx_mgt(struct rum_softc *, struct mbuf *,
|
||||
struct ieee80211_node *);
|
||||
static int rum_tx_raw(struct rum_softc *, struct mbuf *,
|
||||
@ -219,6 +223,7 @@ static const char *rum_get_rf(int);
|
||||
static void rum_read_eeprom(struct rum_softc *);
|
||||
static int rum_bbp_wakeup(struct rum_softc *);
|
||||
static int rum_bbp_init(struct rum_softc *);
|
||||
static void rum_clr_shkey_regs(struct rum_softc *);
|
||||
static int rum_init(struct rum_softc *);
|
||||
static void rum_stop(struct rum_softc *);
|
||||
static void rum_load_microcode(struct rum_softc *, const uint8_t *,
|
||||
@ -230,6 +235,24 @@ static int rum_alloc_beacon(struct rum_softc *,
|
||||
static void rum_update_beacon_cb(struct rum_softc *,
|
||||
union sec_param *, uint8_t, uint8_t);
|
||||
static void rum_update_beacon(struct ieee80211vap *, int);
|
||||
static int rum_common_key_set(struct rum_softc *,
|
||||
struct ieee80211_key *, uint16_t);
|
||||
static void rum_group_key_set_cb(struct rum_softc *,
|
||||
union sec_param *, uint8_t, uint8_t);
|
||||
static void rum_group_key_del_cb(struct rum_softc *,
|
||||
union sec_param *, uint8_t, uint8_t);
|
||||
static void rum_pair_key_set_cb(struct rum_softc *,
|
||||
union sec_param *, uint8_t, uint8_t);
|
||||
static void rum_pair_key_del_cb(struct rum_softc *,
|
||||
union sec_param *, uint8_t, uint8_t);
|
||||
static int rum_key_alloc(struct ieee80211vap *,
|
||||
struct ieee80211_key *, ieee80211_keyix *,
|
||||
ieee80211_keyix *);
|
||||
static int rum_key_set(struct ieee80211vap *,
|
||||
const struct ieee80211_key *,
|
||||
const uint8_t mac[IEEE80211_ADDR_LEN]);
|
||||
static int rum_key_delete(struct ieee80211vap *,
|
||||
const struct ieee80211_key *);
|
||||
static int rum_raw_xmit(struct ieee80211_node *, struct mbuf *,
|
||||
const struct ieee80211_bpf_params *);
|
||||
static void rum_scan_start(struct ieee80211com *);
|
||||
@ -258,9 +281,9 @@ static const struct {
|
||||
{ RT2573_MAC_CSR10, 0x00000718 },
|
||||
{ RT2573_MAC_CSR12, 0x00000004 },
|
||||
{ RT2573_MAC_CSR13, 0x00007f00 },
|
||||
{ RT2573_SEC_CSR0, 0x00000000 },
|
||||
{ RT2573_SEC_CSR1, 0x00000000 },
|
||||
{ RT2573_SEC_CSR5, 0x00000000 },
|
||||
{ RT2573_SEC_CSR2, 0x00000000 },
|
||||
{ RT2573_SEC_CSR3, 0x00000000 },
|
||||
{ RT2573_SEC_CSR4, 0x00000000 },
|
||||
{ RT2573_PHY_CSR1, 0x000023b0 },
|
||||
{ RT2573_PHY_CSR5, 0x00040a06 },
|
||||
{ RT2573_PHY_CSR6, 0x00080606 },
|
||||
@ -504,6 +527,12 @@ rum_attach(device_t self)
|
||||
| IEEE80211_C_WPA /* 802.11i */
|
||||
;
|
||||
|
||||
ic->ic_cryptocaps =
|
||||
IEEE80211_CRYPTO_WEP |
|
||||
IEEE80211_CRYPTO_AES_CCM |
|
||||
IEEE80211_CRYPTO_TKIPMIC |
|
||||
IEEE80211_CRYPTO_TKIP;
|
||||
|
||||
bands = 0;
|
||||
setbit(&bands, IEEE80211_MODE_11B);
|
||||
setbit(&bands, IEEE80211_MODE_11G);
|
||||
@ -620,7 +649,11 @@ rum_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
/* override state transition machine */
|
||||
rvp->newstate = vap->iv_newstate;
|
||||
vap->iv_newstate = rum_newstate;
|
||||
vap->iv_key_alloc = rum_key_alloc;
|
||||
vap->iv_key_set = rum_key_set;
|
||||
vap->iv_key_delete = rum_key_delete;
|
||||
vap->iv_update_beacon = rum_update_beacon;
|
||||
vap->iv_max_aid = RT2573_ADDR_MAX;
|
||||
|
||||
usb_callout_init_mtx(&rvp->ratectl_ch, &sc->sc_mtx, 0);
|
||||
TASK_INIT(&rvp->ratectl_task, 0, rum_ratectl_task, rvp);
|
||||
@ -971,6 +1004,21 @@ rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
goto tr_setup;
|
||||
}
|
||||
if ((flags & RT2573_RX_DEC_MASK) != RT2573_RX_DEC_OK) {
|
||||
switch (flags & RT2573_RX_DEC_MASK) {
|
||||
case RT2573_RX_IV_ERROR:
|
||||
DPRINTFN(5, "IV/EIV error\n");
|
||||
break;
|
||||
case RT2573_RX_MIC_ERROR:
|
||||
DPRINTFN(5, "MIC error\n");
|
||||
break;
|
||||
case RT2573_RX_KEY_ERROR:
|
||||
DPRINTFN(5, "Key error\n");
|
||||
break;
|
||||
}
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
goto tr_setup;
|
||||
}
|
||||
|
||||
m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
|
||||
if (m == NULL) {
|
||||
@ -983,6 +1031,13 @@ rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
|
||||
wh = mtod(m, struct ieee80211_frame_min *);
|
||||
|
||||
if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) &&
|
||||
(flags & RT2573_RX_CIP_MASK) !=
|
||||
RT2573_RX_CIP_MODE(RT2573_MODE_NOSEC)) {
|
||||
wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
|
||||
m->m_flags |= M_WEP;
|
||||
}
|
||||
|
||||
/* finalize mbuf */
|
||||
m->m_pkthdr.len = m->m_len = (flags >> 16) & 0xfff;
|
||||
|
||||
@ -1061,22 +1116,45 @@ rum_plcp_signal(int rate)
|
||||
return 0xff; /* XXX unsupported/unknown rate */
|
||||
}
|
||||
|
||||
/*
|
||||
* Map net80211 cipher to RT2573 security mode.
|
||||
*/
|
||||
static uint8_t
|
||||
rum_crypto_mode(struct rum_softc *sc, u_int cipher, int keylen)
|
||||
{
|
||||
switch (cipher) {
|
||||
case IEEE80211_CIPHER_WEP:
|
||||
return (keylen < 8 ? RT2573_MODE_WEP40 : RT2573_MODE_WEP104);
|
||||
case IEEE80211_CIPHER_TKIP:
|
||||
return RT2573_MODE_TKIP;
|
||||
case IEEE80211_CIPHER_AES_CCM:
|
||||
return RT2573_MODE_AES_CCMP;
|
||||
default:
|
||||
device_printf(sc->sc_dev, "unknown cipher %d\n", cipher);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rum_setup_tx_desc(struct rum_softc *sc, struct rum_tx_desc *desc,
|
||||
uint32_t flags, uint16_t xflags, int len, int rate)
|
||||
struct ieee80211_key *k, uint32_t flags, uint8_t xflags, int hdrlen,
|
||||
int len, int rate)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
uint16_t plcp_length;
|
||||
int remainder;
|
||||
|
||||
desc->flags = htole32(flags);
|
||||
desc->flags |= htole32(RT2573_TX_VALID);
|
||||
desc->flags |= htole32(len << 16);
|
||||
flags |= RT2573_TX_VALID;
|
||||
flags |= len << 16;
|
||||
|
||||
desc->xflags = htole16(xflags);
|
||||
if (k != NULL && !(k->wk_flags & IEEE80211_KEY_SWCRYPT)) {
|
||||
const struct ieee80211_cipher *cip = k->wk_cipher;
|
||||
|
||||
desc->wme = htole16(RT2573_QID(0) | RT2573_AIFSN(2) |
|
||||
RT2573_LOGCWMIN(4) | RT2573_LOGCWMAX(10));
|
||||
len += cip->ic_header + cip->ic_trailer + cip->ic_miclen;
|
||||
|
||||
desc->eiv = 0; /* for WEP */
|
||||
cip->ic_setiv(k, (uint8_t *)&desc->iv);
|
||||
}
|
||||
|
||||
/* setup PLCP fields */
|
||||
desc->plcp_signal = rum_plcp_signal(rate);
|
||||
@ -1084,7 +1162,7 @@ rum_setup_tx_desc(struct rum_softc *sc, struct rum_tx_desc *desc,
|
||||
|
||||
len += IEEE80211_CRC_LEN;
|
||||
if (ieee80211_rate2phytype(ic->ic_rt, rate) == IEEE80211_T_OFDM) {
|
||||
desc->flags |= htole32(RT2573_TX_OFDM);
|
||||
flags |= RT2573_TX_OFDM;
|
||||
|
||||
plcp_length = len & 0xfff;
|
||||
desc->plcp_length_hi = plcp_length >> 6;
|
||||
@ -1104,6 +1182,13 @@ rum_setup_tx_desc(struct rum_softc *sc, struct rum_tx_desc *desc,
|
||||
if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
|
||||
desc->plcp_signal |= 0x08;
|
||||
}
|
||||
|
||||
desc->flags = htole32(flags);
|
||||
desc->hdrlen = hdrlen;
|
||||
desc->xflags = xflags;
|
||||
|
||||
desc->wme = htole16(RT2573_QID(0) | RT2573_AIFSN(2) |
|
||||
RT2573_LOGCWMIN(4) | RT2573_LOGCWMAX(10));
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1149,7 +1234,8 @@ rum_sendprot(struct rum_softc *sc,
|
||||
data->m = mprot;
|
||||
data->ni = ieee80211_ref_node(ni);
|
||||
data->rate = protrate;
|
||||
rum_setup_tx_desc(sc, &data->desc, flags, 0, mprot->m_pkthdr.len, protrate);
|
||||
rum_setup_tx_desc(sc, &data->desc, NULL, flags, 0, 0,
|
||||
mprot->m_pkthdr.len, protrate);
|
||||
|
||||
STAILQ_INSERT_TAIL(&sc->tx_q, data, next);
|
||||
usbd_transfer_start(sc->sc_xfer[RUM_BULK_WR]);
|
||||
@ -1157,6 +1243,40 @@ rum_sendprot(struct rum_softc *sc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
rum_tx_crypto_flags(struct rum_softc *sc, struct ieee80211_node *ni,
|
||||
const struct ieee80211_key *k)
|
||||
{
|
||||
struct ieee80211vap *vap = ni->ni_vap;
|
||||
u_int cipher;
|
||||
uint32_t flags = 0;
|
||||
uint8_t mode, pos;
|
||||
|
||||
if (!(k->wk_flags & IEEE80211_KEY_SWCRYPT)) {
|
||||
cipher = k->wk_cipher->ic_cipher;
|
||||
pos = k->wk_keyix;
|
||||
mode = rum_crypto_mode(sc, cipher, k->wk_keylen);
|
||||
if (mode == 0)
|
||||
return 0;
|
||||
|
||||
flags |= RT2573_TX_CIP_MODE(mode);
|
||||
|
||||
/* Do not trust GROUP flag */
|
||||
if (!(k >= &vap->iv_nw_keys[0] &&
|
||||
k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]))
|
||||
flags |= RT2573_TX_KEY_PAIR;
|
||||
else
|
||||
pos += 0 * RT2573_SKEY_MAX; /* vap id */
|
||||
|
||||
flags |= RT2573_TX_KEY_ID(pos);
|
||||
|
||||
if (cipher == IEEE80211_CIPHER_TKIP)
|
||||
flags |= RT2573_TX_TKIPMIC;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static int
|
||||
rum_tx_mgt(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
|
||||
{
|
||||
@ -1165,9 +1285,10 @@ rum_tx_mgt(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
|
||||
struct rum_tx_data *data;
|
||||
struct ieee80211_frame *wh;
|
||||
const struct ieee80211_txparam *tp;
|
||||
struct ieee80211_key *k;
|
||||
struct ieee80211_key *k = NULL;
|
||||
uint32_t flags = 0;
|
||||
uint16_t dur;
|
||||
int hdrlen;
|
||||
|
||||
RUM_LOCK_ASSERT(sc);
|
||||
|
||||
@ -1176,9 +1297,15 @@ rum_tx_mgt(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
|
||||
sc->tx_nfree--;
|
||||
|
||||
wh = mtod(m0, struct ieee80211_frame *);
|
||||
hdrlen = ieee80211_anyhdrsize(wh);
|
||||
|
||||
if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
|
||||
k = ieee80211_crypto_encap(ni, m0);
|
||||
k = ieee80211_crypto_get_txkey(ni, m0);
|
||||
if (k == NULL)
|
||||
return (ENOENT);
|
||||
|
||||
if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) &&
|
||||
!k->wk_cipher->ic_encap(k, m0))
|
||||
return (ENOBUFS);
|
||||
|
||||
wh = mtod(m0, struct ieee80211_frame *);
|
||||
@ -1200,11 +1327,15 @@ rum_tx_mgt(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
|
||||
flags |= RT2573_TX_TIMESTAMP;
|
||||
}
|
||||
|
||||
if (k != NULL)
|
||||
flags |= rum_tx_crypto_flags(sc, ni, k);
|
||||
|
||||
data->m = m0;
|
||||
data->ni = ni;
|
||||
data->rate = tp->mgmtrate;
|
||||
|
||||
rum_setup_tx_desc(sc, &data->desc, flags, 0, m0->m_pkthdr.len, tp->mgmtrate);
|
||||
rum_setup_tx_desc(sc, &data->desc, k, flags, 0, hdrlen,
|
||||
m0->m_pkthdr.len, tp->mgmtrate);
|
||||
|
||||
DPRINTFN(10, "sending mgt frame len=%d rate=%d\n",
|
||||
m0->m_pkthdr.len + (int)RT2573_TX_DESC_SIZE, tp->mgmtrate);
|
||||
@ -1253,7 +1384,8 @@ rum_tx_raw(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
|
||||
data->rate = rate;
|
||||
|
||||
/* XXX need to setup descriptor ourself */
|
||||
rum_setup_tx_desc(sc, &data->desc, flags, 0, m0->m_pkthdr.len, rate);
|
||||
rum_setup_tx_desc(sc, &data->desc, NULL, flags, 0, 0, m0->m_pkthdr.len,
|
||||
rate);
|
||||
|
||||
DPRINTFN(10, "sending raw frame len=%u rate=%u\n",
|
||||
m0->m_pkthdr.len, rate);
|
||||
@ -1272,14 +1404,15 @@ rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
|
||||
struct rum_tx_data *data;
|
||||
struct ieee80211_frame *wh;
|
||||
const struct ieee80211_txparam *tp;
|
||||
struct ieee80211_key *k;
|
||||
struct ieee80211_key *k = NULL;
|
||||
uint32_t flags = 0;
|
||||
uint16_t dur;
|
||||
int error, rate;
|
||||
int error, hdrlen, rate;
|
||||
|
||||
RUM_LOCK_ASSERT(sc);
|
||||
|
||||
wh = mtod(m0, struct ieee80211_frame *);
|
||||
hdrlen = ieee80211_anyhdrsize(wh);
|
||||
|
||||
tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)];
|
||||
if (IEEE80211_IS_MULTICAST(wh->i_addr1))
|
||||
@ -1290,10 +1423,15 @@ rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
|
||||
rate = ni->ni_txrate;
|
||||
|
||||
if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
|
||||
k = ieee80211_crypto_encap(ni, m0);
|
||||
k = ieee80211_crypto_get_txkey(ni, m0);
|
||||
if (k == NULL) {
|
||||
m_freem(m0);
|
||||
return ENOBUFS;
|
||||
return (ENOENT);
|
||||
}
|
||||
if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) &&
|
||||
!k->wk_cipher->ic_encap(k, m0)) {
|
||||
m_freem(m0);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
|
||||
/* packet header may have moved, reset our local pointer */
|
||||
@ -1317,6 +1455,9 @@ rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
|
||||
}
|
||||
}
|
||||
|
||||
if (k != NULL)
|
||||
flags |= rum_tx_crypto_flags(sc, ni, k);
|
||||
|
||||
data = STAILQ_FIRST(&sc->tx_free);
|
||||
STAILQ_REMOVE_HEAD(&sc->tx_free, next);
|
||||
sc->tx_nfree--;
|
||||
@ -1334,7 +1475,8 @@ rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
|
||||
USETW(wh->i_dur, dur);
|
||||
}
|
||||
|
||||
rum_setup_tx_desc(sc, &data->desc, flags, 0, m0->m_pkthdr.len, rate);
|
||||
rum_setup_tx_desc(sc, &data->desc, k, flags, 0, hdrlen,
|
||||
m0->m_pkthdr.len, rate);
|
||||
|
||||
DPRINTFN(10, "sending frame len=%d rate=%d\n",
|
||||
m0->m_pkthdr.len + (int)RT2573_TX_DESC_SIZE, rate);
|
||||
@ -2087,6 +2229,14 @@ rum_bbp_init(struct rum_softc *sc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
rum_clr_shkey_regs(struct rum_softc *sc)
|
||||
{
|
||||
rum_write(sc, RT2573_SEC_CSR0, 0);
|
||||
rum_write(sc, RT2573_SEC_CSR1, 0);
|
||||
rum_write(sc, RT2573_SEC_CSR5, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
rum_init(struct rum_softc *sc)
|
||||
{
|
||||
@ -2124,6 +2274,12 @@ rum_init(struct rum_softc *sc)
|
||||
/* clear STA registers */
|
||||
rum_read_multi(sc, RT2573_STA_CSR0, sc->sta, sizeof sc->sta);
|
||||
|
||||
/* clear security registers (if required) */
|
||||
if (sc->sc_clr_shkeys == 0) {
|
||||
rum_clr_shkey_regs(sc);
|
||||
sc->sc_clr_shkeys = 1;
|
||||
}
|
||||
|
||||
rum_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
|
||||
|
||||
/* initialize ASIC */
|
||||
@ -2241,8 +2397,8 @@ rum_set_beacon(struct rum_softc *sc, struct ieee80211vap *vap)
|
||||
return EINVAL;
|
||||
|
||||
tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_bsschan)];
|
||||
rum_setup_tx_desc(sc, &desc, RT2573_TX_TIMESTAMP, RT2573_TX_HWSEQ,
|
||||
m->m_pkthdr.len, tp->mgmtrate);
|
||||
rum_setup_tx_desc(sc, &desc, NULL, RT2573_TX_TIMESTAMP,
|
||||
RT2573_TX_HWSEQ, 0, m->m_pkthdr.len, tp->mgmtrate);
|
||||
|
||||
/* copy the Tx descriptor into NIC memory */
|
||||
if (rum_write_multi(sc, RT2573_HW_BCN_BASE(0), (uint8_t *)&desc,
|
||||
@ -2329,6 +2485,216 @@ rum_update_beacon(struct ieee80211vap *vap, int item)
|
||||
rum_cmd_sleepable(sc, &vap, sizeof(vap), 0, 0, rum_update_beacon_cb);
|
||||
}
|
||||
|
||||
static int
|
||||
rum_common_key_set(struct rum_softc *sc, struct ieee80211_key *k,
|
||||
uint16_t base)
|
||||
{
|
||||
|
||||
if (rum_write_multi(sc, base, k->wk_key, k->wk_keylen))
|
||||
return EIO;
|
||||
|
||||
if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP) {
|
||||
if (rum_write_multi(sc, base + IEEE80211_KEYBUF_SIZE,
|
||||
k->wk_txmic, 8))
|
||||
return EIO;
|
||||
if (rum_write_multi(sc, base + IEEE80211_KEYBUF_SIZE + 8,
|
||||
k->wk_rxmic, 8))
|
||||
return EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
rum_group_key_set_cb(struct rum_softc *sc, union sec_param *data,
|
||||
uint8_t rn_id, uint8_t rvp_id)
|
||||
{
|
||||
struct ieee80211_key *k = &data->key;
|
||||
uint8_t mode;
|
||||
|
||||
if (sc->sc_clr_shkeys == 0) {
|
||||
rum_clr_shkey_regs(sc);
|
||||
sc->sc_clr_shkeys = 1;
|
||||
}
|
||||
|
||||
mode = rum_crypto_mode(sc, k->wk_cipher->ic_cipher, k->wk_keylen);
|
||||
if (mode == 0)
|
||||
goto print_err;
|
||||
|
||||
DPRINTFN(1, "setting group key %d for vap %d, mode %d "
|
||||
"(tx %s, rx %s)\n", k->wk_keyix, rvp_id, mode,
|
||||
(k->wk_flags & IEEE80211_KEY_XMIT) ? "on" : "off",
|
||||
(k->wk_flags & IEEE80211_KEY_RECV) ? "on" : "off");
|
||||
|
||||
/* Install the key. */
|
||||
if (rum_common_key_set(sc, k, RT2573_SKEY(rvp_id, k->wk_keyix)) != 0)
|
||||
goto print_err;
|
||||
|
||||
/* Set cipher mode. */
|
||||
if (rum_modbits(sc, rvp_id < 2 ? RT2573_SEC_CSR1 : RT2573_SEC_CSR5,
|
||||
mode << (rvp_id % 2 + k->wk_keyix) * RT2573_SKEY_MAX,
|
||||
RT2573_MODE_MASK << (rvp_id % 2 + k->wk_keyix) * RT2573_SKEY_MAX)
|
||||
!= 0)
|
||||
goto print_err;
|
||||
|
||||
/* Mark this key as valid. */
|
||||
if (rum_setbits(sc, RT2573_SEC_CSR0,
|
||||
1 << (rvp_id * RT2573_SKEY_MAX + k->wk_keyix)) != 0)
|
||||
goto print_err;
|
||||
|
||||
return;
|
||||
|
||||
print_err:
|
||||
device_printf(sc->sc_dev, "%s: cannot set group key %d for vap %d\n",
|
||||
__func__, k->wk_keyix, rvp_id);
|
||||
}
|
||||
|
||||
static void
|
||||
rum_group_key_del_cb(struct rum_softc *sc, union sec_param *data,
|
||||
uint8_t rn_id, uint8_t rvp_id)
|
||||
{
|
||||
struct ieee80211_key *k = &data->key;
|
||||
|
||||
DPRINTF("%s: removing group key %d for vap %d\n", __func__,
|
||||
k->wk_keyix, rvp_id);
|
||||
rum_clrbits(sc,
|
||||
rvp_id < 2 ? RT2573_SEC_CSR1 : RT2573_SEC_CSR5,
|
||||
RT2573_MODE_MASK << (rvp_id % 2 + k->wk_keyix) * RT2573_SKEY_MAX);
|
||||
rum_clrbits(sc, RT2573_SEC_CSR0,
|
||||
rvp_id * RT2573_SKEY_MAX + k->wk_keyix);
|
||||
}
|
||||
|
||||
static void
|
||||
rum_pair_key_set_cb(struct rum_softc *sc, union sec_param *data, uint8_t rn_id,
|
||||
uint8_t rvp_id)
|
||||
{
|
||||
struct ieee80211_key *k = &data->key;
|
||||
uint8_t buf[IEEE80211_ADDR_LEN + 1];
|
||||
uint8_t mode;
|
||||
|
||||
mode = rum_crypto_mode(sc, k->wk_cipher->ic_cipher, k->wk_keylen);
|
||||
if (mode == 0)
|
||||
goto print_err;
|
||||
|
||||
DPRINTFN(1, "setting pairwise key %d for vap %d, mode %d "
|
||||
"(tx %s, rx %s)\n", k->wk_keyix, rvp_id, mode,
|
||||
(k->wk_flags & IEEE80211_KEY_XMIT) ? "on" : "off",
|
||||
(k->wk_flags & IEEE80211_KEY_RECV) ? "on" : "off");
|
||||
|
||||
/* Install the key. */
|
||||
if (rum_common_key_set(sc, k, RT2573_PKEY(k->wk_keyix)) != 0)
|
||||
goto print_err;
|
||||
|
||||
IEEE80211_ADDR_COPY(buf, k->wk_macaddr);
|
||||
buf[IEEE80211_ADDR_LEN] = mode;
|
||||
|
||||
/* Set transmitter address and cipher mode. */
|
||||
if (rum_write_multi(sc, RT2573_ADDR_ENTRY(k->wk_keyix),
|
||||
buf, sizeof buf) != 0)
|
||||
goto print_err;
|
||||
|
||||
/* Enable key table lookup for this vap. */
|
||||
if (sc->vap_key_count[rvp_id]++ == 0)
|
||||
if (rum_setbits(sc, RT2573_SEC_CSR4, 1 << rvp_id) != 0)
|
||||
goto print_err;
|
||||
|
||||
/* Mark this key as valid. */
|
||||
if (rum_setbits(sc,
|
||||
k->wk_keyix < 32 ? RT2573_SEC_CSR2 : RT2573_SEC_CSR3,
|
||||
1 << (k->wk_keyix % 32)) != 0)
|
||||
goto print_err;
|
||||
|
||||
return;
|
||||
|
||||
print_err:
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: cannot set pairwise key %d, vap %d\n", __func__, k->wk_keyix,
|
||||
rvp_id);
|
||||
}
|
||||
|
||||
static void
|
||||
rum_pair_key_del_cb(struct rum_softc *sc, union sec_param *data, uint8_t rn_id,
|
||||
uint8_t rvp_id)
|
||||
{
|
||||
struct ieee80211_key *k = &data->key;
|
||||
|
||||
DPRINTF("%s: removing key %d\n", __func__, k->wk_keyix);
|
||||
rum_clrbits(sc, (k->wk_keyix < 32) ? RT2573_SEC_CSR2 : RT2573_SEC_CSR3,
|
||||
1 << (k->wk_keyix % 32));
|
||||
sc->keys_bmap &= ~(1 << k->wk_keyix);
|
||||
if (--sc->vap_key_count[rvp_id] == 0)
|
||||
rum_clrbits(sc, RT2573_SEC_CSR4, 1 << rvp_id);
|
||||
}
|
||||
|
||||
static int
|
||||
rum_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
|
||||
ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
|
||||
{
|
||||
struct rum_softc *sc = vap->iv_ic->ic_softc;
|
||||
uint8_t i;
|
||||
|
||||
if (!(&vap->iv_nw_keys[0] <= k &&
|
||||
k < &vap->iv_nw_keys[IEEE80211_WEP_NKID])) {
|
||||
if (!(k->wk_flags & IEEE80211_KEY_SWCRYPT)) {
|
||||
RUM_LOCK(sc);
|
||||
for (i = 0; i < RT2573_ADDR_MAX; i++) {
|
||||
if ((sc->keys_bmap & (1 << i)) == 0) {
|
||||
sc->keys_bmap |= 1 << i;
|
||||
*keyix = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
RUM_UNLOCK(sc);
|
||||
if (i == RT2573_ADDR_MAX) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: no free space in the key table\n",
|
||||
__func__);
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
*keyix = 0;
|
||||
} else {
|
||||
*keyix = k - vap->iv_nw_keys;
|
||||
}
|
||||
*rxkeyix = *keyix;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
rum_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k,
|
||||
const uint8_t mac[IEEE80211_ADDR_LEN])
|
||||
{
|
||||
struct rum_softc *sc = vap->iv_ic->ic_softc;
|
||||
int group;
|
||||
|
||||
if (k->wk_flags & IEEE80211_KEY_SWCRYPT) {
|
||||
/* Not for us. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
group = k >= &vap->iv_nw_keys[0] && k < &vap->iv_nw_keys[IEEE80211_WEP_NKID];
|
||||
|
||||
return !rum_cmd_sleepable(sc, k, sizeof(*k), 0, 0,
|
||||
group ? rum_group_key_set_cb : rum_pair_key_set_cb);
|
||||
}
|
||||
|
||||
static int
|
||||
rum_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
|
||||
{
|
||||
struct rum_softc *sc = vap->iv_ic->ic_softc;
|
||||
int group;
|
||||
|
||||
if (k->wk_flags & IEEE80211_KEY_SWCRYPT) {
|
||||
/* Not for us. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
group = k >= &vap->iv_nw_keys[0] && k < &vap->iv_nw_keys[IEEE80211_WEP_NKID];
|
||||
|
||||
return !rum_cmd_sleepable(sc, k, sizeof(*k), 0, 0,
|
||||
group ? rum_group_key_del_cb : rum_pair_key_del_cb);
|
||||
}
|
||||
|
||||
static int
|
||||
rum_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
const struct ieee80211_bpf_params *params)
|
||||
|
@ -34,13 +34,34 @@
|
||||
#define RT2573_WRITE_LED 0x0a
|
||||
|
||||
/*
|
||||
* Control and status registers.
|
||||
* WME registers.
|
||||
*/
|
||||
#define RT2573_AIFSN_CSR 0x0400
|
||||
#define RT2573_CWMIN_CSR 0x0404
|
||||
#define RT2573_CWMAX_CSR 0x0408
|
||||
#define RT2573_MCU_CODE_BASE 0x0800
|
||||
|
||||
/*
|
||||
* H/w encryption/decryption support
|
||||
*/
|
||||
#define KEY_SIZE (IEEE80211_KEYBUF_SIZE + IEEE80211_MICBUF_SIZE)
|
||||
#define RT2573_ADDR_MAX 64
|
||||
#define RT2573_SKEY_MAX 4
|
||||
|
||||
#define RT2573_SKEY(vap, kidx) (0x1000 + ((vap) * RT2573_SKEY_MAX + \
|
||||
(kidx)) * KEY_SIZE)
|
||||
#define RT2573_PKEY(id) (0x1200 + (id) * KEY_SIZE)
|
||||
|
||||
#define RT2573_ADDR_ENTRY(id) (0x1a00 + (id) * 8)
|
||||
|
||||
/*
|
||||
* Shared memory area
|
||||
*/
|
||||
#define RT2573_HW_BCN_BASE(id) (0x2400 + (id) * 0x100)
|
||||
|
||||
/*
|
||||
* Control and status registers.
|
||||
*/
|
||||
#define RT2573_MAC_CSR0 0x3000
|
||||
#define RT2573_MAC_CSR1 0x3004
|
||||
#define RT2573_MAC_CSR2 0x3008
|
||||
@ -95,6 +116,16 @@
|
||||
#define RT2573_STA_CSR5 0x30d4
|
||||
|
||||
|
||||
/* possible values for register RT2573_ADDR_MODE */
|
||||
#define RT2573_MODE_MASK 0x7
|
||||
#define RT2573_MODE_NOSEC 0
|
||||
#define RT2573_MODE_WEP40 1
|
||||
#define RT2573_MODE_WEP104 2
|
||||
#define RT2573_MODE_TKIP 3
|
||||
#define RT2573_MODE_AES_CCMP 4
|
||||
#define RT2573_MODE_CKIP40 5
|
||||
#define RT2573_MODE_CKIP104 6
|
||||
|
||||
/* possible flags for register RT2573_MAC_CSR1 */
|
||||
#define RT2573_RESET_ASIC (1 << 0)
|
||||
#define RT2573_RESET_BBP (1 << 1)
|
||||
@ -178,6 +209,10 @@ struct rum_tx_desc {
|
||||
#define RT2573_TX_OFDM (1 << 5)
|
||||
#define RT2573_TX_IFS_SIFS (1 << 6)
|
||||
#define RT2573_TX_LONG_RETRY (1 << 7)
|
||||
#define RT2573_TX_TKIPMIC (1 << 8)
|
||||
#define RT2573_TX_KEY_PAIR (1 << 9)
|
||||
#define RT2573_TX_KEY_ID(id) (((id) & 0x3f) << 10)
|
||||
#define RT2573_TX_CIP_MODE(m) ((m) << 29)
|
||||
|
||||
uint16_t wme;
|
||||
#define RT2573_QID(v) (v)
|
||||
@ -185,8 +220,9 @@ struct rum_tx_desc {
|
||||
#define RT2573_LOGCWMIN(v) ((v) << 8)
|
||||
#define RT2573_LOGCWMAX(v) ((v) << 12)
|
||||
|
||||
uint16_t xflags;
|
||||
#define RT2573_TX_HWSEQ (1 << 12)
|
||||
uint8_t hdrlen;
|
||||
uint8_t xflags;
|
||||
#define RT2573_TX_HWSEQ (1 << 4)
|
||||
|
||||
uint8_t plcp_signal;
|
||||
uint8_t plcp_service;
|
||||
@ -210,9 +246,25 @@ struct rum_rx_desc {
|
||||
uint32_t flags;
|
||||
#define RT2573_RX_BUSY (1 << 0)
|
||||
#define RT2573_RX_DROP (1 << 1)
|
||||
#define RT2573_RX_UC2ME (1 << 2)
|
||||
#define RT2573_RX_MC (1 << 3)
|
||||
#define RT2573_RX_BC (1 << 4)
|
||||
#define RT2573_RX_MYBSS (1 << 5)
|
||||
#define RT2573_RX_CRC_ERROR (1 << 6)
|
||||
#define RT2573_RX_OFDM (1 << 7)
|
||||
|
||||
#define RT2573_RX_DEC_MASK (3 << 8)
|
||||
#define RT2573_RX_DEC_OK (0 << 8)
|
||||
|
||||
#define RT2573_RX_IV_ERROR (1 << 8)
|
||||
#define RT2573_RX_MIC_ERROR (2 << 8)
|
||||
#define RT2573_RX_KEY_ERROR (3 << 8)
|
||||
|
||||
#define RT2573_RX_KEY_PAIR (1 << 28)
|
||||
|
||||
#define RT2573_RX_CIP_MASK (7 << 29)
|
||||
#define RT2573_RX_CIP_MODE(m) ((m) << 29)
|
||||
|
||||
uint8_t rate;
|
||||
uint8_t rssi;
|
||||
uint8_t reserved1;
|
||||
|
@ -136,10 +136,14 @@ struct rum_softc {
|
||||
uint32_t rf_regs[4];
|
||||
uint8_t txpow[44];
|
||||
u_int sc_detached:1,
|
||||
sc_running:1;
|
||||
sc_running:1,
|
||||
sc_clr_shkeys:1;
|
||||
|
||||
uint8_t sc_bssid[IEEE80211_ADDR_LEN];
|
||||
|
||||
uint8_t vap_key_count[1];
|
||||
uint64_t keys_bmap;
|
||||
|
||||
struct {
|
||||
uint8_t val;
|
||||
uint8_t reg;
|
||||
|
Loading…
x
Reference in New Issue
Block a user