summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/pci/if_ipw.c58
-rw-r--r--sys/dev/pci/if_ipwreg.h22
2 files changed, 78 insertions, 2 deletions
diff --git a/sys/dev/pci/if_ipw.c b/sys/dev/pci/if_ipw.c
index ccf77ce3f72..3a0784b7eea 100644
--- a/sys/dev/pci/if_ipw.c
+++ b/sys/dev/pci/if_ipw.c
@@ -1,4 +1,4 @@
-/* $Id: if_ipw.c,v 1.31 2004/12/05 19:39:22 damien Exp $ */
+/* $Id: if_ipw.c,v 1.32 2004/12/05 19:54:03 damien Exp $ */
/*-
* Copyright (c) 2004
@@ -86,6 +86,7 @@ int ipw_media_change(struct ifnet *);
void ipw_media_status(struct ifnet *, struct ifmediareq *);
int ipw_newstate(struct ieee80211com *, enum ieee80211_state, int);
u_int16_t ipw_read_prom_word(struct ipw_softc *, u_int8_t);
+void ipw_scan_result(struct ipw_softc *);
void ipw_command_intr(struct ipw_softc *, struct ipw_soft_buf *);
void ipw_newstate_intr(struct ipw_softc *, struct ipw_soft_buf *);
void ipw_data_intr(struct ipw_softc *, struct ipw_status *,
@@ -735,6 +736,57 @@ ipw_read_prom_word(struct ipw_softc *sc, u_int8_t addr)
}
void
+ipw_scan_result(struct ipw_softc *sc)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211_node *ni;
+ u_int32_t i, cnt, off;
+ struct ipw_node ap;
+
+ /* flush previously seen access points */
+ ieee80211_free_allnodes(ic);
+
+ cnt = ipw_read_table1(sc, IPW_INFO_APS_CNT);
+ off = ipw_read_table1(sc, IPW_INFO_APS_BASE);
+
+ DPRINTF(("Found %u APs\n", cnt));
+
+ for (i = 0; i < cnt; i++) {
+ ipw_read_mem_1(sc, off, (u_int8_t *)&ap, sizeof ap);
+ off += sizeof ap;
+
+#ifdef IPW_DEBUG
+ if (ipw_debug >= 2) {
+ u_char *p = (u_char *)&ap;
+ int j;
+
+ printf("AP%u\n", i);
+ for (j = 0; j < sizeof ap; j++)
+ printf("%02x", *p++);
+ printf("\n");
+ }
+#endif
+
+ ni = ieee80211_lookup_node(ic, ap.bssid,
+ &ic->ic_channels[ap.chan]);
+ if (ni != NULL)
+ continue;
+
+ ni = ieee80211_alloc_node(ic, ap.bssid);
+ if (ni == NULL)
+ return;
+
+ IEEE80211_ADDR_COPY(ni->ni_bssid, ap.bssid);
+ ni->ni_rssi = ap.rssi;
+ ni->ni_intval = letoh16(ap.intval);
+ ni->ni_capinfo = letoh16(ap.capinfo);
+ ni->ni_chan = &ic->ic_channels[ap.chan];
+ ni->ni_esslen = ap.esslen;
+ bcopy(ap.essid, ni->ni_essid, IEEE80211_NWID_LEN);
+ }
+}
+
+void
ipw_command_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf)
{
struct ipw_cmd *cmd;
@@ -775,6 +827,10 @@ ipw_newstate_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf)
ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
break;
+ case IPW_STATE_SCAN_COMPLETE:
+ ipw_scan_result(sc);
+ break;
+
case IPW_STATE_ASSOCIATION_LOST:
ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
break;
diff --git a/sys/dev/pci/if_ipwreg.h b/sys/dev/pci/if_ipwreg.h
index 3db0a39f64c..f25f98ba3bf 100644
--- a/sys/dev/pci/if_ipwreg.h
+++ b/sys/dev/pci/if_ipwreg.h
@@ -1,4 +1,4 @@
-/* $Id: if_ipwreg.h,v 1.8 2004/12/05 19:39:22 damien Exp $ */
+/* $Id: if_ipwreg.h,v 1.9 2004/12/05 19:54:03 damien Exp $ */
/*-
* Copyright (c) 2004
@@ -97,6 +97,8 @@
/* table1 offsets */
#define IPW_INFO_LOCK 480
+#define IPW_INFO_APS_CNT 604
+#define IPW_INFO_APS_BASE 608
#define IPW_INFO_CARD_DISABLED 628
#define IPW_INFO_CURRENT_CHANNEL 756
#define IPW_INFO_CURRENT_TX_RATE 768
@@ -252,6 +254,24 @@ struct ipw_configuration {
u_int32_t ibss_chan;
} __attribute__((__packed__));
+/* element in AP table */
+struct ipw_node {
+ u_int32_t reserved1[2];
+ u_int8_t bssid[IEEE80211_ADDR_LEN];
+ u_int8_t chan;
+ u_int8_t rates;
+ u_int16_t reserved2;
+ u_int16_t capinfo;
+ u_int16_t reserved3;
+ u_int16_t intval;
+ u_int8_t reserved4[28];
+ u_int8_t essid[IEEE80211_NWID_LEN];
+ u_int16_t reserved5;
+ u_int8_t esslen;
+ u_int8_t reserved6[7];
+ u_int8_t rssi;
+} __attribute__((__packed__));
+
/* EEPROM = Electrically Erasable Programmable Read-Only Memory */
#define IPW_MEM_EEPROM_CTL 0x00300040