diff options
author | Damien Bergamini <damien@cvs.openbsd.org> | 2005-09-19 20:01:13 +0000 |
---|---|---|
committer | Damien Bergamini <damien@cvs.openbsd.org> | 2005-09-19 20:01:13 +0000 |
commit | 4f304aec0bf1afc18f8ace1583aeb99017d8542f (patch) | |
tree | 0487194277434d040c95c9d8e20c628ca89e2ef0 /sys/dev | |
parent | dc552528f4605adef5476d4f205e85958463ceae (diff) |
o Add initial bits for IBSS support.
o Fix association with APs not broadcasting their SSIDs.
o Don't send anything if there is less than eight free slots in Tx ring.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/if_iwi.c | 78 | ||||
-rw-r--r-- | sys/dev/pci/if_iwireg.h | 20 | ||||
-rw-r--r-- | sys/dev/pci/if_iwivar.h | 6 |
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; |