summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2006-08-01 12:43:57 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2006-08-01 12:43:57 +0000
commit22c8606ccdffebd21ec62450def95cdae067486c (patch)
tree80589b78305e1649462485a09ae74969ab5ad0e5
parent96d51816bd7e4ce52143f3dff1c709355bd8ba9e (diff)
- improve scan code to support scanning of 802.11a channels
- fix protection mode - fix association to APs hiding their SSID + various cosmetic tweaks while i'm here
-rw-r--r--sys/dev/pci/if_wpi.c116
-rw-r--r--sys/dev/pci/if_wpireg.h23
-rw-r--r--sys/dev/pci/if_wpivar.h6
3 files changed, 100 insertions, 45 deletions
diff --git a/sys/dev/pci/if_wpi.c b/sys/dev/pci/if_wpi.c
index 7772e78f522..f41f15c4316 100644
--- a/sys/dev/pci/if_wpi.c
+++ b/sys/dev/pci/if_wpi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_wpi.c,v 1.21 2006/06/17 19:07:19 damien Exp $ */
+/* $OpenBSD: if_wpi.c,v 1.22 2006/08/01 12:43:56 damien Exp $ */
/*-
* Copyright (c) 2006
@@ -72,10 +72,9 @@ const struct pci_matchid wpi_devices[] = {
/*
* Supported rates for 802.11a/b/g modes (in 500Kbps unit).
*/
-#ifdef notyet
static const struct ieee80211_rateset wpi_rateset_11a =
{ 8, { 12, 18, 24, 36, 48, 72, 96, 108 } };
-#endif
+
static const struct ieee80211_rateset wpi_rateset_11b =
{ 4, { 2, 4, 11, 22 } };
@@ -137,7 +136,7 @@ void wpi_set_led(struct wpi_softc *, uint8_t, uint8_t, uint8_t);
void wpi_enable_tsf(struct wpi_softc *, struct ieee80211_node *);
int wpi_setup_beacon(struct wpi_softc *, struct ieee80211_node *);
int wpi_auth(struct wpi_softc *);
-int wpi_scan(struct wpi_softc *);
+int wpi_scan(struct wpi_softc *, uint16_t);
int wpi_config(struct wpi_softc *);
void wpi_stop_master(struct wpi_softc *);
int wpi_power_up(struct wpi_softc *);
@@ -284,7 +283,6 @@ wpi_attach(struct device *parent, struct device *self, void *aux)
wpi_read_eeprom(sc);
printf(", address %s\n", ether_sprintf(ic->ic_myaddr));
-#ifdef notyet
/* set supported .11a rates */
ic->ic_sup_rates[IEEE80211_MODE_11A] = wpi_rateset_11a;
@@ -299,7 +297,6 @@ wpi_attach(struct device *parent, struct device *self, void *aux)
ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
}
-#endif
/* set supported .11b and .11g rates */
ic->ic_sup_rates[IEEE80211_MODE_11B] = wpi_rateset_11b;
@@ -344,7 +341,7 @@ wpi_attach(struct device *parent, struct device *self, void *aux)
#if NBPFILTER > 0
bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO,
- sizeof (struct ieee80211_frame) + 64);
+ sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN);
sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
@@ -776,7 +773,7 @@ wpi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
/* make the link LED blink while we're scanning */
wpi_set_led(sc, WPI_LED_LINK, 20, 2);
- if ((error = wpi_scan(sc)) != 0) {
+ if ((error = wpi_scan(sc, IEEE80211_CHAN_G)) != 0) {
printf("%s: could not initiate scan\n",
sc->sc_dev.dv_xname);
return error;
@@ -1340,10 +1337,25 @@ wpi_notif_intr(struct wpi_softc *sc)
break;
}
case WPI_STOP_SCAN:
- DPRINTF(("scan finished\n"));
+ {
+ struct wpi_stop_scan *scan =
+ (struct wpi_stop_scan *)(desc + 1);
+
+ DPRINTF(("scan finished nchan=%d status=%d chan=%d\n",
+ scan->nchan, scan->status, scan->chan));
+
+ if (scan->status == 1 && scan->chan <= 14) {
+ /*
+ * We just finished scanning 802.11g channels,
+ * start scanning 802.11a ones.
+ */
+ if (wpi_scan(sc, IEEE80211_CHAN_A) == 0)
+ break;
+ }
ieee80211_end_scan(ifp);
break;
}
+ }
sc->rxq.cur = (sc->rxq.cur + 1) % WPI_RX_RING_COUNT;
}
@@ -1372,6 +1384,7 @@ wpi_intr(void *arg)
WPI_WRITE(sc, WPI_INTR, r);
if (r & (WPI_SW_ERROR | WPI_HW_ERROR)) {
+ /* SYSTEM FAILURE, SYSTEM FAILURE */
printf("%s: fatal firmware error\n", sc->sc_dev.dv_xname);
ifp->if_flags &= ~IFF_UP;
wpi_stop(ifp, 1);
@@ -1493,17 +1506,20 @@ wpi_tx_data(struct wpi_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
tx = (struct wpi_cmd_data *)cmd->data;
tx->flags = 0;
- if (!IEEE80211_IS_MULTICAST(wh->i_addr1))
+ if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
+ tx->id = WPI_ID_BSS;
tx->flags |= htole32(WPI_TX_NEED_ACK);
- else if (m0->m_pkthdr.len + IEEE80211_CRC_LEN > ic->ic_rtsthreshold ||
- ((ic->ic_flags & IEEE80211_F_USEPROT) && WPI_RATE_IS_OFDM(rate)))
- tx->flags |= htole32(WPI_TX_NEED_RTS | WPI_TX_FULL_TXOP);
- tx->flags |= htole32(WPI_TX_AUTO_SEQ);
+ if (m0->m_pkthdr.len + IEEE80211_CRC_LEN >
+ ic->ic_rtsthreshold || (WPI_RATE_IS_OFDM(rate) &&
+ (ic->ic_flags & IEEE80211_F_USEPROT))) {
+ tx->flags |= htole32(WPI_TX_NEED_RTS |
+ WPI_TX_FULL_TXOP);
+ }
+ } else
+ tx->id = WPI_ID_BROADCAST;
- /* retrieve destination node's id */
- tx->id = IEEE80211_IS_MULTICAST(wh->i_addr1) ? WPI_ID_BROADCAST :
- WPI_ID_BSS;
+ tx->flags |= htole32(WPI_TX_AUTO_SEQ);
if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
IEEE80211_FC0_TYPE_MGT) {
@@ -2036,7 +2052,7 @@ wpi_auth(struct wpi_softc *sc)
* into a mbuf instead of using the pre-allocated set of commands.
*/
int
-wpi_scan(struct wpi_softc *sc)
+wpi_scan(struct wpi_softc *sc, uint16_t flags)
{
struct ieee80211com *ic = &sc->sc_ic;
struct wpi_tx_ring *ring = &sc->cmdq;
@@ -2046,11 +2062,11 @@ wpi_scan(struct wpi_softc *sc)
struct wpi_scan_hdr *hdr;
struct wpi_scan_chan *chan;
struct ieee80211_frame *wh;
- struct ieee80211_node *ni = ic->ic_bss;
struct ieee80211_rateset *rs;
+ struct ieee80211_channel *c;
enum ieee80211_phymode mode;
uint8_t *frm;
- int i, pktlen, error;
+ int pktlen, error;
desc = &ring->desc[ring->cur];
data = &ring->data[ring->cur];
@@ -2080,16 +2096,29 @@ wpi_scan(struct wpi_softc *sc)
hdr = (struct wpi_scan_hdr *)cmd->data;
bzero(hdr, sizeof (struct wpi_scan_hdr));
hdr->first = 1;
- hdr->nchan = 14;
- hdr->len = hdr->nchan * sizeof (struct wpi_scan_chan);
- hdr->quiet = htole16(5);
- hdr->threshold = htole16(1);
- hdr->filter = htole32(5); /* XXX */
- hdr->rate = wpi_plcp_signal(2);
+ /*
+ * Move to the next channel if no packets are received within 5 msecs
+ * after sending the probe request (this helps to reduce the duration
+ * of active scans).
+ */
+ hdr->quiet = htole16(5); /* timeout in milliseconds */
+ hdr->threshold = htole16(1); /* min # of packets */
+
+ if (flags & IEEE80211_CHAN_A) {
+ hdr->band = htole16(WPI_SCAN_5GHZ);
+ /* send probe requests at 6Mbps */
+ hdr->rate = wpi_plcp_signal(12);
+ } else {
+ hdr->flags = htole32(WPI_CONFIG_24GHZ | WPI_CONFIG_AUTO);
+ /* send probe requests at 1Mbps */
+ hdr->rate = wpi_plcp_signal(2);
+ }
hdr->id = WPI_ID_BROADCAST;
hdr->mask = htole32(0xffffffff);
- hdr->esslen = ni->ni_esslen;
- bcopy(ni->ni_essid, hdr->essid, ni->ni_esslen);
+ hdr->magic1 = htole32(1 << 13);
+
+ hdr->esslen = ic->ic_des_esslen;
+ bcopy(ic->ic_des_essid, hdr->essid, ic->ic_des_esslen);
/*
* Build a probe request frame. Most of the following code is a
@@ -2108,7 +2137,7 @@ wpi_scan(struct wpi_softc *sc)
frm = (uint8_t *)(wh + 1);
/* add essid IE */
- frm = ieee80211_add_ssid(frm, ni->ni_essid, ni->ni_esslen);
+ frm = ieee80211_add_ssid(frm, ic->ic_des_essid, ic->ic_des_esslen);
mode = ieee80211_chan2mode(ic, ic->ic_ibss_chan);
rs = &ic->ic_sup_rates[mode];
@@ -2122,22 +2151,34 @@ wpi_scan(struct wpi_softc *sc)
/* setup length of probe request */
hdr->length = htole16(frm - (uint8_t *)wh);
- /* XXX: align on a 4-byte boundary? */
chan = (struct wpi_scan_chan *)frm;
- for (i = 1; i <= hdr->nchan; i++, chan++) {
- chan->flags = 3;
- chan->chan = i;
+ for (c = &ic->ic_channels[1];
+ c <= &ic->ic_channels[IEEE80211_CHAN_MAX]; c++) {
+ if ((c->ic_flags & flags) != flags)
+ continue;
+
+ chan->chan = ieee80211_chan2ieee(ic, c);
+ chan->flags = (c->ic_flags & IEEE80211_CHAN_PASSIVE) ?
+ 0 : WPI_CHAN_ACTIVE;
chan->magic = htole16(0x62ab);
- chan->active = htole16(20);
- chan->passive = htole16(120);
+ if (IEEE80211_IS_CHAN_5GHZ(c)) {
+ chan->active = htole16(10);
+ chan->passive = htole16(110);
+ } else {
+ chan->active = htole16(20);
+ chan->passive = htole16(120);
+ }
+ hdr->nchan++;
+ chan++;
frm += sizeof (struct wpi_scan_chan);
}
+ hdr->len = hdr->nchan * sizeof (struct wpi_scan_chan);
pktlen = frm - mtod(data->m, uint8_t *);
- error = bus_dmamap_load(sc->sc_dmat, data->map, cmd, pktlen,
- NULL, BUS_DMA_NOWAIT);
+ error = bus_dmamap_load(sc->sc_dmat, data->map, cmd, pktlen, NULL,
+ BUS_DMA_NOWAIT);
if (error != 0) {
printf("%s: could not map scan command\n",
sc->sc_dev.dv_xname);
@@ -2493,6 +2534,7 @@ wpi_init(struct ifnet *ifp)
/* ..and wait at most one second for adapter to initialize */
if ((error = tsleep(sc, PCATCH, "wpiinit", hz)) != 0) {
+ /* this isn't what was supposed to happen.. */
printf("%s: timeout waiting for adapter to initialize\n",
sc->sc_dev.dv_xname);
goto fail1;
diff --git a/sys/dev/pci/if_wpireg.h b/sys/dev/pci/if_wpireg.h
index b0acfe5bfca..84e19fe6cb9 100644
--- a/sys/dev/pci/if_wpireg.h
+++ b/sys/dev/pci/if_wpireg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_wpireg.h,v 1.9 2006/06/17 19:07:19 damien Exp $ */
+/* $OpenBSD: if_wpireg.h,v 1.10 2006/08/01 12:43:56 damien Exp $ */
/*-
* Copyright (c) 2006
@@ -440,9 +440,12 @@ struct wpi_scan_hdr {
uint8_t nchan;
uint16_t quiet;
uint16_t threshold;
- uint32_t reserved2[3];
+ uint16_t band;
+#define WPI_SCAN_5GHZ 1
+
+ uint16_t reserved2[5];
+ uint32_t flags;
uint32_t filter;
- uint32_t reserved3;
uint16_t length;
uint16_t reserved4;
uint32_t magic1;
@@ -462,10 +465,12 @@ struct wpi_scan_hdr {
struct wpi_scan_chan {
uint8_t flags;
+#define WPI_CHAN_ACTIVE 3
+
uint8_t chan;
uint16_t magic; /* XXX */
- uint16_t active; /* dwell time */
- uint16_t passive; /* dwell time */
+ uint16_t active; /* msecs */
+ uint16_t passive; /* msecs */
} __packed;
/* structure for WPI_CMD_BLUETOOTH */
@@ -519,6 +524,14 @@ struct wpi_start_scan {
uint32_t status;
} __packed;
+/* structure for WPI_STOP_SCAN notification */
+struct wpi_stop_scan {
+ uint8_t nchan;
+ uint8_t status;
+ uint8_t reserved;
+ uint8_t chan;
+ uint64_t tsf;
+} __packed;
#define WPI_EEPROM_MAC 0x015
#define WPI_EEPROM_REVISION 0x035
diff --git a/sys/dev/pci/if_wpivar.h b/sys/dev/pci/if_wpivar.h
index 8f3324e90bb..3aa2b19e588 100644
--- a/sys/dev/pci/if_wpivar.h
+++ b/sys/dev/pci/if_wpivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_wpivar.h,v 1.7 2006/06/17 19:07:19 damien Exp $ */
+/* $OpenBSD: if_wpivar.h,v 1.8 2006/08/01 12:43:56 damien Exp $ */
/*-
* Copyright (c) 2006
@@ -139,14 +139,14 @@ struct wpi_softc {
union {
struct wpi_rx_radiotap_header th;
- uint8_t pad[64];
+ uint8_t pad[IEEE80211_RADIOTAP_HDRLEN];
} sc_rxtapu;
#define sc_rxtap sc_rxtapu.th
int sc_rxtap_len;
union {
struct wpi_tx_radiotap_header th;
- uint8_t pad[64];
+ uint8_t pad[IEEE80211_RADIOTAP_HDRLEN];
} sc_txtapu;
#define sc_txtap sc_txtapu.th
int sc_txtap_len;