-/* $OpenBSD: if_iwi.c,v 1.89 2008/08/27 09:28:38 damien Exp $ */
+/* $OpenBSD: if_iwi.c,v 1.90 2008/08/28 15:52:20 damien Exp $ */
/*-
- * Copyright (c) 2004-2006
+ * Copyright (c) 2004-2008
* Damien Bergamini <damien.bergamini@free.fr>. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice unmodified, this list of conditions, and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
*
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
int iwi_load_ucode(struct iwi_softc *, const char *, int);
int iwi_load_firmware(struct iwi_softc *, const char *, int);
int iwi_config(struct iwi_softc *);
+void iwi_update_edca(struct ieee80211com *);
int iwi_set_chan(struct iwi_softc *, struct ieee80211_channel *);
int iwi_scan(struct iwi_softc *);
int iwi_auth_and_assoc(struct iwi_softc *);
IEEE80211_C_TXPMGT | /* tx power management */
IEEE80211_C_SHPREAMBLE | /* short preamble supported */
IEEE80211_C_SHSLOT | /* short slot time supported */
- IEEE80211_C_WEP | /* h/w WEP supported */
+ IEEE80211_C_WEP | /* s/w WEP */
+ IEEE80211_C_RSN | /* WPA/RSN supported */
IEEE80211_C_SCANALL; /* h/w scanning */
/* read MAC address from EEPROM */
error = ENOMEM;
goto fail;
}
-
MCLGET(data->m, M_DONTWAIT);
if (!(data->m->m_flags & M_EXT)) {
m_freem(data->m);
sizeof (struct iwi_frame) + letoh16(frame->len);
m_adj(m, sizeof (struct iwi_hdr) + sizeof (struct iwi_frame));
- wh = mtod(m, struct ieee80211_frame *);
-
- rxi.rxi_flags = 0;
- if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
- /*
- * Hardware decrypts the frame itself but leaves the WEP bit
- * set in the 802.11 header and doesn't remove the IV and CRC
- * fields.
- */
- wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
- ovbcopy(wh, (char *)wh + IEEE80211_WEP_IVLEN +
- IEEE80211_WEP_KIDLEN, sizeof (struct ieee80211_frame));
- m_adj(m, IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN);
- m_adj(m, -IEEE80211_WEP_CRCLEN);
- wh = mtod(m, struct ieee80211_frame *);
-
- rxi.rxi_flags |= IEEE80211_RXI_HWDEC;
- }
-
#if NBPFILTER > 0
if (sc->sc_drvbpf != NULL) {
struct mbuf mb;
}
#endif
+ wh = mtod(m, struct ieee80211_frame *);
ni = ieee80211_find_rxnode(ic, wh);
/* send the frame to the upper layer */
+ rxi.rxi_flags = 0;
rxi.rxi_rssi = frame->rssi_dbm;
rxi.rxi_tstamp = 0; /* unused */
ieee80211_input(ifp, m, ni, &rxi);
{
struct iwi_softc *sc = ifp->if_softc;
struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211_frame *wh;
+ struct ieee80211_key *k;
struct iwi_tx_data *data;
struct iwi_tx_desc *desc;
struct iwi_tx_ring *txq = &sc->txq[0];
struct mbuf *mnew;
- int error, i, station = 0;
+ int hdrlen, error, i, station = 0;
+
+ wh = mtod(m0, struct ieee80211_frame *);
+
+ if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
+ k = ieee80211_get_txkey(ic, wh, ni);
+
+ if ((m0 = ieee80211_encrypt(ic, m0, k)) == NULL)
+ return ENOBUFS;
+
+ /* packet header may have moved, reset our local pointer */
+ wh = mtod(m0, struct ieee80211_frame *);
+ }
#if NBPFILTER > 0
if (sc->sc_drvbpf != NULL) {
data = &txq->data[txq->cur];
desc = &txq->desc[txq->cur];
- /* save and trim IEEE802.11 header */
- m_copydata(m0, 0, sizeof (struct ieee80211_frame), (caddr_t)&desc->wh);
- m_adj(m0, sizeof (struct ieee80211_frame));
+ /* copy and trim IEEE802.11 header */
+ hdrlen = ieee80211_get_hdrlen(wh);
+ bcopy(wh, &desc->wh, hdrlen);
+ m_adj(m0, hdrlen);
#ifndef IEEE80211_STA_ONLY
if (ic->ic_opmode == IEEE80211_M_IBSS) {
m_freem(m0);
return ENOMEM;
}
-
M_DUP_PKTHDR(mnew, m0);
if (m0->m_pkthdr.len > MHLEN) {
MCLGET(mnew, M_DONTWAIT);
desc->cmd = IWI_DATA_CMD_TX;
desc->len = htole16(m0->m_pkthdr.len);
desc->station = station;
- desc->flags = 0;
+ desc->flags = IWI_DATA_FLAG_NO_WEP;
desc->xflags = 0;
if (!IEEE80211_IS_MULTICAST(desc->wh.i_addr1))
desc->flags |= IWI_DATA_FLAG_NEED_ACK;
- if (desc->wh.i_fc[1] & IEEE80211_FC1_WEP) {
- desc->wep_txkey = ic->ic_wep_txkey |
- ((ic->ic_nw_keys[ic->ic_wep_txkey].k_cipher ==
- IEEE80211_CIPHER_WEP40) ? IWI_DATA_KEY_WEP40 :
- IWI_DATA_KEY_WEP104);
- } else {
- desc->flags |= IWI_DATA_FLAG_NO_WEP;
- desc->wep_txkey = 0;
- }
if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
desc->flags |= IWI_DATA_FLAG_SHPREAMBLE;
+ if ((desc->wh.i_fc[0] &
+ (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) ==
+ (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS))
+ desc->xflags |= IWI_DATA_XFLAG_QOS;
+
if (ic->ic_curmode == IEEE80211_MODE_11B)
desc->xflags |= IWI_DATA_XFLAG_CCK;
struct iwi_configuration config;
struct iwi_rateset rs;
struct iwi_txpower power;
- struct ieee80211_key *k;
- struct iwi_wep_key wepkey;
uint32_t data;
int error, nchan, i;
return error;
}
- data = htole32(arc4random());
- DPRINTF(("Setting initialization vector to %u\n", letoh32(data)));
- error = iwi_cmd(sc, IWI_CMD_SET_IV, &data, sizeof data, 0);
+ data = arc4random();
+ DPRINTF(("Setting random seed to %u\n", data));
+ error = iwi_cmd(sc, IWI_CMD_SET_RANDOM_SEED, &data, sizeof data, 0);
if (error != 0)
return error;
- if (ic->ic_flags & IEEE80211_F_WEPON) {
- k = ic->ic_nw_keys;
- for (i = 0; i < IEEE80211_WEP_NKID; i++, k++) {
- wepkey.cmd = IWI_WEP_KEY_CMD_SETKEY;
- wepkey.idx = i;
- wepkey.len = k->k_len;
- bzero(wepkey.key, sizeof wepkey.key);
- bcopy(k->k_key, wepkey.key, k->k_len);
- DPRINTF(("Setting wep key index %u len %u\n",
- wepkey.idx, wepkey.len));
- error = iwi_cmd(sc, IWI_CMD_SET_WEP_KEY, &wepkey,
- sizeof wepkey, 0);
- if (error != 0)
- return error;
- }
- }
-
/* enable adapter */
DPRINTF(("Enabling adapter\n"));
return iwi_cmd(sc, IWI_CMD_ENABLE, NULL, 0, 0);
}
+void
+iwi_update_edca(struct ieee80211com *ic)
+{
+#define IWI_EXP2(v) htole16((1 << (v)) - 1)
+#define IWI_TXOP(v) IEEE80211_TXOP_TO_US(v)
+ struct iwi_softc *sc = ic->ic_softc;
+ struct iwi_qos_cmd cmd;
+ struct iwi_qos_params *qos;
+ struct ieee80211_edca_ac_params *edca = ic->ic_edca_ac;
+ int aci;
+
+ /* set default QoS parameters for CCK */
+ qos = &cmd.cck;
+ for (aci = 0; aci < EDCA_NUM_AC; aci++) {
+ qos->cwmin[aci] = IWI_EXP2(iwi_cck[aci].ac_ecwmin);
+ qos->cwmax[aci] = IWI_EXP2(iwi_cck[aci].ac_ecwmax);
+ qos->txop [aci] = IWI_TXOP(iwi_cck[aci].ac_txoplimit);
+ qos->aifsn[aci] = iwi_cck[aci].ac_aifsn;
+ qos->acm [aci] = 0;
+ }
+ /* set default QoS parameters for OFDM */
+ qos = &cmd.ofdm;
+ for (aci = 0; aci < EDCA_NUM_AC; aci++) {
+ qos->cwmin[aci] = IWI_EXP2(iwi_ofdm[aci].ac_ecwmin);
+ qos->cwmax[aci] = IWI_EXP2(iwi_ofdm[aci].ac_ecwmax);
+ qos->txop [aci] = IWI_TXOP(iwi_ofdm[aci].ac_txoplimit);
+ qos->aifsn[aci] = iwi_ofdm[aci].ac_aifsn;
+ qos->acm [aci] = 0;
+ }
+ /* set current QoS parameters */
+ qos = &cmd.current;
+ for (aci = 0; aci < EDCA_NUM_AC; aci++) {
+ qos->cwmin[aci] = IWI_EXP2(edca[aci].ac_ecwmin);
+ qos->cwmax[aci] = IWI_EXP2(edca[aci].ac_ecwmax);
+ qos->txop [aci] = IWI_TXOP(edca[aci].ac_txoplimit);
+ qos->aifsn[aci] = edca[aci].ac_aifsn;
+ qos->acm [aci] = 0;
+ }
+
+ DPRINTF(("Setting QoS parameters\n"));
+ (void)iwi_cmd(sc, IWI_CMD_SET_QOS_PARAMS, &cmd, sizeof cmd, 1);
+#undef IWI_EXP2
+#undef IWI_TXOP
+}
+
int
iwi_set_chan(struct iwi_softc *sc, struct ieee80211_channel *chan)
{
struct iwi_configuration config;
struct iwi_associate assoc;
struct iwi_rateset rs;
- uint16_t capinfo;
+ uint8_t *frm;
uint32_t data;
+ uint16_t capinfo;
+ uint8_t buf[64]; /* XXX max WPA/RSN/WMM IE length */
int error;
/* update adapter configuration */
bzero(&config, sizeof config);
config.multicast_enabled = 1;
+ config.disable_unicast_decryption = 1;
+ config.disable_multicast_decryption = 1;
config.silence_threshold = 30;
config.report_noise = 1;
config.answer_pbreq =
if (error != 0)
return error;
+ if (ic->ic_flags & IEEE80211_F_QOS) {
+ iwi_update_edca(ic);
+
+ frm = ieee80211_add_edca_params(buf, ic);
+ DPRINTF(("Setting EDCA IE length %d\n", frm - buf));
+ error = iwi_cmd(sc, IWI_CMD_SET_EDCAIE, buf, frm - buf, 1);
+ if (error != 0)
+ return error;
+ }
+ if (ic->ic_flags & IEEE80211_F_RSNON) {
+ /* tell firmware to add WPA/RSN IE to (re)assoc request */
+ if (ni->ni_rsnprotos == IEEE80211_PROTO_RSN)
+ frm = ieee80211_add_rsn(buf, ic, ni);
+ else
+ frm = ieee80211_add_wpa(buf, ic, ni);
+ DPRINTF(("Setting RSN IE length %d\n", frm - buf));
+ error = iwi_cmd(sc, IWI_CMD_SET_OPTIE, buf, frm - buf, 1);
+ if (error != 0)
+ return error;
+ }
+
bzero(&assoc, sizeof assoc);
#ifndef IEEE80211_STA_ONLY
if (ic->ic_flags & IEEE80211_F_SIBSS)
else
#endif
assoc.type = IWI_ASSOC_ASSOCIATE;
+ assoc.policy = 0;
+ if (ic->ic_flags & IEEE80211_F_RSNON)
+ assoc.policy |= htole16(IWI_ASSOC_POLICY_RSN);
+ if (ic->ic_flags & IEEE80211_F_QOS)
+ assoc.policy |= htole16(IWI_ASSOC_POLICY_QOS);
if (ic->ic_curmode == IEEE80211_MODE_11A)
assoc.mode = IWI_MODE_11A;
else if (ic->ic_curmode == IEEE80211_MODE_11B)
else /* assume 802.11b/g */
assoc.mode = IWI_MODE_11G;
assoc.chan = ieee80211_chan2ieee(ic, ni->ni_chan);
-#if 0
- if (ni->ni_challenge != NULL) /* XXX */
- assoc.auth = (ic->ic_wep_txkey << 4) | IWI_AUTH_SHARED;
-#endif
- if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
+ if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
+ IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
assoc.plen = IWI_ASSOC_SHPREAMBLE;
bcopy(ni->ni_tstamp, assoc.tstamp, 8);
capinfo = IEEE80211_CAPINFO_ESS;
- if (ic->ic_flags & IEEE80211_F_WEPON)
+ if (ic->ic_flags & (IEEE80211_F_WEPON | IEEE80211_F_RSNON))
capinfo |= IEEE80211_CAPINFO_PRIVACY;
if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
-/* $OpenBSD: if_iwireg.h,v 1.25 2006/08/19 11:07:45 damien Exp $ */
+/* $OpenBSD: if_iwireg.h,v 1.26 2008/08/28 15:52:20 damien Exp $ */
/*-
- * Copyright (c) 2004-2006
+ * Copyright (c) 2004-2008
* Damien Bergamini <damien.bergamini@free.fr>. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice unmodified, this list of conditions, and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
*
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define IWI_CMD_RING_COUNT 16
#define IWI_NOTIF_TYPE_SCAN_COMPLETE 13
#define IWI_NOTIF_TYPE_BAD_LINK 15
#define IWI_NOTIF_TYPE_BEACON 17
+#define IWI_NOTIF_TYPE_PAIRWISE_KEY 18
#define IWI_NOTIF_TYPE_CALIBRATION 20
#define IWI_NOTIF_TYPE_NOISE 25
#define IWI_DATA_FLAG_NEED_ACK (1 << 7)
uint8_t xflags;
-#define IWI_DATA_XFLAG_CCK (1 << 0)
+#define IWI_DATA_XFLAG_CCK (1 << 0)
+#define IWI_DATA_XFLAG_QOS (1 << 4)
- uint8_t wep_txkey;
-#define IWI_DATA_KEY_WEP40 (1 << 6)
-#define IWI_DATA_KEY_WEP104 (1 << 7)
+ uint8_t txkey;
+#define IWI_DATA_KEY_USE_PAIRWISE (1 << 5)
+#define IWI_DATA_KEY_WEP40 (1 << 6)
+#define IWI_DATA_KEY_WEP104 (1 << 7)
uint8_t wepkey[IEEE80211_KEYBUF_SIZE];
uint8_t rate;
#define IWI_CMD_SET_RTS_THRESHOLD 15
#define IWI_CMD_SET_FRAG_THRESHOLD 16
#define IWI_CMD_SET_POWER_MODE 17
-#define IWI_CMD_SET_WEP_KEY 18
+#define IWI_CMD_SET_GROUP_KEY 18
+#define IWI_CMD_SET_PAIRWISE_KEY 19
#define IWI_CMD_ASSOCIATE 21
#define IWI_CMD_SET_RATES 22
+#define IWI_CMD_SET_QOS_PARAMS 25
#define IWI_CMD_SCAN 26
+#define IWI_CMD_SET_OPTIE 31
#define IWI_CMD_DISABLE 33
-#define IWI_CMD_SET_IV 34
+#define IWI_CMD_SET_RANDOM_SEED 34
#define IWI_CMD_SET_TX_POWER 35
#define IWI_CMD_SET_SENSITIVITY 42
+#define IWI_CMD_SET_EDCAIE 84
uint8_t len;
uint16_t reserved;
uint8_t rates[12];
} __packed;
+/* structures for command IWI_CMD_SET_QOS_PARAMS */
+struct iwi_qos_params {
+ uint16_t cwmin[EDCA_NUM_AC];
+ uint16_t cwmax[EDCA_NUM_AC];
+ uint8_t aifsn[EDCA_NUM_AC];
+ uint8_t acm [EDCA_NUM_AC];
+ uint8_t txop [EDCA_NUM_AC];
+} __packed;
+
+struct iwi_qos_cmd {
+ struct iwi_qos_params cck;
+ struct iwi_qos_params ofdm;
+ struct iwi_qos_params current;
+} __packed;
+
+/* copied verbatim from sys/net80211/ieee80211_output.c */
+static const struct ieee80211_edca_ac_params iwi_cck[EDCA_NUM_AC] = {
+ [EDCA_AC_BK] = { 5, 10, 7, 0 },
+ [EDCA_AC_BE] = { 5, 10, 3, 0 },
+ [EDCA_AC_VI] = { 4, 5, 2, 188 },
+ [EDCA_AC_VO] = { 3, 4, 2, 102 }
+};
+
+/* copied verbatim from sys/net80211/ieee80211_output.c */
+static const struct ieee80211_edca_ac_params iwi_ofdm[EDCA_NUM_AC] = {
+ [EDCA_AC_BK] = { 4, 10, 7, 0 },
+ [EDCA_AC_BE] = { 4, 10, 3, 0 },
+ [EDCA_AC_VI] = { 3, 4, 2, 94 },
+ [EDCA_AC_VO] = { 2, 3, 2, 47 }
+};
+
/* structure for command IWI_CMD_SET_TX_POWER */
struct iwi_txpower {
uint8_t nchan;
#define IWI_ASSOC_SIBSS 3
uint8_t reserved1;
- uint16_t reserved2;
+ uint16_t policy;
+#define IWI_ASSOC_POLICY_QOS (1 << 0)
+#define IWI_ASSOC_POLICY_RSN (1 << 1)
+
uint8_t plen;
#define IWI_ASSOC_SHPREAMBLE (1 << 2)
uint8_t reserved5;
} __packed;
-/* structure for command IWI_CMD_SET_WEP_KEY */
-struct iwi_wep_key {
+/* structure for command IWI_CMD_SET_GROUP_KEY */
+struct iwi_group_key {
uint8_t cmd;
-#define IWI_WEP_KEY_CMD_SETKEY 0x08
+#define IWI_GROUP_KEY_CMD_SETKEY 0x08
uint8_t seq;
uint8_t idx;
uint8_t len;
- uint8_t key[IEEE80211_KEYBUF_SIZE];
+ uint8_t key[16];
+} __packed;
+
+/* structure for command IWI_CMD_SET_PAIRWISE_KEY */
+struct iwi_pairwise_key {
+ uint8_t idx;
+ uint8_t cipher;
+#define IWI_CIPHER_WEP 0
+#define IWI_CIPHER_CCMP 2
+#define IWI_CIPHER_TKIP 3
+ uint8_t sta;
+ uint8_t flags;
+ uint8_t key[16];
+ uint64_t tsc;
} __packed;
#define IWI_MEM_EEPROM_CTL 0x00300040