summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/if_iwi.c78
-rw-r--r--sys/dev/pci/if_iwireg.h20
-rw-r--r--sys/dev/pci/if_iwivar.h6
3 files changed, 92 insertions, 12 deletions
diff --git a/sys/dev/pci/if_iwi.c b/sys/dev/pci/if_iwi.c
index 33cfba47915..7a62f676d88 100644
--- a/sys/dev/pci/if_iwi.c
+++ b/sys/dev/pci/if_iwi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_iwi.c,v 1.48 2005/08/09 04:10:12 mickey Exp $ */
+/* $OpenBSD: if_iwi.c,v 1.49 2005/09/19 20:01:11 damien Exp $ */
/*-
* Copyright (c) 2004, 2005
@@ -102,6 +102,7 @@ void iwi_release(struct iwi_softc *);
int iwi_media_change(struct ifnet *);
void iwi_media_status(struct ifnet *, struct ifmediareq *);
u_int16_t iwi_read_prom_word(struct iwi_softc *, u_int8_t);
+int iwi_find_txnode(struct iwi_softc *, const u_int8_t *);
int iwi_newstate(struct ieee80211com *, enum ieee80211_state, int);
void iwi_frame_intr(struct iwi_softc *, struct iwi_rx_buf *, int,
struct iwi_frame *);
@@ -234,8 +235,9 @@ iwi_attach(struct device *parent, struct device *self, void *aux)
ic->ic_state = IEEE80211_S_INIT;
/* set device capabilities */
- ic->ic_caps = IEEE80211_C_PMGT | IEEE80211_C_WEP | IEEE80211_C_TXPMGT |
- IEEE80211_C_SHPREAMBLE | IEEE80211_C_MONITOR | IEEE80211_C_SCANALL;
+ ic->ic_caps = IEEE80211_C_IBSS | IEEE80211_C_PMGT | IEEE80211_C_WEP |
+ IEEE80211_C_TXPMGT | IEEE80211_C_SHPREAMBLE | IEEE80211_C_MONITOR |
+ IEEE80211_C_SCANALL;
/* read MAC address from EEPROM */
val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 0);
@@ -633,6 +635,37 @@ iwi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
#undef N
}
+/*
+ * This is only used for IBSS mode where the firmware expect an index to an
+ * internal node table instead of a destination address.
+ */
+int
+iwi_find_txnode(struct iwi_softc *sc, const u_int8_t *macaddr)
+{
+ struct iwi_node node;
+ int i;
+
+ for (i = 0; i < sc->nsta; i++)
+ if (IEEE80211_ADDR_EQ(sc->sta[i], macaddr))
+ return i; /* already existing node */
+
+ if (i == IWI_MAX_NODE)
+ return -1; /* no place left in neighbor table */
+
+ /* save this new node in our softc table */
+ IEEE80211_ADDR_COPY(sc->sta[i], macaddr);
+ sc->nsta = i;
+
+ /* write node information into NIC memory */
+ bzero(&node, sizeof node);
+ IEEE80211_ADDR_COPY(node.bssid, macaddr);
+
+ CSR_WRITE_REGION_1(sc, IWI_CSR_NODE_BASE + i * sizeof node,
+ (u_int8_t *)&node, sizeof node);
+
+ return i;
+}
+
int
iwi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
{
@@ -648,9 +681,10 @@ iwi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
break;
case IEEE80211_S_RUN:
- if (ic->ic_opmode == IEEE80211_M_IBSS)
+ if (ic->ic_opmode == IEEE80211_M_IBSS) {
+ sc->nsta = 0; /* flush IBSS nodes */
ieee80211_new_state(ic, IEEE80211_S_AUTH, -1);
- else if (ic->ic_opmode == IEEE80211_M_MONITOR)
+ } else if (ic->ic_opmode == IEEE80211_M_MONITOR)
iwi_set_chan(sc, ic->ic_ibss_chan);
break;
@@ -1077,7 +1111,7 @@ iwi_tx_start(struct ifnet *ifp, struct mbuf *m0, struct ieee80211_node *ni)
struct iwi_tx_buf *buf;
struct iwi_tx_desc *desc;
struct mbuf *mnew;
- int error, i;
+ int error, i, station = 0;
#if NBPFILTER > 0
if (sc->sc_drvbpf != NULL) {
@@ -1104,6 +1138,16 @@ iwi_tx_start(struct ifnet *ifp, struct mbuf *m0, struct ieee80211_node *ni)
m_copydata(m0, 0, sizeof (struct ieee80211_frame), (caddr_t)&desc->wh);
m_adj(m0, sizeof (struct ieee80211_frame));
+ if (ic->ic_opmode == IEEE80211_M_IBSS) {
+ station = iwi_find_txnode(sc, desc->wh.i_addr1);
+ if (station == -1) {
+ m_freem(m0);
+ ieee80211_release_node(ic, ni);
+ ifp->if_oerrors++;
+ return 0;
+ }
+ }
+
error = bus_dmamap_load_mbuf(sc->sc_dmat, buf->map, m0, BUS_DMA_NOWAIT);
if (error != 0 && error != EFBIG) {
printf("%s: could not map mbuf (error %d)\n",
@@ -1150,6 +1194,7 @@ iwi_tx_start(struct ifnet *ifp, struct mbuf *m0, struct ieee80211_node *ni)
desc->hdr.flags = IWI_HDR_FLAG_IRQ;
desc->cmd = IWI_DATA_CMD_TX;
desc->len = htole16(m0->m_pkthdr.len);
+ desc->station = station;
desc->flags = 0;
if (!IEEE80211_IS_MULTICAST(desc->wh.i_addr1))
@@ -1203,7 +1248,7 @@ iwi_start(struct ifnet *ifp)
if (m0 == NULL)
break;
- if (sc->tx_queued >= IWI_TX_RING_SIZE - 4) {
+ if (sc->tx_queued >= IWI_TX_RING_SIZE - 8) {
IF_PREPEND(&ifp->if_snd, m0);
ifp->if_flags |= IFF_OACTIVE;
break;
@@ -1724,6 +1769,22 @@ iwi_config(struct iwi_softc *sc)
if (error != 0)
return error;
+ /* if we have a desired ESSID, set it now */
+ if (ic->ic_des_esslen != 0) {
+#ifdef IWI_DEBUG
+ if (iwi_debug > 0) {
+ printf("Setting desired ESSID to ");
+ ieee80211_print_essid(ic->ic_des_essid,
+ ic->ic_des_esslen);
+ printf("\n");
+ }
+#endif
+ error = iwi_cmd(sc, IWI_CMD_SET_ESSID, ic->ic_des_essid,
+ ic->ic_des_esslen, 0);
+ if (error != 0)
+ 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);
@@ -1778,7 +1839,8 @@ iwi_scan(struct iwi_softc *sc)
int i, count;
bzero(&scan, sizeof scan);
- scan.type = IWI_SCAN_TYPE_BROADCAST;
+ scan.type = (ic->ic_des_esslen != 0) ? IWI_SCAN_TYPE_BDIRECTED :
+ IWI_SCAN_TYPE_BROADCAST;
scan.intval = htole16(40);
p = scan.channels;
diff --git a/sys/dev/pci/if_iwireg.h b/sys/dev/pci/if_iwireg.h
index 6216778aaf7..e347ed75c55 100644
--- a/sys/dev/pci/if_iwireg.h
+++ b/sys/dev/pci/if_iwireg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_iwireg.h,v 1.15 2005/05/22 16:05:47 damien Exp $ */
+/* $OpenBSD: if_iwireg.h,v 1.16 2005/09/19 20:01:12 damien Exp $ */
/*-
* Copyright (c) 2004, 2005
@@ -59,6 +59,7 @@
#define IWI_CSR_RX_BASE 0x0500
#define IWI_CSR_TABLE0_SIZE 0x0700
#define IWI_CSR_TABLE0_BASE 0x0704
+#define IWI_CSR_NODE_BASE 0x0c0c
#define IWI_CSR_CURRENT_TX_RATE IWI_CSR_TABLE0_BASE
#define IWI_CSR_CMD_WRITE_INDEX 0x0f80
#define IWI_CSR_TX1_WRITE_INDEX 0x0f84
@@ -209,7 +210,9 @@ struct iwi_frame {
/* header for transmission */
struct iwi_tx_desc {
struct iwi_hdr hdr;
- u_int32_t reserved1[2];
+ u_int32_t reserved1;
+ u_int8_t station;
+ u_int8_t reserved2[3];
u_int8_t cmd;
#define IWI_DATA_CMD_TX 0x0b
u_int8_t seq;
@@ -224,7 +227,7 @@ struct iwi_tx_desc {
u_int8_t wepkey[IEEE80211_KEYBUF_SIZE];
u_int8_t rate;
u_int8_t antenna;
- u_int8_t reserved2[10];
+ u_int8_t reserved3[10];
struct ieee80211_qosframe_addr4 wh;
u_int32_t iv[2];
@@ -259,6 +262,12 @@ struct iwi_cmd_desc {
u_int8_t data[120];
} __packed;
+/* node information (IBSS) */
+struct iwi_node {
+ u_int8_t bssid[IEEE80211_ADDR_LEN];
+ u_int8_t reserved[2];
+} __packed;
+
/* constants for 'mode' fields */
#define IWI_MODE_11A 0
#define IWI_MODE_11B 1
@@ -319,7 +328,9 @@ struct iwi_associate {
struct iwi_scan {
u_int8_t type;
#define IWI_SCAN_TYPE_PASSIVE 1
+#define IWI_SCAN_TYPE_DIRECTED 2
#define IWI_SCAN_TYPE_BROADCAST 3
+#define IWI_SCAN_TYPE_BDIRECTED 4
u_int16_t intval;
u_int8_t channels[54];
#define IWI_CHAN_5GHZ (0 << 6)
@@ -402,6 +413,9 @@ struct iwi_wep_key {
#define CSR_WRITE_4(sc, reg, val) \
bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (reg), (val))
+#define CSR_WRITE_REGION_1(sc, offset, datap, count) \
+ bus_space_write_region_1((sc)->sc_st, (sc)->sc_sh, (offset), \
+ (datap), (count))
/*
* indirect memory space access macros
*/
diff --git a/sys/dev/pci/if_iwivar.h b/sys/dev/pci/if_iwivar.h
index 1a674530aa8..981fbcd828a 100644
--- a/sys/dev/pci/if_iwivar.h
+++ b/sys/dev/pci/if_iwivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_iwivar.h,v 1.11 2005/07/07 07:55:19 kevlo Exp $ */
+/* $OpenBSD: if_iwivar.h,v 1.12 2005/09/19 20:01:12 damien Exp $ */
/*-
* Copyright (c) 2004, 2005
@@ -93,6 +93,10 @@ struct iwi_softc {
int rx_cur;
+#define IWI_MAX_NODE 32
+ u_int8_t sta[IWI_MAX_NODE][IEEE80211_ADDR_LEN];
+ u_int8_t nsta;
+
bus_space_tag_t sc_st;
bus_space_handle_t sc_sh;
void *sc_ih;