summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2008-08-28 14:40:45 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2008-08-28 14:40:45 +0000
commit71d3aafee2ea867be57ce58c03d68cd0e0215e17 (patch)
treef1b3c762eed5d25b10f8f469924da62bd9612f2b /sys
parentd773ef3fa87a6513840e05dbc285a6d6b8997e36 (diff)
WPA support for ipw(4).
Did a lot of cleanup while I was there.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/if_ipw.c399
-rw-r--r--sys/dev/pci/if_ipwreg.h30
2 files changed, 260 insertions, 169 deletions
diff --git a/sys/dev/pci/if_ipw.c b/sys/dev/pci/if_ipw.c
index dec88cbf888..ce7e03cc9c0 100644
--- a/sys/dev/pci/if_ipw.c
+++ b/sys/dev/pci/if_ipw.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ipw.c,v 1.75 2008/08/27 09:28:38 damien Exp $ */
+/* $OpenBSD: if_ipw.c,v 1.76 2008/08/28 14:40:44 damien Exp $ */
/*-
* Copyright (c) 2004-2008
@@ -36,6 +36,7 @@
#include <sys/param.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
+#include <sys/workq.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
@@ -106,6 +107,8 @@ int ipw_reset(struct ipw_softc *);
int ipw_load_ucode(struct ipw_softc *, u_char *, int);
int ipw_load_firmware(struct ipw_softc *, u_char *, int);
int ipw_read_firmware(struct ipw_softc *, struct ipw_firmware *);
+void ipw_scan(void *, void *);
+void ipw_auth_and_assoc(void *, void *);
int ipw_config(struct ipw_softc *);
int ipw_init(struct ifnet *);
void ipw_stop(struct ifnet *, int);
@@ -235,6 +238,7 @@ ipw_attach(struct device *parent, struct device *self, void *aux)
IEEE80211_C_TXPMGT | /* tx power management */
IEEE80211_C_SHPREAMBLE | /* short preamble supported */
IEEE80211_C_WEP | /* s/w WEP */
+ IEEE80211_C_RSN | /* WPA/RSN */
IEEE80211_C_SCANALL; /* h/w scanning */
/* read MAC address from EEPROM */
@@ -665,29 +669,25 @@ int
ipw_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
{
struct ipw_softc *sc = ic->ic_softc;
- struct ieee80211_node *ni;
- uint8_t macaddr[IEEE80211_ADDR_LEN];
- uint32_t len;
+ int error;
switch (nstate) {
- case IEEE80211_S_RUN:
- DELAY(100); /* firmware needs a short delay here */
-
- len = IEEE80211_ADDR_LEN;
- ipw_read_table2(sc, IPW_INFO_CURRENT_BSSID, macaddr, &len);
-
- ni = ieee80211_find_node(ic, macaddr);
- if (ni == NULL)
- break;
+ case IEEE80211_S_SCAN:
+ error = workq_add_task(NULL, 0, ipw_scan, sc, NULL);
+ if (error != 0)
+ return error;
+ break;
- (*ic->ic_node_copy)(ic, ic->ic_bss, ni);
- ieee80211_node_newstate(ni, IEEE80211_STA_BSS);
+ case IEEE80211_S_AUTH:
+ error = workq_add_task(NULL, 0, ipw_auth_and_assoc, sc, NULL);
+ if (error != 0)
+ return error;
break;
+ case IEEE80211_S_RUN:
case IEEE80211_S_INIT:
- case IEEE80211_S_SCAN:
- case IEEE80211_S_AUTH:
case IEEE80211_S_ASSOC:
+ /* nothing to do */
break;
}
@@ -761,11 +761,10 @@ ipw_command_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf)
cmd = mtod(sbuf->m, struct ipw_cmd *);
- DPRINTFN(2, ("RX!CMD!%u!%u!%u!%u!%u\n",
- letoh32(cmd->type), letoh32(cmd->subtype), letoh32(cmd->seq),
- letoh32(cmd->len), letoh32(cmd->status)));
+ DPRINTFN(2, ("received command ack type=%u,status=%u\n",
+ letoh32(cmd->type), letoh32(cmd->status)));
- wakeup(sc);
+ wakeup(&sc->cmd);
}
void
@@ -780,29 +779,26 @@ ipw_newstate_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf)
state = letoh32(*mtod(sbuf->m, uint32_t *));
- DPRINTFN(2, ("RX!NEWSTATE!%u\n", state));
+ DPRINTFN(2, ("firmware state changed to 0x%x\n", state));
switch (state) {
case IPW_STATE_ASSOCIATED:
ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
break;
- case IPW_STATE_SCANNING:
- /* don't leave run state on background scan */
- if (ic->ic_state != IEEE80211_S_RUN)
- ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
-
- ic->ic_flags |= IEEE80211_F_ASCAN;
- break;
-
case IPW_STATE_SCAN_COMPLETE:
- ic->ic_flags &= ~IEEE80211_F_ASCAN;
+ if (ic->ic_state == IEEE80211_S_SCAN)
+ ieee80211_end_scan(ifp);
break;
case IPW_STATE_ASSOCIATION_LOST:
ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
break;
+ case IPW_STATE_DISABLED:
+ wakeup(sc);
+ break;
+
case IPW_STATE_RADIO_DISABLED:
ifp->if_flags &= ~IFF_UP;
ipw_stop(&ic->ic_if, 1);
@@ -822,7 +818,8 @@ ipw_data_intr(struct ipw_softc *sc, struct ipw_status *status,
struct ieee80211_node *ni;
int error;
- DPRINTFN(5, ("RX!DATA!%u!%u\n", letoh32(status->len), status->rssi));
+ DPRINTFN(5, ("received data frame len=%u,rssi=%u\n",
+ letoh32(status->len), status->rssi));
/*
* Try to allocate a new mbuf for this ring element and load it before
@@ -907,7 +904,7 @@ ipw_data_intr(struct ipw_softc *sc, struct ipw_status *status,
void
ipw_notification_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf)
{
- DPRINTFN(2, ("RX!NOTIFICATION\n"));
+ DPRINTFN(2, ("received notification\n"));
}
void
@@ -1043,8 +1040,6 @@ ipw_intr(void *arg)
/* disable interrupts */
CSR_WRITE_4(sc, IPW_CSR_INTR_MASK, 0);
- DPRINTFN(8, ("INTR!0x%08x\n", r));
-
if (r & (IPW_INTR_FATAL_ERROR | IPW_INTR_PARITY_ERROR)) {
printf("%s: fatal firmware error\n", sc->sc_dev.dv_xname);
ifp->if_flags &= ~IFF_UP;
@@ -1074,25 +1069,27 @@ int
ipw_cmd(struct ipw_softc *sc, uint32_t type, void *data, uint32_t len)
{
struct ipw_soft_bd *sbd;
- int error;
+ int s, error;
- sbd = &sc->stbd_list[sc->txcur];
+ s = splnet();
+
+ sc->cmd.type = htole32(type);
+ sc->cmd.subtype = htole32(0);
+ sc->cmd.len = htole32(len);
+ sc->cmd.seq = htole32(0);
+ if (data != NULL)
+ bcopy(data, sc->cmd.data, len);
error = bus_dmamap_load(sc->sc_dmat, sc->cmd_map, &sc->cmd,
sizeof (struct ipw_cmd), NULL, BUS_DMA_NOWAIT);
if (error != 0) {
printf("%s: could not map command DMA memory\n",
sc->sc_dev.dv_xname);
+ splx(s);
return error;
}
- sc->cmd.type = htole32(type);
- sc->cmd.subtype = htole32(0);
- sc->cmd.len = htole32(len);
- sc->cmd.seq = htole32(0);
- if (data != NULL)
- bcopy(data, sc->cmd.data, len);
-
+ sbd = &sc->stbd_list[sc->txcur];
sbd->type = IPW_SBD_TYPE_COMMAND;
sbd->bd->physaddr = htole32(sc->cmd_map->dm_segs[0].ds_addr);
sbd->bd->len = htole32(sizeof (struct ipw_cmd));
@@ -1102,7 +1099,6 @@ ipw_cmd(struct ipw_softc *sc, uint32_t type, void *data, uint32_t len)
bus_dmamap_sync(sc->sc_dmat, sc->cmd_map, 0, sizeof (struct ipw_cmd),
BUS_DMASYNC_PREWRITE);
-
bus_dmamap_sync(sc->sc_dmat, sc->tbd_map,
sc->txcur * sizeof (struct ipw_bd), sizeof (struct ipw_bd),
BUS_DMASYNC_PREWRITE);
@@ -1111,10 +1107,13 @@ ipw_cmd(struct ipw_softc *sc, uint32_t type, void *data, uint32_t len)
sc->txfree--;
CSR_WRITE_4(sc, IPW_CSR_TX_WRITE_INDEX, sc->txcur);
- DPRINTFN(2, ("TX!CMD!%u!%u!%u!%u\n", type, 0, 0, len));
+ DPRINTFN(2, ("sending command type=%u,len=%u\n", type, len));
/* wait at most one second for command to complete */
- return tsleep(sc, 0, "ipwcmd", hz);
+ error = tsleep(&sc->cmd, 0, "ipwcmd", hz);
+ splx(s);
+
+ return error;
}
int
@@ -1241,11 +1240,6 @@ ipw_tx_start(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni)
sbd->bd->flags = IPW_BD_FLAG_TX_FRAME_802_3 |
IPW_BD_FLAG_TX_NOT_LAST_FRAGMENT;
- DPRINTFN(5, ("TX!HDR!%u!%u!%u!%u", shdr->hdr.type, shdr->hdr.subtype,
- shdr->hdr.encrypted, shdr->hdr.encrypt));
- DPRINTFN(5, ("!%s", ether_sprintf(shdr->hdr.src_addr)));
- DPRINTFN(5, ("!%s\n", ether_sprintf(shdr->hdr.dst_addr)));
-
bus_dmamap_sync(sc->sc_dmat, sc->tbd_map,
sc->txcur * sizeof (struct ipw_bd),
sizeof (struct ipw_bd), BUS_DMASYNC_PREWRITE);
@@ -1271,9 +1265,6 @@ ipw_tx_start(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni)
sbd->bd->flags |= IPW_BD_FLAG_TX_NOT_LAST_FRAGMENT;
}
- DPRINTFN(5, ("TX!FRAG!%d!%d\n", i,
- sbuf->map->dm_segs[i].ds_len));
-
bus_dmamap_sync(sc->sc_dmat, sc->tbd_map,
sc->txcur * sizeof (struct ipw_bd),
sizeof (struct ipw_bd), BUS_DMASYNC_PREWRITE);
@@ -1301,11 +1292,10 @@ ipw_start(struct ifnet *ifp)
struct ieee80211_node *ni;
struct mbuf *m;
- for (;;) {
- IF_PURGE(&ic->ic_mgtq);
+ if (ic->ic_state != IEEE80211_S_RUN)
+ return;
- if (ic->ic_state != IEEE80211_S_RUN)
- return;
+ for (;;) {
IFQ_POLL(&ifp->if_snd, m);
if (m == NULL)
break;
@@ -1671,18 +1661,174 @@ fail: free(fw->data, M_DEVBUF);
return error;
}
+void
+ipw_scan(void *arg1, void *arg2)
+{
+ struct ipw_softc *sc = arg1;
+ struct ifnet *ifp = &sc->sc_ic.ic_if;
+ struct ipw_scan_options scan;
+ uint8_t ssid[IEEE80211_NWID_LEN];
+ int error;
+
+ /*
+ * Firmware has a bug and does not honour the ``do not associate
+ * after scan'' bit in the scan command. To prevent the firmware
+ * from associating after the scan, we set the ESSID to something
+ * unlikely to be used by a real AP.
+ * XXX would setting the BSSID to a multicast address work?
+ */
+ memset(ssid, '\r', sizeof ssid);
+ error = ipw_cmd(sc, IPW_CMD_SET_ESSID, ssid, sizeof ssid);
+ if (error != 0)
+ goto fail;
+
+ /* no mandatory BSSID */
+ DPRINTF(("Setting mandatory BSSID to null\n"));
+ error = ipw_cmd(sc, IPW_CMD_SET_MANDATORY_BSSID, NULL, 0);
+ if (error != 0)
+ goto fail;
+
+ scan.flags = htole32(IPW_SCAN_DO_NOT_ASSOCIATE | IPW_SCAN_MIXED_CELL);
+ scan.channels = htole32(0x3fff); /* scan channels 1-14 */
+ DPRINTF(("Setting scan options to 0x%x\n", letoh32(scan.flags)));
+ error = ipw_cmd(sc, IPW_CMD_SET_SCAN_OPTIONS, &scan, sizeof scan);
+ if (error != 0)
+ goto fail;
+
+ /* start scanning */
+ DPRINTF(("Enabling adapter\n"));
+ error = ipw_cmd(sc, IPW_CMD_ENABLE, NULL, 0);
+ if (error != 0)
+ goto fail;
+
+ return;
+ fail:
+ printf("%s: scan request failed (error=%d)\n", sc->sc_dev.dv_xname,
+ error);
+ ieee80211_end_scan(ifp);
+}
+
+void
+ipw_auth_and_assoc(void *arg1, void *arg2)
+{
+ struct ipw_softc *sc = arg1;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211_node *ni = ic->ic_bss;
+ struct ipw_scan_options scan;
+ struct ipw_security security;
+ struct ipw_assoc_req assoc;
+ uint32_t data;
+ uint8_t chan;
+ int s, error;
+
+ DPRINTF(("Disabling adapter\n"));
+ error = ipw_cmd(sc, IPW_CMD_DISABLE, NULL, 0);
+ if (error != 0)
+ goto fail;
+#if 1
+ /* wait at most one second for card to be disabled */
+ s = splnet();
+ error = tsleep(sc, 0, "ipwdis", hz);
+ splx(s);
+ if (error != 0) {
+ printf("%s: timeout waiting for disabled state\n",
+ sc->sc_dev.dv_xname);
+ goto fail;
+ }
+#else
+ /* Intel's Linux driver polls for the DISABLED state instead.. */
+ for (ntries = 0; ntries < 1000; ntries++) {
+ if (ipw_read_table1(sc, IPW_INFO_CARD_DISABLED) == 1)
+ break;
+ DELAY(10);
+ }
+ if (ntries == 1000) {
+ printf("%s: timeout waiting for disabled state\n",
+ sc->sc_dev.dv_xname);
+ goto fail;
+ }
+#endif
+
+ bzero(&security, sizeof security);
+ security.authmode = IPW_AUTH_OPEN;
+ security.ciphers = htole32(IPW_CIPHER_NONE);
+ DPRINTF(("Setting authmode to %u\n", security.authmode));
+ error = ipw_cmd(sc, IPW_CMD_SET_SECURITY_INFORMATION, &security,
+ sizeof security);
+ if (error != 0)
+ goto fail;
+
+#ifdef IPW_DEBUG
+ if (ipw_debug > 0) {
+ printf("Setting ESSID to ");
+ ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
+ printf("\n");
+ }
+#endif
+ error = ipw_cmd(sc, IPW_CMD_SET_ESSID, ni->ni_essid, ni->ni_esslen);
+ if (error != 0)
+ goto fail;
+
+ DPRINTF(("Setting BSSID to %s\n", ether_sprintf(ni->ni_bssid)));
+ error = ipw_cmd(sc, IPW_CMD_SET_MANDATORY_BSSID, ni->ni_bssid,
+ IEEE80211_ADDR_LEN);
+ if (error != 0)
+ goto fail;
+
+ data = htole32((ic->ic_flags & (IEEE80211_F_WEPON |
+ IEEE80211_F_RSNON)) ? IPW_PRIVACYON : 0);
+ DPRINTF(("Setting privacy flags to 0x%x\n", letoh32(data)));
+ error = ipw_cmd(sc, IPW_CMD_SET_PRIVACY_FLAGS, &data, sizeof data);
+ if (error != 0)
+ goto fail;
+
+ /* let firmware set the capinfo, lintval, and bssid fixed fields */
+ bzero(&assoc, sizeof assoc);
+ if (ic->ic_flags & IEEE80211_F_RSNON) {
+ uint8_t *frm = assoc.optie;
+
+ /* tell firmware to add a WPA or RSN IE in (Re)Assoc req */
+ if (ni->ni_rsnprotos & IEEE80211_PROTO_RSN)
+ frm = ieee80211_add_rsn(frm, ic, ni);
+ else if (ni->ni_rsnprotos & IEEE80211_PROTO_WPA)
+ frm = ieee80211_add_wpa(frm, ic, ni);
+ assoc.optie_len = htole32(frm - assoc.optie);
+ }
+ DPRINTF(("Preparing assocation request (optional IE length=%d)\n",
+ letoh32(assoc.optie_len)));
+ error = ipw_cmd(sc, IPW_CMD_SET_ASSOC_REQ, &assoc, sizeof assoc);
+ if (error != 0)
+ goto fail;
+
+ scan.flags = htole32(IPW_SCAN_MIXED_CELL);
+ chan = ieee80211_chan2ieee(ic, ni->ni_chan);
+ scan.channels = htole32(1 << (chan - 1));
+ DPRINTF(("Setting scan options to 0x%x\n", letoh32(scan.flags)));
+ error = ipw_cmd(sc, IPW_CMD_SET_SCAN_OPTIONS, &scan, sizeof scan);
+ if (error != 0)
+ goto fail;
+
+ /* trigger scan+association */
+ DPRINTF(("Enabling adapter\n"));
+ error = ipw_cmd(sc, IPW_CMD_ENABLE, NULL, 0);
+ if (error != 0)
+ goto fail;
+
+ return;
+ fail:
+ printf("%s: association failed (error=%d)\n", sc->sc_dev.dv_xname,
+ error);
+ ieee80211_begin_scan(&ic->ic_if);
+}
+
int
ipw_config(struct ipw_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
struct ifnet *ifp = &ic->ic_if;
- struct ipw_security security;
- struct ieee80211_key *k;
- struct ipw_wep_key wepkey;
- struct ipw_scan_options options;
struct ipw_configuration config;
uint32_t data;
- int error, i;
+ int error;
switch (ic->ic_opmode) {
case IEEE80211_M_STA:
@@ -1730,7 +1876,7 @@ ipw_config(struct ipw_softc *sc)
return error;
config.flags = htole32(IPW_CFG_BSS_MASK | IPW_CFG_IBSS_MASK |
- IPW_CFG_PREAMBLE_AUTO | IPW_CFG_802_1x_ENABLE);
+ IPW_CFG_PREAMBLE_AUTO | IPW_CFG_802_1X_ENABLE);
#ifndef IEEE80211_STA_ONLY
if (ic->ic_opmode == IEEE80211_M_IBSS)
config.flags |= htole32(IPW_CFG_IBSS_AUTO_START);
@@ -1744,6 +1890,18 @@ ipw_config(struct ipw_softc *sc)
if (error != 0)
return error;
+ data = htole32(ic->ic_rtsthreshold);
+ DPRINTF(("Setting RTS threshold to %u\n", letoh32(data)));
+ error = ipw_cmd(sc, IPW_CMD_SET_RTS_THRESHOLD, &data, sizeof data);
+ if (error != 0)
+ return error;
+
+ data = htole32(ic->ic_fragthreshold);
+ DPRINTF(("Setting frag threshold to %u\n", letoh32(data)));
+ error = ipw_cmd(sc, IPW_CMD_SET_FRAG_THRESHOLD, &data, sizeof data);
+ if (error != 0)
+ return error;
+
data = htole32(0x3); /* 1, 2 */
DPRINTF(("Setting basic tx rates to 0x%x\n", letoh32(data)));
error = ipw_cmd(sc, IPW_CMD_SET_BASIC_TX_RATES, &data, sizeof data);
@@ -1756,6 +1914,12 @@ ipw_config(struct ipw_softc *sc)
if (error != 0)
return error;
+ data = htole32(0xf); /* 1, 2, 5.5, 11 */
+ DPRINTF(("Setting MSDU tx rates to 0x%x\n", letoh32(data)));
+ error = ipw_cmd(sc, IPW_CMD_SET_MSDU_TX_RATES, &data, sizeof data);
+ if (error != 0)
+ return error;
+
data = htole32(IPW_POWER_MODE_CAM);
DPRINTF(("Setting power mode to %u\n", letoh32(data)));
error = ipw_cmd(sc, IPW_CMD_SET_POWER_MODE, &data, sizeof data);
@@ -1770,92 +1934,7 @@ ipw_config(struct ipw_softc *sc)
sizeof data);
if (error != 0)
return error;
- }
-#endif
-
- data = htole32(ic->ic_rtsthreshold);
- DPRINTF(("Setting RTS threshold to %u\n", letoh32(data)));
- error = ipw_cmd(sc, IPW_CMD_SET_RTS_THRESHOLD, &data, sizeof data);
- if (error != 0)
- return error;
-
- data = htole32(ic->ic_fragthreshold);
- DPRINTF(("Setting frag threshold to %u\n", letoh32(data)));
- error = ipw_cmd(sc, IPW_CMD_SET_FRAG_THRESHOLD, &data, sizeof data);
- if (error != 0)
- return error;
-
-#ifdef IPW_DEBUG
- if (ipw_debug > 0) {
- printf("Setting ESSID to ");
- ieee80211_print_essid(ic->ic_des_essid, ic->ic_des_esslen);
- printf("\n");
- }
-#endif
- error = ipw_cmd(sc, IPW_CMD_SET_ESSID, ic->ic_des_essid,
- ic->ic_des_esslen);
- if (error != 0)
- return error;
-
- /* no mandatory BSSID */
- DPRINTF(("Setting mandatory BSSID to null\n"));
- error = ipw_cmd(sc, IPW_CMD_SET_MANDATORY_BSSID, NULL, 0);
- if (error != 0)
- return error;
-
- if (ic->ic_flags & IEEE80211_F_DESBSSID) {
- DPRINTF(("Setting adapter BSSID to %s\n",
- ether_sprintf(ic->ic_des_bssid)));
- error = ipw_cmd(sc, IPW_CMD_SET_DESIRED_BSSID,
- ic->ic_des_bssid, IEEE80211_ADDR_LEN);
- if (error != 0)
- return error;
- }
-
- bzero(&security, sizeof security);
- security.authmode = IPW_AUTH_OPEN; /* XXX shared mode */
- security.ciphers = htole32(IPW_CIPHER_NONE);
- DPRINTF(("Setting authmode to %u\n", security.authmode));
- error = ipw_cmd(sc, IPW_CMD_SET_SECURITY_INFORMATION, &security,
- sizeof security);
- 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++) {
- if (k->k_len == 0)
- continue;
-
- 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 = ipw_cmd(sc, IPW_CMD_SET_WEP_KEY, &wepkey,
- sizeof wepkey);
- if (error != 0)
- return error;
- }
-
- data = htole32(ic->ic_wep_txkey);
- DPRINTF(("Setting wep tx key index to %u\n", letoh32(data)));
- error = ipw_cmd(sc, IPW_CMD_SET_WEP_KEY_INDEX, &data,
- sizeof data);
- if (error != 0)
- return error;
- }
-
- data = htole32((ic->ic_flags & IEEE80211_F_WEPON) ? IPW_WEPON : 0);
- DPRINTF(("Setting wep flags to 0x%x\n", letoh32(data)));
- error = ipw_cmd(sc, IPW_CMD_SET_WEP_FLAGS, &data, sizeof data);
- if (error != 0)
- return error;
-#ifndef IEEE80211_STA_ONLY
- if (ic->ic_opmode == IEEE80211_M_IBSS ||
- ic->ic_opmode == IEEE80211_M_HOSTAP) {
data = htole32(ic->ic_lintval);
DPRINTF(("Setting beacon interval to %u\n", letoh32(data)));
error = ipw_cmd(sc, IPW_CMD_SET_BEACON_INTERVAL, &data,
@@ -1864,23 +1943,14 @@ ipw_config(struct ipw_softc *sc)
return error;
}
#endif
-
- options.flags = htole32(0);
- options.channels = htole32(0x3fff); /* scan channels 1-14 */
- DPRINTF(("Setting scan options to 0x%x\n", letoh32(options.flags)));
- error = ipw_cmd(sc, IPW_CMD_SET_SCAN_OPTIONS, &options, sizeof options);
- if (error != 0)
- return error;
-
- /* finally, enable adapter (start scanning for an access point) */
- DPRINTF(("Enabling adapter\n"));
- return ipw_cmd(sc, IPW_CMD_ENABLE, NULL, 0);
+ return 0;
}
int
ipw_init(struct ifnet *ifp)
{
struct ipw_softc *sc = ifp->if_softc;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ipw_firmware fw;
int error;
@@ -1941,14 +2011,19 @@ ipw_init(struct ifnet *ifp)
sc->sc_dev.dv_xname);
goto fail2;
}
+
ifp->if_flags &= ~IFF_OACTIVE;
ifp->if_flags |= IFF_RUNNING;
+ if (ic->ic_opmode != IEEE80211_M_MONITOR)
+ ieee80211_begin_scan(ifp);
+ else
+ ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
+
return 0;
fail2: free(fw.data, M_DEVBUF);
fail1: ipw_stop(ifp, 0);
-
return error;
}
diff --git a/sys/dev/pci/if_ipwreg.h b/sys/dev/pci/if_ipwreg.h
index 54521f8631b..a048b56b68d 100644
--- a/sys/dev/pci/if_ipwreg.h
+++ b/sys/dev/pci/if_ipwreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ipwreg.h,v 1.14 2006/02/26 19:14:40 damien Exp $ */
+/* $OpenBSD: if_ipwreg.h,v 1.15 2008/08/28 14:40:44 damien Exp $ */
/*-
* Copyright (c) 2004-2006
@@ -182,7 +182,7 @@ struct ipw_cmd {
#define IPW_CMD_SET_BASIC_TX_RATES 19
#define IPW_CMD_SET_WEP_KEY 20
#define IPW_CMD_SET_WEP_KEY_INDEX 25
-#define IPW_CMD_SET_WEP_FLAGS 26
+#define IPW_CMD_SET_PRIVACY_FLAGS 26
#define IPW_CMD_ADD_MULTICAST 27
#define IPW_CMD_SET_BEACON_INTERVAL 29
#define IPW_CMD_SET_TX_POWER_INDEX 36
@@ -192,7 +192,9 @@ struct ipw_cmd {
#define IPW_CMD_SET_SCAN_OPTIONS 46
#define IPW_CMD_PREPARE_POWER_DOWN 58
#define IPW_CMD_DISABLE_PHY 61
+#define IPW_CMD_SET_MSDU_TX_RATES 62
#define IPW_CMD_SET_SECURITY_INFORMATION 67
+#define IPW_CMD_SET_ASSOC_REQ 69
uint32_t subtype;
uint32_t seq;
uint32_t len;
@@ -210,8 +212,8 @@ struct ipw_cmd {
#define IPW_MODE_IBSS 1
#define IPW_MODE_MONITOR 2
-/* possible flags for command IPW_CMD_SET_WEP_FLAGS */
-#define IPW_WEPON 0x8
+/* possible flags for command IPW_CMD_SET_PRIVACY_FLAGS */
+#define IPW_PRIVACYON 0x8
/* structure for command IPW_CMD_SET_WEP_KEY */
struct ipw_wep_key {
@@ -225,6 +227,8 @@ struct ipw_security {
uint32_t ciphers;
#define IPW_CIPHER_NONE 0x00000001
#define IPW_CIPHER_WEP40 0x00000002
+#define IPW_CIPHER_TKIP 0x00000004
+#define IPW_CIPHER_CCMP 0x00000010
#define IPW_CIPHER_WEP104 0x00000020
uint16_t reserved1;
uint8_t authmode;
@@ -237,6 +241,7 @@ struct ipw_security {
struct ipw_scan_options {
uint32_t flags;
#define IPW_SCAN_DO_NOT_ASSOCIATE 0x00000001
+#define IPW_SCAN_MIXED_CELL 0x00000002
#define IPW_SCAN_PASSIVE 0x00000008
uint32_t channels;
} __packed;
@@ -247,14 +252,25 @@ struct ipw_configuration {
#define IPW_CFG_PROMISCUOUS 0x00000004
#define IPW_CFG_PREAMBLE_AUTO 0x00000010
#define IPW_CFG_IBSS_AUTO_START 0x00000020
-#define IPW_CFG_802_1x_ENABLE 0x00004000
+#define IPW_CFG_802_1X_ENABLE 0x00004000
#define IPW_CFG_BSS_MASK 0x00008000
#define IPW_CFG_IBSS_MASK 0x00010000
uint32_t bss_chan;
uint32_t ibss_chan;
} __packed;
-/* EEPROM = Electrically Erasable Programmable Read-Only Memory */
+/* structure for command IPW_CMD_SET_ASSOC_REQ */
+struct ipw_assoc_req {
+ uint16_t flags;
+#define IPW_ASSOC_CAPINFO 0x0001
+#define IPW_ASSOC_LINTVAL 0x0002
+#define IPW_ASSOC_BSSID 0x0004 /* reassoc */
+ uint16_t capinfo;
+ uint16_t lintval;
+ uint8_t bssid[IEEE80211_ADDR_LEN];
+ uint32_t optie_len;
+ uint8_t optie[384];
+} __packed;
#define IPW_MEM_EEPROM_CTL 0x00300040
@@ -324,5 +340,5 @@ struct ipw_configuration {
#define IPW_EEPROM_CTL(sc, val) do { \
MEM_WRITE_4((sc), IPW_MEM_EEPROM_CTL, (val)); \
DELAY(IPW_EEPROM_DELAY); \
-} while (0)
+} while (/* CONSTCOND */0)