diff options
author | Damien Bergamini <damien@cvs.openbsd.org> | 2007-09-11 18:52:33 +0000 |
---|---|---|
committer | Damien Bergamini <damien@cvs.openbsd.org> | 2007-09-11 18:52:33 +0000 |
commit | f20a0b6afbcd69672d1e54410a4745f23cf93a98 (patch) | |
tree | 4bb3ef22b43f8a5e0c1fef6bae89b056239f9dc6 | |
parent | 77f718ed0105ea599f5b32134e45a0161dedc979 (diff) |
- add callbacks for setting EDCA parameters and pairwise crypto keys.
- tweaks to make it look more like iwn(4).
-rw-r--r-- | sys/dev/pci/if_wpi.c | 156 | ||||
-rw-r--r-- | sys/dev/pci/if_wpireg.h | 122 | ||||
-rw-r--r-- | sys/dev/pci/if_wpivar.h | 5 |
3 files changed, 176 insertions, 107 deletions
diff --git a/sys/dev/pci/if_wpi.c b/sys/dev/pci/if_wpi.c index e577030cd57..842700696a2 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.55 2007/09/11 18:06:11 damien Exp $ */ +/* $OpenBSD: if_wpi.c,v 1.56 2007/09/11 18:52:32 damien Exp $ */ /*- * Copyright (c) 2006, 2007 @@ -72,6 +72,8 @@ static const struct pci_matchid wpi_devices[] = { int wpi_match(struct device *, void *, void *); void wpi_attach(struct device *, struct device *, void *); +void wpi_sensor_attach(struct wpi_softc *); +void wpi_radiotap_attach(struct wpi_softc *); void wpi_power(int, void *); int wpi_dma_contig_alloc(bus_dma_tag_t, struct wpi_dma_info *, void **, bus_size_t, bus_size_t, int); @@ -125,6 +127,9 @@ void wpi_watchdog(struct ifnet *); int wpi_ioctl(struct ifnet *, u_long, caddr_t); int wpi_cmd(struct wpi_softc *, int, const void *, int, int); int wpi_mrr_setup(struct wpi_softc *); +int wpi_set_key(struct ieee80211com *, struct ieee80211_node *, + const struct ieee80211_key *); +void wpi_updateedca(struct ieee80211com *); 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_set_txpower(struct wpi_softc *, @@ -176,7 +181,7 @@ wpi_attach(struct device *parent, struct device *self, void *aux) bus_space_handle_t memh; pci_intr_handle_t ih; pcireg_t data; - int ac, error; + int i, error; sc->sc_pct = pa->pa_pc; sc->sc_pcitag = pa->pa_tag; @@ -244,25 +249,19 @@ wpi_attach(struct device *parent, struct device *self, void *aux) goto fail2; } - for (ac = 0; ac < 4; ac++) { - error = wpi_alloc_tx_ring(sc, &sc->txq[ac], WPI_TX_RING_COUNT, - ac); + for (i = 0; i < WPI_NTXQUEUES; i++) { + struct wpi_tx_ring *txq = &sc->txq[i]; + error = wpi_alloc_tx_ring(sc, txq, WPI_TX_RING_COUNT, i); if (error != 0) { - printf(": could not allocate Tx ring %d\n", ac); + printf(": could not allocate Tx ring %d\n", i); goto fail3; } } - error = wpi_alloc_tx_ring(sc, &sc->cmdq, WPI_CMD_RING_COUNT, 4); - if (error != 0) { - printf(": could not allocate command ring\n"); - goto fail3; - } - error = wpi_alloc_rx_ring(sc, &sc->rxq); if (error != 0) { printf(": could not allocate Rx ring\n"); - goto fail4; + goto fail3; } ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ @@ -301,6 +300,8 @@ wpi_attach(struct device *parent, struct device *self, void *aux) ieee80211_ifattach(ifp); ic->ic_node_alloc = wpi_node_alloc; ic->ic_newassoc = wpi_newassoc; + ic->ic_set_key = wpi_set_key; + ic->ic_updateedca = wpi_updateedca; /* override state transition machine */ sc->sc_newstate = ic->ic_newstate; @@ -310,7 +311,29 @@ wpi_attach(struct device *parent, struct device *self, void *aux) sc->amrr.amrr_min_success_threshold = 1; sc->amrr.amrr_max_success_threshold = 15; - /* register thermal sensor with the sensor framework */ + wpi_sensor_attach(sc); + wpi_radiotap_attach(sc); + + timeout_set(&sc->calib_to, wpi_calib_timeout, sc); + + sc->powerhook = powerhook_establish(wpi_power, sc); + + return; + + /* free allocated memory if something failed during attachment */ +fail3: while (--i >= 0) + wpi_free_tx_ring(sc, &sc->txq[i]); + wpi_free_rpool(sc); +fail2: wpi_free_shared(sc); +fail1: wpi_free_fwmem(sc); +} + +/* + * Attach the adapter's on-board thermal sensor to the sensors framework. + */ +void +wpi_sensor_attach(struct wpi_softc *sc) +{ strlcpy(sc->sensordev.xname, sc->sc_dev.dv_xname, sizeof sc->sensordev.xname); strlcpy(sc->sensor.desc, "temperature 0 - 285", @@ -321,13 +344,16 @@ wpi_attach(struct device *parent, struct device *self, void *aux) sc->sensor.flags = SENSOR_FINVALID; sensor_attach(&sc->sensordev, &sc->sensor); sensordev_install(&sc->sensordev); +} - timeout_set(&sc->calib_to, wpi_calib_timeout, sc); - - sc->powerhook = powerhook_establish(wpi_power, sc); - +/* + * Attach the interface to 802.11 radiotap. + */ +void +wpi_radiotap_attach(struct wpi_softc *sc) +{ #if NBPFILTER > 0 - bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO, + bpfattach(&sc->sc_drvbpf, &sc->sc_ic.ic_if, DLT_IEEE802_11_RADIO, sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN); sc->sc_rxtap_len = sizeof sc->sc_rxtapu; @@ -338,16 +364,6 @@ wpi_attach(struct device *parent, struct device *self, void *aux) sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len); sc->sc_txtap.wt_ihdr.it_present = htole32(WPI_TX_RADIOTAP_PRESENT); #endif - - return; - - /* free allocated memory if something failed during attachment */ -fail4: wpi_free_tx_ring(sc, &sc->cmdq); -fail3: while (--ac >= 0) - wpi_free_tx_ring(sc, &sc->txq[ac]); - wpi_free_rpool(sc); -fail2: wpi_free_shared(sc); -fail1: wpi_free_fwmem(sc); } void @@ -674,13 +690,15 @@ fail: wpi_free_tx_ring(sc, ring); void wpi_reset_tx_ring(struct wpi_softc *sc, struct wpi_tx_ring *ring) { + uint32_t tmp; int i, ntries; wpi_mem_lock(sc); WPI_WRITE(sc, WPI_TX_CONFIG(ring->qid), 0); for (ntries = 0; ntries < 100; ntries++) { - if (WPI_READ(sc, WPI_TX_STATUS) & WPI_TX_IDLE(ring->qid)) + tmp = WPI_READ(sc, WPI_TX_STATUS); + if ((tmp & WPI_TX_IDLE(ring->qid)) == WPI_TX_IDLE(ring->qid)) break; DELAY(10); } @@ -1359,7 +1377,7 @@ wpi_tx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc) void wpi_cmd_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc) { - struct wpi_tx_ring *ring = &sc->cmdq; + struct wpi_tx_ring *ring = &sc->txq[4]; struct wpi_tx_data *data; if ((desc->qid & 7) != 4) @@ -2021,7 +2039,7 @@ wpi_read_eeprom_group(struct wpi_softc *sc, int n) int wpi_cmd(struct wpi_softc *sc, int code, const void *buf, int size, int async) { - struct wpi_tx_ring *ring = &sc->cmdq; + struct wpi_tx_ring *ring = &sc->txq[4]; struct wpi_tx_desc *desc; struct wpi_tx_cmd *cmd; @@ -2042,7 +2060,7 @@ wpi_cmd(struct wpi_softc *sc, int code, const void *buf, int size, int async) desc->segs[0].len = htole32(4 + size); /* kick cmd ring */ - ring->cur = (ring->cur + 1) % WPI_CMD_RING_COUNT; + ring->cur = (ring->cur + 1) % WPI_TX_RING_COUNT; WPI_WRITE(sc, WPI_TX_WIDX, ring->qid << 8 | ring->cur); return async ? 0 : tsleep(cmd, PCATCH, "wpicmd", hz); @@ -2103,6 +2121,62 @@ wpi_mrr_setup(struct wpi_softc *sc) return 0; } +/* + * Install a pairwise key into the hardware. + */ +int +wpi_set_key(struct ieee80211com *ic, struct ieee80211_node *ni, + const struct ieee80211_key *k) +{ + struct wpi_softc *sc = ic->ic_softc; + struct wpi_node_info node; + + if (k->k_flags & IEEE80211_KEY_GROUP) + return 0; + + memset(&node, 0, sizeof node); + + switch (k->k_cipher) { + case IEEE80211_CIPHER_CCMP: + node.security = htole16(WPI_CIPHER_CCMP); + node.security |= htole16(k->k_id << 8); + memcpy(node.key, k->k_key, k->k_len); + break; + default: + return 0; + } + + node.id = WPI_ID_BSS; + IEEE80211_ADDR_COPY(node.macaddr, ni->ni_macaddr); + node.control = WPI_NODE_UPDATE; + node.flags = WPI_FLAG_SET_KEY; + + return wpi_cmd(sc, WPI_CMD_ADD_NODE, &node, sizeof node, 1); +} + +void +wpi_updateedca(struct ieee80211com *ic) +{ +#define WPI_EXP2(x) ((1 << (x)) - 1) /* CWmin = 2^ECWmin - 1 */ + struct wpi_softc *sc = ic->ic_softc; + struct wpi_edca_params cmd; + int aci; + + memset(&cmd, 0, sizeof cmd); + cmd.flags = htole32(WPI_EDCA_UPDATE); + for (aci = 0; aci < EDCA_NUM_AC; aci++) { + const struct ieee80211_edca_ac_params *ac = + &ic->ic_edca_ac[aci]; + cmd.ac[aci].aifsn = ac->ac_aifsn; + cmd.ac[aci].cwmin = htole16(WPI_EXP2(ac->ac_ecwmin)); + cmd.ac[aci].cwmax = htole16(WPI_EXP2(ac->ac_ecwmax)); + cmd.ac[aci].txoplimit = + htole16(IEEE80211_TXOP_TO_US(ac->ac_txoplimit)); + } + (void)wpi_cmd(sc, WPI_CMD_EDCA_PARAMS, &cmd, sizeof cmd, 1); +#undef WPI_EXP2 +} + void wpi_set_led(struct wpi_softc *sc, uint8_t which, uint8_t off, uint8_t on) { @@ -2311,7 +2385,7 @@ wpi_auth(struct wpi_softc *sc) /* add default node */ memset(&node, 0, sizeof node); - IEEE80211_ADDR_COPY(node.bssid, ni->ni_bssid); + IEEE80211_ADDR_COPY(node.macaddr, ni->ni_bssid); node.id = WPI_ID_BSS; node.rate = (ic->ic_curmode == IEEE80211_MODE_11A) ? wpi_plcp_signal(12) : wpi_plcp_signal(2); @@ -2334,7 +2408,7 @@ int wpi_scan(struct wpi_softc *sc, uint16_t flags) { struct ieee80211com *ic = &sc->sc_ic; - struct wpi_tx_ring *ring = &sc->cmdq; + struct wpi_tx_ring *ring = &sc->txq[4]; struct wpi_tx_desc *desc; struct wpi_tx_data *data; struct wpi_tx_cmd *cmd; @@ -2484,7 +2558,7 @@ wpi_scan(struct wpi_softc *sc, uint16_t flags) desc->segs[0].len = htole32(data->map->dm_segs[0].ds_len); /* kick cmd ring */ - ring->cur = (ring->cur + 1) % WPI_CMD_RING_COUNT; + ring->cur = (ring->cur + 1) % WPI_TX_RING_COUNT; WPI_WRITE(sc, WPI_TX_WIDX, ring->qid << 8 | ring->cur); return 0; /* will be notified async. of failure/success */ @@ -2569,7 +2643,7 @@ wpi_config(struct wpi_softc *sc) /* add broadcast node */ memset(&node, 0, sizeof node); - IEEE80211_ADDR_COPY(node.bssid, etherbroadcastaddr); + IEEE80211_ADDR_COPY(node.macaddr, etherbroadcastaddr); node.id = WPI_ID_BROADCAST; node.rate = wpi_plcp_signal(2); node.action = htole32(WPI_ACTION_SET_RATE); @@ -2827,7 +2901,7 @@ wpi_stop(struct ifnet *ifp, int disable) struct wpi_softc *sc = ifp->if_softc; struct ieee80211com *ic = &sc->sc_ic; uint32_t tmp; - int ac; + int i; ifp->if_timer = sc->sc_tx_timer = 0; ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); @@ -2845,9 +2919,8 @@ wpi_stop(struct ifnet *ifp, int disable) wpi_mem_unlock(sc); /* reset all Tx rings */ - for (ac = 0; ac < 4; ac++) - wpi_reset_tx_ring(sc, &sc->txq[ac]); - wpi_reset_tx_ring(sc, &sc->cmdq); + for (i = 0; i < WPI_NTXQUEUES; i++) + wpi_reset_tx_ring(sc, &sc->txq[i]); /* reset Rx ring */ wpi_reset_rx_ring(sc, &sc->rxq); @@ -2863,7 +2936,6 @@ wpi_stop(struct ifnet *ifp, int disable) DELAY(5); wpi_stop_master(sc); - tmp = WPI_READ(sc, WPI_RESET); WPI_WRITE(sc, WPI_RESET, tmp | WPI_SW_RESET); } diff --git a/sys/dev/pci/if_wpireg.h b/sys/dev/pci/if_wpireg.h index 4bd921b3f9b..7017263ac10 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.19 2007/09/10 20:53:22 damien Exp $ */ +/* $OpenBSD: if_wpireg.h,v 1.20 2007/09/11 18:52:32 damien Exp $ */ /*- * Copyright (c) 2006, 2007 @@ -18,12 +18,12 @@ */ #define WPI_TX_RING_COUNT 256 -#define WPI_CMD_RING_COUNT 256 #define WPI_RX_RING_COUNT 64 +#define WPI_NTXQUEUES 16 + /* * Rings must be aligned on a 16K boundary. - * I had a hard time figuring this out. */ #define WPI_RING_DMA_ALIGN 0x4000 @@ -211,42 +211,11 @@ struct wpi_rx_desc { uint8_t qid; } __packed; -struct wpi_rx_stat { - uint8_t len; -#define WPI_STAT_MAXLEN 20 - - uint8_t id; - uint8_t rssi; /* received signal strength */ -#define WPI_RSSI_OFFSET 95 - - uint8_t agc; /* access gain control */ - uint16_t signal; - uint16_t noise; -} __packed; - -struct wpi_rx_head { - uint16_t chan; - uint16_t flags; - uint8_t reserved; - uint8_t rate; - uint16_t len; -} __packed; - -struct wpi_rx_tail { - uint32_t flags; -#define WPI_RX_NO_CRC_ERR (1 << 0) -#define WPI_RX_NO_OVFL_ERR (1 << 1) -/* shortcut for the above */ -#define WPI_RX_NOERROR (WPI_RX_NO_CRC_ERR | WPI_RX_NO_OVFL_ERR) - - uint64_t tstamp; - uint32_t tbeacon; -} __packed; - struct wpi_tx_cmd { uint8_t code; #define WPI_CMD_CONFIGURE 16 #define WPI_CMD_ASSOCIATE 17 +#define WPI_CMD_EDCA_PARAMS 19 #define WPI_CMD_TSF 20 #define WPI_CMD_ADD_NODE 24 #define WPI_CMD_TX_DATA 28 @@ -254,7 +223,6 @@ struct wpi_tx_cmd { #define WPI_CMD_SET_LED 72 #define WPI_CMD_SET_POWER_MODE 119 #define WPI_CMD_SCAN 128 -#define WPI_CMD_SET_BEACON 145 #define WPI_CMD_TXPOWER 151 #define WPI_CMD_BLUETOOTH 155 @@ -264,7 +232,7 @@ struct wpi_tx_cmd { uint8_t data[124]; } __packed; -/* structure for WPI_CMD_CONFIGURE */ +/* structure for command WPI_CMD_CONFIGURE */ struct wpi_config { uint8_t myaddr[IEEE80211_ADDR_LEN]; uint16_t reserved1; @@ -312,6 +280,21 @@ struct wpi_assoc { uint16_t reserved; } __packed; +/* structure for command WPI_CMD_EDCA_PARAMS */ +struct wpi_edca_params { + uint32_t flags; +#define WPI_EDCA_UPDATE (1 << 0) +#define WPI_EDCA_TXOP (1 << 4) + + struct { + uint16_t cwmin; + uint16_t cwmax; + uint8_t aifsn; + uint8_t reserved; + uint16_t txoplimit; + } __packed ac[EDCA_NUM_AC]; +} __packed; + /* structure for command WPI_CMD_TSF */ struct wpi_cmd_tsf { uint64_t tstamp; @@ -322,13 +305,13 @@ struct wpi_cmd_tsf { uint16_t reserved; } __packed; -/* structure for WPI_CMD_ADD_NODE */ +/* structure for command WPI_CMD_ADD_NODE */ struct wpi_node_info { uint8_t control; #define WPI_NODE_UPDATE (1 << 0) uint8_t reserved1[3]; - uint8_t bssid[IEEE80211_ADDR_LEN]; + uint8_t macaddr[IEEE80211_ADDR_LEN]; uint16_t reserved2; uint8_t id; #define WPI_ID_BSS 0 @@ -396,25 +379,7 @@ struct wpi_cmd_data { uint16_t txop; } __packed; -/* structure for command WPI_CMD_SET_BEACON */ -struct wpi_cmd_beacon { - uint16_t len; - uint16_t reserved1; - uint32_t flags; /* same as wpi_cmd_data */ - uint8_t rate; - uint8_t id; - uint8_t reserved2[30]; - uint32_t lifetime; - uint8_t ofdm_mask; - uint8_t cck_mask; - uint16_t reserved3[3]; - uint16_t tim; - uint8_t timsz; - uint8_t reserved4; - struct ieee80211_frame wh; -} __packed; - -/* structure for WPI_CMD_MRR_SETUP */ +/* structure for command WPI_CMD_MRR_SETUP */ struct wpi_mrr_setup { uint32_t which; #define WPI_MRR_CTL 0 @@ -434,7 +399,7 @@ struct wpi_mrr_setup { } __packed rates[WPI_CCK11 + 1]; } __packed; -/* structure for WPI_CMD_SET_LED */ +/* structure for command WPI_CMD_SET_LED */ struct wpi_cmd_led { uint32_t unit; /* multiplier (in usecs) */ uint8_t which; @@ -446,7 +411,7 @@ struct wpi_cmd_led { uint8_t reserved; } __packed; -/* structure for WPI_CMD_SET_POWER_MODE */ +/* structure for command WPI_CMD_SET_POWER_MODE */ struct wpi_power { uint32_t flags; #define WPI_POWER_CAM 0 /* constantly awake mode */ @@ -494,7 +459,7 @@ struct wpi_scan_chan { uint16_t passive; /* msecs */ } __packed; -/* structure for WPI_CMD_TXPOWER */ +/* structure for command WPI_CMD_TXPOWER */ struct wpi_cmd_txpower { uint8_t band; #define WPI_BAND_5GHZ 0 @@ -510,7 +475,7 @@ struct wpi_cmd_txpower { } __packed rates[WPI_CCK11 + 1]; } __packed; -/* structure for WPI_CMD_BLUETOOTH */ +/* structure for command WPI_CMD_BLUETOOTH */ struct wpi_bluetooth { uint8_t flags; uint8_t lead; @@ -521,6 +486,39 @@ struct wpi_bluetooth { } __packed; +/* structures for WPI_RX_DONE notification */ +struct wpi_rx_stat { + uint8_t len; +#define WPI_STAT_MAXLEN 20 + + uint8_t id; + uint8_t rssi; /* received signal strength */ +#define WPI_RSSI_OFFSET 95 + + uint8_t agc; /* access gain control */ + uint16_t signal; + uint16_t noise; +} __packed; + +struct wpi_rx_head { + uint16_t chan; + uint16_t flags; + uint8_t reserved; + uint8_t rate; + uint16_t len; +} __packed; + +struct wpi_rx_tail { + uint32_t flags; +#define WPI_RX_NO_CRC_ERR (1 << 0) +#define WPI_RX_NO_OVFL_ERR (1 << 1) +/* shortcut for the above */ +#define WPI_RX_NOERROR (WPI_RX_NO_CRC_ERR | WPI_RX_NO_OVFL_ERR) + + uint64_t tstamp; + uint32_t tbeacon; +} __packed; + /* structure for WPI_UC_READY notification */ struct wpi_ucode_info { uint32_t version; diff --git a/sys/dev/pci/if_wpivar.h b/sys/dev/pci/if_wpivar.h index 921afe74bdf..29b51f04962 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.13 2007/08/22 19:50:25 damien Exp $ */ +/* $OpenBSD: if_wpivar.h,v 1.14 2007/09/11 18:52:32 damien Exp $ */ /*- * Copyright (c) 2006, 2007 @@ -141,8 +141,7 @@ struct wpi_softc { struct wpi_dma_info fw_dma; /* rings */ - struct wpi_tx_ring txq[4]; - struct wpi_tx_ring cmdq; + struct wpi_tx_ring txq[WPI_NTXQUEUES]; struct wpi_rx_ring rxq; bus_space_tag_t sc_st; |