Date: Sun, 28 Jul 2013 10:45:19 +0200 From: "Cedric GROSS" <cg@cgross.info> To: <freebsd-wireless@freebsd.org> Subject: [IWN] Centrino 2230 patch. Message-ID: <000301ce8b6e$cbca9dc0$635fd940$@info>
index | next in thread | raw e-mail
[-- Attachment #1 --]
Hello,
Here is the full patch against -HEAD for managing 2230 NIC and 6235.
You will need firmware file. It's too big for the ML.
Cedric
[-- Attachment #2 --]
Index: sys/dev/iwn/if_iwn.c
===================================================================
--- sys/dev/iwn/if_iwn.c (revision 253707)
+++ sys/dev/iwn/if_iwn.c (working copy)
@@ -1,4 +1,6 @@
/*-
+ * Copyright (c) 2013 Cedric GROSS <c.gross@kreiz-it.fr>
+ * Copyright (c) 2011 Intel Corporation
* Copyright (c) 2007-2009
* Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2008
@@ -22,7 +24,7 @@
* Driver for Intel WiFi Link 4965 and 1000/5000/6000 Series 802.11 network
* adapters.
*/
-
+
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -74,6 +76,7 @@
#include <dev/iwn/if_iwnreg.h>
#include <dev/iwn/if_iwnvar.h>
+
struct iwn_ident {
uint16_t vendor;
uint16_t device;
@@ -81,40 +84,42 @@
};
static const struct iwn_ident iwn_ident_table[] = {
- { 0x8086, 0x0082, "Intel Centrino Advanced-N 6205" },
- { 0x8086, 0x0083, "Intel Centrino Wireless-N 1000" },
- { 0x8086, 0x0084, "Intel Centrino Wireless-N 1000" },
- { 0x8086, 0x0085, "Intel Centrino Advanced-N 6205" },
- { 0x8086, 0x0087, "Intel Centrino Advanced-N + WiMAX 6250" },
- { 0x8086, 0x0089, "Intel Centrino Advanced-N + WiMAX 6250" },
- { 0x8086, 0x008a, "Intel Centrino Wireless-N 1030" },
- { 0x8086, 0x008b, "Intel Centrino Wireless-N 1030" },
- { 0x8086, 0x0090, "Intel Centrino Advanced-N 6230" },
- { 0x8086, 0x0091, "Intel Centrino Advanced-N 6230" },
- { 0x8086, 0x0885, "Intel Centrino Wireless-N + WiMAX 6150" },
- { 0x8086, 0x0886, "Intel Centrino Wireless-N + WiMAX 6150" },
- { 0x8086, 0x0887, "Intel Centrino Wireless-N 2230" },
- { 0x8086, 0x0888, "Intel Centrino Wireless-N 2230" },
- { 0x8086, 0x0896, "Intel Centrino Wireless-N 130" },
- { 0x8086, 0x0897, "Intel Centrino Wireless-N 130" },
- { 0x8086, 0x08ae, "Intel Centrino Wireless-N 100" },
- { 0x8086, 0x08af, "Intel Centrino Wireless-N 100" },
+ { 0x8086, IWN_DID_6x05_1, "Intel Centrino Advanced-N 6205" },
+ { 0x8086, IWN_DID_1000_1, "Intel Centrino Wireless-N 1000" },
+ { 0x8086, IWN_DID_1000_2, "Intel Centrino Wireless-N 1000" },
+ { 0x8086, IWN_DID_6x05_2, "Intel Centrino Advanced-N 6205" },
+ { 0x8086, IWN_DID_6050_1, "Intel Centrino Advanced-N + WiMAX 6250" },
+ { 0x8086, IWN_DID_6050_2, "Intel Centrino Advanced-N + WiMAX 6250" },
+ { 0x8086, IWN_DID_x030_1, "Intel Centrino Wireless-N 1030" },
+ { 0x8086, IWN_DID_x030_2, "Intel Centrino Wireless-N 1030" },
+ { 0x8086, IWN_DID_x030_3, "Intel Centrino Advanced-N 6230" },
+ { 0x8086, IWN_DID_x030_4, "Intel Centrino Advanced-N 6230" },
+ { 0x8086, IWN_DID_6150_1, "Intel Centrino Wireless-N + WiMAX 6150" },
+ { 0x8086, IWN_DID_6150_2, "Intel Centrino Wireless-N + WiMAX 6150" },
+ { 0x8086, IWN_DID_2x30_1, "Intel Centrino Wireless-N 2230"},
+ { 0x8086, IWN_DID_2x30_2, "Intel Centrino Wireless-N 2230"},
+ { 0x8086, IWN_DID_130_1, "Intel Centrino Wireless-N 130" },
+ { 0x8086, IWN_DID_130_2, "Intel Centrino Wireless-N 130" },
+ { 0x8086, IWN_DID_100_1, "Intel Centrino Wireless-N 100" },
+ { 0x8086, IWN_DID_100_2, "Intel Centrino Wireless-N 100" },
{ 0x8086, 0x4229, "Intel Wireless WiFi Link 4965" },
- { 0x8086, 0x422b, "Intel Centrino Ultimate-N 6300" },
- { 0x8086, 0x422c, "Intel Centrino Advanced-N 6200" },
+ { 0x8086, IWN_DID_6x00_1, "Intel Centrino Ultimate-N 6300" },
+ { 0x8086, IWN_DID_6x00_2, "Intel Centrino Advanced-N 6200" },
{ 0x8086, 0x422d, "Intel Wireless WiFi Link 4965" },
{ 0x8086, 0x4230, "Intel Wireless WiFi Link 4965" },
- { 0x8086, 0x4232, "Intel WiFi Link 5100" },
+ { 0x8086, IWN_DID_5x00_1, "Intel WiFi Link 5100" },
{ 0x8086, 0x4233, "Intel Wireless WiFi Link 4965" },
- { 0x8086, 0x4235, "Intel Ultimate N WiFi Link 5300" },
- { 0x8086, 0x4236, "Intel Ultimate N WiFi Link 5300" },
- { 0x8086, 0x4237, "Intel WiFi Link 5100" },
- { 0x8086, 0x4238, "Intel Centrino Ultimate-N 6300" },
- { 0x8086, 0x4239, "Intel Centrino Advanced-N 6200" },
- { 0x8086, 0x423a, "Intel WiMAX/WiFi Link 5350" },
- { 0x8086, 0x423b, "Intel WiMAX/WiFi Link 5350" },
- { 0x8086, 0x423c, "Intel WiMAX/WiFi Link 5150" },
- { 0x8086, 0x423d, "Intel WiMAX/WiFi Link 5150" },
+ { 0x8086, IWN_DID_5x00_3, "Intel Ultimate N WiFi Link 5300" },
+ { 0x8086, IWN_DID_5x00_4, "Intel Ultimate N WiFi Link 5300" },
+ { 0x8086, IWN_DID_5x00_2, "Intel WiFi Link 5100" },
+ { 0x8086, IWN_DID_6x00_3, "Intel Centrino Ultimate-N 6300" },
+ { 0x8086, IWN_DID_6x00_4, "Intel Centrino Advanced-N 6200" },
+ { 0x8086, IWN_DID_5x50_1, "Intel WiMAX/WiFi Link 5350" },
+ { 0x8086, IWN_DID_5x50_2, "Intel WiMAX/WiFi Link 5350" },
+ { 0x8086, IWN_DID_5x50_3, "Intel WiMAX/WiFi Link 5150" },
+ { 0x8086, IWN_DID_5x50_4, "Intel WiMAX/WiFi Link 5150" },
+ { 0x8086, IWN_DID_6035_1, "Centrino Advanced-N 6235" },
+ { 0x8086, IWN_DID_6035_2, "Centrino Advanced-N 6235" },
{ 0, 0, NULL }
};
@@ -160,7 +165,9 @@
static int iwn_read_eeprom(struct iwn_softc *,
uint8_t macaddr[IEEE80211_ADDR_LEN]);
static void iwn4965_read_eeprom(struct iwn_softc *);
+#ifdef IWN_DEBUG
static void iwn4965_print_power_group(struct iwn_softc *, int);
+#endif
static void iwn5000_read_eeprom(struct iwn_softc *);
static uint32_t iwn_eeprom_channel_flags(struct iwn_eeprom_chan *);
static void iwn_read_eeprom_band(struct iwn_softc *, int);
@@ -229,7 +236,7 @@
static int iwn_add_broadcast_node(struct iwn_softc *, int);
static int iwn_updateedca(struct ieee80211com *);
static void iwn_update_mcast(struct ifnet *);
-static void iwn_set_led(struct iwn_softc *, uint8_t, uint8_t, uint8_t);
+static void iwn_set_led(struct iwn_softc *, uint8_t , uint8_t , uint8_t , uint8_t );
static int iwn_set_critical_temp(struct iwn_softc *);
static int iwn_set_timing(struct iwn_softc *, struct ieee80211_node *);
static void iwn4965_power_calibration(struct iwn_softc *, int);
@@ -255,7 +262,7 @@
static int iwn_set_pslevel(struct iwn_softc *, int, int, int);
static int iwn_send_btcoex(struct iwn_softc *);
static int iwn_send_advanced_btcoex(struct iwn_softc *);
-static int iwn5000_runtime_calib(struct iwn_softc *);
+//static int iwn5000_runtime_calib(struct iwn_softc *);
static int iwn_config(struct iwn_softc *);
static uint8_t *ieee80211_add_ssid(uint8_t *, const uint8_t *, u_int);
static int iwn_scan(struct iwn_softc *);
@@ -286,6 +293,7 @@
static int iwn5000_send_wimax_coex(struct iwn_softc *);
static int iwn5000_crystal_calib(struct iwn_softc *);
static int iwn5000_temp_offset_calib(struct iwn_softc *);
+static int iwn5000_temp_offset_calibv2(struct iwn_softc *);
static int iwn4965_post_alive(struct iwn_softc *);
static int iwn5000_post_alive(struct iwn_softc *);
static int iwn4965_load_bootcode(struct iwn_softc *, const uint8_t *,
@@ -320,8 +328,27 @@
static void iwn_scan_curchan(struct ieee80211_scan_state *, unsigned long);
static void iwn_scan_mindwell(struct ieee80211_scan_state *);
static void iwn_hw_reset(void *, int);
+#ifdef IWN_DEBUG
+static char *iwn_get_csr_string(int);
+static void iwn_debug_register(struct iwn_softc *);
+#endif
+static int iwn_config_specific(struct iwn_softc *,uint16_t);
+//static int iwn_prepare_crystal_calib(struct iwn_softc *sc);
+static int iwn_set_statistics_request(struct iwn_softc *,bool ,bool ,int );
+static int iwn_cfg_ucode_post_alive(struct iwn_softc *);
+static int iwn_iv_reset(struct ieee80211vap *, u_long );
+static int iwn_newstate_u1(struct ieee80211vap *, enum ieee80211_state , int );
+static int iwn_auth_u1(struct iwn_softc *, struct ieee80211vap *);
+static int iwn_run_u1(struct iwn_softc *, struct ieee80211vap *);
+static int iwn_set_timing_u1(struct iwn_softc *);
+static int iwn_config_u1(struct iwn_softc *);
+static int iwn_set_pan_params(struct iwn_softc *);
+static int iwn_updateedca_u1(struct ieee80211com *);
+static int iwn_add_broadcast_node_u1(struct iwn_softc *, int );
+static uint16_t iwn_get_active_dwell(struct iwn_softc *, struct ieee80211_channel *);
+static uint16_t iwn_get_passive_dwell(struct iwn_softc *, struct ieee80211_channel *);
+static void iwn_led_pattern(struct iwn_softc *);
-#define IWN_DEBUG
#ifdef IWN_DEBUG
enum {
IWN_DEBUG_XMIT = 0x00000001, /* basic xmit operation */
@@ -339,6 +366,7 @@
IWN_DEBUG_CMD = 0x00001000, /* cmd submission */
IWN_DEBUG_TXRATE = 0x00002000, /* TX rate debugging */
IWN_DEBUG_PWRSAVE = 0x00004000, /* Power save operations */
+ IWN_DEBUG_REGISTER = 0x20000000, /* print chipset register */
IWN_DEBUG_TRACE = 0x40000000, /* Print begin and start driver function */
IWN_DEBUG_FATAL = 0x80000000, /* fatal errors */
IWN_DEBUG_ANY = 0xffffffff
@@ -345,7 +373,7 @@
};
#define DPRINTF(sc, m, fmt, ...) do { \
- if (sc->sc_debug & (m)) \
+ if ((sc->sc_debug & (m))== (m)) \
printf(fmt, __VA_ARGS__); \
} while (0)
@@ -366,6 +394,7 @@
case IWN_RX_PHY: return "RX_PHY";
case IWN_MPDU_RX_DONE: return "MPDU_RX_DONE";
case IWN_RX_DONE: return "RX_DONE";
+ case IWN_TEMP_NOTIFICATION: return "TEMPERATURE_NOTIFICATION";
/* Command Notifications */
case IWN_CMD_RXON: return "IWN_CMD_RXON";
@@ -388,6 +417,21 @@
case IWN_CMD_SET_CRITICAL_TEMP: return "IWN_CMD_SET_CRITICAL_TEMP";
case IWN_CMD_SET_SENSITIVITY: return "IWN_CMD_SET_SENSITIVITY";
case IWN_CMD_PHY_CALIB: return "IWN_CMD_PHY_CALIB";
+ case IWN_CMD_BT_COEX_PRIOTABLE: return "IWN_CMD_BT_COEX_PRIOTABLE";
+ case IWN_CMD_BT_COEX_PROT: return "IWN_CMD_BT_COEX_PROT";
+ case IWN_CMD_BT_COEX_NOTIF: return "IWN_CMD_BT_COEX_NOTIF";
+ /* PAN commands */
+ case IWN_CMD_WIPAN_PARAMS: return "IWN_CMD_WIPAN_PARAMS";
+ case IWN_CMD_WIPAN_RXON: return "IWN_CMD_WIPAN_RXON";
+ case IWN_CMD_WIPAN_RXON_TIMING: return "IWN_CMD_WIPAN_RXON_TIMING";
+ case IWN_CMD_WIPAN_RXON_ASSOC: return "IWN_CMD_WIPAN_RXON_ASSOC";
+ case IWN_CMD_WIPAN_QOS_PARAM: return "IWN_CMD_WIPAN_QOS_PARAM";
+ case IWN_CMD_WIPAN_WEPKEY: return "IWN_CMD_WIPAN_WEPKEY";
+ case IWN_CMD_WIPAN_P2P_CHANNEL_SWITCH: return "IWN_CMD_WIPAN_P2P_CHANNEL_SWITCH";
+ case IWN_CMD_WIPAN_NOA_NOTIFICATION: return "IWN_CMD_WIPAN_NOA_NOTIFICATION";
+ case IWN_CMD_WIPAN_DEACTIVATION_COMPLETE: return "IWN_CMD_WIPAN_DEACTIVATION_COMPLETE";
+
+
}
return "UNKNOWN INTR NOTIF/CMD";
}
@@ -421,6 +465,7 @@
MODULE_DEPEND(iwn, pci, 1, 1, 1);
MODULE_DEPEND(iwn, wlan, 1, 1, 1);
+/* Should be better to add subdevice dependency*/
static int
iwn_probe(device_t dev)
{
@@ -436,6 +481,7 @@
return ENXIO;
}
+/* Here we detect chipset */
static int
iwn_attach(device_t dev)
{
@@ -446,8 +492,12 @@
int i, error, result;
uint8_t macaddr[IEEE80211_ADDR_LEN];
+ sc->desired_pwrsave_level = IWN_POWERSAVE_LVL_DEFAULT;
+ sc->current_pwrsave_level = -1; /* signifies uninitialized */
+
+
sc->sc_dev = dev;
-
+
#ifdef IWN_DEBUG
error = resource_int_value(device_get_name(sc->sc_dev),
device_get_unit(sc->sc_dev), "debug", &(sc->sc_debug));
@@ -456,9 +506,9 @@
#else
sc->sc_debug = 0;
#endif
+
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_RESET, "->%s: begin\n",__func__);
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: begin\n",__func__);
-
/*
* Get the offset of the PCI Express Capability Structure in PCI
* Configuration Space.
@@ -511,7 +561,8 @@
IWN_LOCK_INIT(sc);
/* Read hardware revision and attach. */
- sc->hw_type = (IWN_READ(sc, IWN_HW_REV) >> 4) & 0xf;
+ sc->hw_type = (IWN_READ(sc, IWN_HW_REV) >> 4) & 0xff;
+ sc->subdevice_id=pci_get_subdevice(dev);
if (sc->hw_type == IWN_HW_REV_TYPE_4965)
error = iwn4965_attach(sc, pci_get_device(dev));
else
@@ -603,6 +654,11 @@
| IEEE80211_C_WME /* WME */
| IEEE80211_C_PMGT /* Station-side power mgmt */
;
+ if (sc->base_params->support_hostap) {
+ ic->ic_caps |= IEEE80211_C_HOSTAP ;/* HOSTAP mode supported */
+ } else {
+ ic->ic_caps &= ~ IEEE80211_C_HOSTAP ; /* HOSTAP mode not supported */
+ }
/* Read MAC address, channels, etc from EEPROM. */
if ((error = iwn_read_eeprom(sc, macaddr)) != 0) {
@@ -686,14 +742,24 @@
ic->ic_scan_mindwell = iwn_scan_mindwell;
ic->ic_setregdomain = iwn_setregdomain;
+ sc->sc_led.led_cur_mode = IWN_LED_STATIC_OFF;
+ sc->sc_led.led_cur_tpt = 0;
+ sc->sc_led.led_last_tpt = 0;
+ sc->sc_led.led_cur_time = 0;
+ sc->sc_led.led_last_time = 0;
+
+
+
iwn_radiotap_attach(sc);
callout_init_mtx(&sc->calib_to, &sc->sc_mtx, 0);
callout_init_mtx(&sc->watchdog_to, &sc->sc_mtx, 0);
+ callout_init_mtx(&sc->ct_kill_exit_to, &sc->sc_mtx, 0);
TASK_INIT(&sc->sc_reinit_task, 0, iwn_hw_reset, sc);
TASK_INIT(&sc->sc_radioon_task, 0, iwn_radio_on, sc);
TASK_INIT(&sc->sc_radiooff_task, 0, iwn_radio_off, sc);
+
iwn_sysctlattach(sc);
/*
@@ -706,14 +772,21 @@
error);
goto fail;
}
+ /* update ic->ic_flags to the default power save mode */
+ if (IWN_POWERSAVE_LVL_DEFAULT != IWN_POWERSAVE_LVL_NONE)
+ ic->ic_flags |= IEEE80211_F_PMGTON;
+ else
+ ic->ic_flags &= ~IEEE80211_F_PMGTON;
+
if (bootverbose)
ieee80211_announce(ic);
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s: end\n",__func__);
return 0;
fail:
iwn_detach(dev);
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end in error\n",__func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET | IWN_DEBUG_FATAL,
+ "->%s: end in error\n",__func__);
return error;
}
@@ -722,7 +795,8 @@
{
struct iwn_ops *ops = &sc->ops;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s begin\n", __func__);
+
ops->load_firmware = iwn4965_load_firmware;
ops->read_eeprom = iwn4965_read_eeprom;
ops->post_alive = iwn4965_post_alive;
@@ -752,9 +826,10 @@
/* Override chains masks, ROM is known to be broken. */
sc->txchainmask = IWN_ANT_AB;
sc->rxchainmask = IWN_ANT_ABC;
+ sc->base_params = &iwn_default_base_params; /* !! TODO : Define something may be more specific */
- DPRINTF(sc, IWN_DEBUG_TRACE, "%s: end\n",__func__);
-
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "%s: end\n",__func__);
+
return 0;
}
@@ -762,9 +837,9 @@
iwn5000_attach(struct iwn_softc *sc, uint16_t pid)
{
struct iwn_ops *ops = &sc->ops;
+
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s begin\n", __func__);
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
-
ops->load_firmware = iwn5000_load_firmware;
ops->read_eeprom = iwn5000_read_eeprom;
ops->post_alive = iwn5000_post_alive;
@@ -792,59 +867,7 @@
sc->reset_noise_gain = IWN5000_PHY_CALIB_RESET_NOISE_GAIN;
sc->noise_gain = IWN5000_PHY_CALIB_NOISE_GAIN;
- switch (sc->hw_type) {
- case IWN_HW_REV_TYPE_5100:
- sc->limits = &iwn5000_sensitivity_limits;
- sc->fwname = "iwn5000fw";
- /* Override chains masks, ROM is known to be broken. */
- sc->txchainmask = IWN_ANT_B;
- sc->rxchainmask = IWN_ANT_AB;
- break;
- case IWN_HW_REV_TYPE_5150:
- sc->limits = &iwn5150_sensitivity_limits;
- sc->fwname = "iwn5150fw";
- break;
- case IWN_HW_REV_TYPE_5300:
- case IWN_HW_REV_TYPE_5350:
- sc->limits = &iwn5000_sensitivity_limits;
- sc->fwname = "iwn5000fw";
- break;
- case IWN_HW_REV_TYPE_1000:
- sc->limits = &iwn1000_sensitivity_limits;
- sc->fwname = "iwn1000fw";
- break;
- case IWN_HW_REV_TYPE_6000:
- sc->limits = &iwn6000_sensitivity_limits;
- sc->fwname = "iwn6000fw";
- if (pid == 0x422c || pid == 0x4239) {
- sc->sc_flags |= IWN_FLAG_INTERNAL_PA;
- /* Override chains masks, ROM is known to be broken. */
- sc->txchainmask = IWN_ANT_BC;
- sc->rxchainmask = IWN_ANT_BC;
- }
- break;
- case IWN_HW_REV_TYPE_6050:
- sc->limits = &iwn6000_sensitivity_limits;
- sc->fwname = "iwn6050fw";
- /* Override chains masks, ROM is known to be broken. */
- sc->txchainmask = IWN_ANT_AB;
- sc->rxchainmask = IWN_ANT_AB;
- break;
- case IWN_HW_REV_TYPE_6005:
- sc->limits = &iwn6000_sensitivity_limits;
- if (pid != 0x0082 && pid != 0x0085) {
- sc->fwname = "iwn6000g2bfw";
- sc->sc_flags |= IWN_FLAG_ADV_BTCOEX;
- } else
- sc->fwname = "iwn6000g2afw";
- break;
- default:
- device_printf(sc->sc_dev, "adapter type %d not supported\n",
- sc->hw_type);
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end in error\n",__func__);
- return ENOTSUP;
- }
- return 0;
+ return iwn_config_specific(sc,pid);
}
/*
@@ -855,15 +878,19 @@
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s begin\n", __func__);
+
ieee80211_radiotap_attach(ic,
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
IWN_TX_RADIOTAP_PRESENT,
&sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap),
IWN_RX_RADIOTAP_PRESENT);
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
-}
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s end\n", __func__);
+
+ }
+
static void
iwn_sysctlattach(struct iwn_softc *sc)
{
@@ -885,19 +912,54 @@
{
struct iwn_vap *ivp;
struct ieee80211vap *vap;
+ uint8_t mac1[IEEE80211_ADDR_LEN];
+ struct iwn_softc *sc = ic->ic_ifp->if_softc;
- if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
- return NULL;
+
+ if (sc->base_params->no_multi_vaps) {
+ if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
+ return NULL;
+ }
+
+ IEEE80211_ADDR_COPY(mac1, mac);
+
+ if(unit == 1) {
+ if(!(sc->sc_flags & IWN_FLAG_PAN_SUPPORT))
+ return NULL;
+ mac1[5] += 1;
+ sc->ctx = IWN_RXON_PAN_CTX;
+ }
+
ivp = (struct iwn_vap *) malloc(sizeof(struct iwn_vap),
M_80211_VAP, M_NOWAIT | M_ZERO);
if (ivp == NULL)
return NULL;
vap = &ivp->iv_vap;
- ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
+
+ ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac1);
+
+ if(unit == 1) {
+ ivp->ctx = IWN_RXON_PAN_CTX;
+ ivp->iv_newstate = vap->iv_newstate;
+ vap->iv_newstate = iwn_newstate_u1;
+ IEEE80211_ADDR_COPY(ivp->macaddr, mac1);
+ memset(&sc->rx_on[IWN_RXON_PAN_CTX], 0, sizeof (struct iwn_rxon));
+ memcpy(&sc->rx_on[IWN_RXON_PAN_CTX], &sc->rx_on[IWN_RXON_BSS_CTX], sc->rxonsz);
+ IEEE80211_ADDR_COPY(sc->rx_on[IWN_RXON_PAN_CTX].myaddr, mac1);
+ sc->rx_on[IWN_RXON_PAN_CTX].mode = IWN_MODE_2STA;
+ sc->ivap[IWN_RXON_PAN_CTX] = vap;
+ }
+ else {
+ ivp->ctx = IWN_RXON_BSS_CTX;
+ IEEE80211_ADDR_COPY(ivp->macaddr, mac1);
+ ivp->iv_newstate = vap->iv_newstate;
+ vap->iv_newstate = iwn_newstate;
+ sc->ivap[IWN_RXON_BSS_CTX] = vap;
+ }
+
vap->iv_bmissthreshold = 10; /* override default */
- /* Override with driver methods. */
- ivp->iv_newstate = vap->iv_newstate;
- vap->iv_newstate = iwn_newstate;
+ /* handler for setting change (partial 're'set) requested via ioctl */
+ vap->iv_reset = iwn_iv_reset;
ieee80211_ratectl_init(vap);
/* Complete setup. */
@@ -910,7 +972,12 @@
iwn_vap_delete(struct ieee80211vap *vap)
{
struct iwn_vap *ivp = IWN_VAP(vap);
+ struct iwn_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ if(ivp->ctx == IWN_RXON_PAN_CTX)
+ sc->ctx = 0;
+
+
ieee80211_ratectl_deinit(vap);
ieee80211_vap_detach(vap);
free(ivp, M_80211_VAP);
@@ -924,6 +991,8 @@
struct ieee80211com *ic;
int qid;
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s begin\n", __func__);
+
if (ifp != NULL) {
ic = ifp->if_l2com;
@@ -933,6 +1002,7 @@
iwn_stop(sc);
callout_drain(&sc->watchdog_to);
+ callout_drain(&sc->ct_kill_exit_to);
callout_drain(&sc->calib_to);
ieee80211_ifdetach(ic);
}
@@ -961,7 +1031,8 @@
if (ifp != NULL)
if_free(ifp);
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s done\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s: end\n",__func__);
+
IWN_LOCK_DESTROY(sc);
return 0;
}
@@ -980,8 +1051,15 @@
{
struct iwn_softc *sc = device_get_softc(dev);
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->Doing %s\n",__func__);
+
ieee80211_suspend_all(ic);
+ iwn_stop(sc);
+ if (vap != NULL)
+ ieee80211_stop(vap);
+
return 0;
}
@@ -989,12 +1067,23 @@
iwn_resume(device_t dev)
{
struct iwn_softc *sc = device_get_softc(dev);
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->Doing %s\n", __func__);
/* Clear device-specific "PCI retry timeout" register (41h). */
pci_write_config(dev, 0x41, 0, 1);
ieee80211_resume_all(ic);
+ if (ifp->if_flags & IFF_UP) {
+ iwn_init(sc);
+ if (vap != NULL)
+ ieee80211_init(vap);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ iwn_start(ifp);
+ }
+
return 0;
}
@@ -1002,7 +1091,7 @@
iwn_nic_lock(struct iwn_softc *sc)
{
int ntries;
-
+
/* Request exclusive access to NIC. */
IWN_SETBITS(sc, IWN_GP_CNTRL, IWN_GP_CNTRL_MAC_ACCESS_REQ);
@@ -1011,9 +1100,11 @@
if ((IWN_READ(sc, IWN_GP_CNTRL) &
(IWN_GP_CNTRL_MAC_ACCESS_ENA | IWN_GP_CNTRL_SLEEP)) ==
IWN_GP_CNTRL_MAC_ACCESS_ENA)
- return 0;
+ return 0;
DELAY(10);
}
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_FATAL, "->%s timeout\n", __func__);
+
return ETIMEDOUT;
}
@@ -1122,7 +1213,7 @@
DELAY(10);
}
}
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end timeout\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_FATAL, "->%s end timeout\n", __func__);
return ETIMEDOUT;
}
@@ -1142,8 +1233,8 @@
uint16_t prev, base, next;
int count, error;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
-
+ DPRINTF(sc, IWN_DEBUG_TRACE| IWN_DEBUG_RESET, "->%s begin\n", __func__);
+
/* Wait for clock stabilization before accessing prph. */
if ((error = iwn_clock_wait(sc)) != 0)
return error;
@@ -1156,7 +1247,7 @@
iwn_nic_unlock(sc);
/* Set auto clock gate disable bit for HW with OTP shadow RAM. */
- if (sc->hw_type != IWN_HW_REV_TYPE_1000) {
+ if (sc->base_params->shadow_ram_support) {
IWN_SETBITS(sc, IWN_DBG_LINK_PWR_MGMT,
IWN_RESET_LINK_PWR_MGMT_DIS);
}
@@ -1169,11 +1260,11 @@
* Find the block before last block (contains the EEPROM image)
* for HW without OTP shadow RAM.
*/
- if (sc->hw_type == IWN_HW_REV_TYPE_1000) {
+ if (!(sc->base_params->shadow_ram_support)) {
/* Switch to absolute addressing mode. */
IWN_CLRBITS(sc, IWN_OTP_GP, IWN_OTP_GP_RELATIVE_ACCESS);
base = prev = 0;
- for (count = 0; count < IWN1000_OTP_NBLOCKS; count++) {
+ for (count = 0; count < sc->base_params->max_ll_items; count++) {
error = iwn_read_prom_data(sc, base, &next, 2);
if (error != 0)
return error;
@@ -1182,14 +1273,12 @@
prev = base;
base = le16toh(next);
}
- if (count == 0 || count == IWN1000_OTP_NBLOCKS)
+ if (count == 0 || count == sc->base_params->max_ll_items)
return EIO;
/* Skip "next" word. */
sc->prom_base = prev + 1;
}
-
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
-
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s end\n", __func__);
return 0;
}
@@ -1200,7 +1289,7 @@
uint32_t val, tmp;
int ntries;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s begin\n", __func__);
addr += sc->prom_base;
for (; count > 0; count -= 2, addr++) {
@@ -1235,7 +1324,7 @@
*out++ = val >> 24;
}
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s end\n", __func__);
return 0;
}
@@ -1293,7 +1382,7 @@
bus_dmamap_sync(dma->tag, dma->map,
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(dma->tag, dma->map);
- bus_dmamem_free(dma->tag, dma->vaddr, dma->map);
+ bus_dmamem_free(dma->tag, &dma->vaddr, dma->map);
dma->vaddr = NULL;
}
bus_dmamap_destroy(dma->tag, dma->map);
@@ -1367,7 +1456,7 @@
ring->cur = 0;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s begin\n", __func__);
/* Allocate RX descriptors (256-byte aligned). */
size = IWN_RX_RING_COUNT * sizeof (uint32_t);
@@ -1417,7 +1506,7 @@
goto fail;
}
- data->m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR,
+ data->m = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR,
IWN_RBUF_SIZE);
if (data->m == NULL) {
device_printf(sc->sc_dev,
@@ -1443,13 +1532,13 @@
bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map,
BUS_DMASYNC_PREWRITE);
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s: end\n",__func__);
return 0;
fail: iwn_free_rx_ring(sc, ring);
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end in error\n",__func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s: end in error\n",__func__);
return error;
}
@@ -1459,7 +1548,7 @@
{
int ntries;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->Doing %s\n", __func__);
if (iwn_nic_lock(sc) == 0) {
IWN_WRITE(sc, IWN_FH_RX_CONFIG, 0);
@@ -1480,7 +1569,7 @@
{
int i;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s \n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->Doing %s \n", __func__);
iwn_dma_contig_free(&ring->desc_dma);
iwn_dma_contig_free(&ring->stat_dma);
@@ -1515,7 +1604,7 @@
ring->queued = 0;
ring->cur = 0;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s begin\n", __func__);
/* Allocate TX descriptors (256-byte aligned). */
size = IWN_TX_RING_COUNT * sizeof (struct iwn_tx_desc);
@@ -1566,12 +1655,12 @@
}
}
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s end\n", __func__);
return 0;
fail: iwn_free_tx_ring(sc, ring);
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end in error\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s end in error\n", __func__);
return error;
}
@@ -1580,7 +1669,7 @@
{
int i;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->doing %s \n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->doing %s \n", __func__);
for (i = 0; i < IWN_TX_RING_COUNT; i++) {
struct iwn_tx_data *data = &ring->data[i];
@@ -1607,7 +1696,7 @@
{
int i;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s \n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->Doing %s \n", __func__);
iwn_dma_contig_free(&ring->desc_dma);
iwn_dma_contig_free(&ring->cmd_dma);
@@ -1633,6 +1722,9 @@
static void
iwn5000_ict_reset(struct iwn_softc *sc)
{
+
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s begin\n", __func__);
+
/* Disable interrupts. */
IWN_WRITE(sc, IWN_INT_MASK, 0);
@@ -1653,6 +1745,9 @@
/* Re-enable interrupts. */
IWN_WRITE(sc, IWN_INT, 0xffffffff);
IWN_WRITE(sc, IWN_INT_MASK, sc->int_mask);
+
+
+ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
}
static int
@@ -1662,8 +1757,8 @@
uint16_t val;
int error;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
-
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s begin\n", __func__);
+
/* Check whether adapter has an EEPROM or an OTPROM. */
if (sc->hw_type >= IWN_HW_REV_TYPE_1000 &&
(IWN_READ(sc, IWN_OTP_GP) & IWN_OTP_GP_DEV_SEL_OTP))
@@ -1698,6 +1793,7 @@
}
iwn_read_prom_data(sc, IWN_EEPROM_SKU_CAP, &val, 2);
+
DPRINTF(sc, IWN_DEBUG_RESET, "SKU capabilities=0x%04x\n", le16toh(val));
/* Check if HT support is bonded out. */
if (val & htole16(IWN_EEPROM_SKU_CAP_11N))
@@ -1722,8 +1818,8 @@
iwn_eeprom_unlock(sc);
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
-
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s end\n", __func__);
+
return 0;
}
@@ -1734,7 +1830,7 @@
uint16_t val;
int i;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s begin\n", __func__);
/* Read regulatory domain (4 ASCII characters). */
iwn_read_prom_data(sc, IWN4965_EEPROM_DOMAIN, sc->eeprom_domain, 4);
@@ -1775,7 +1871,7 @@
}
#endif
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s end\n", __func__);
}
#ifdef IWN_DEBUG
@@ -1818,12 +1914,11 @@
{
struct iwn5000_eeprom_calib_hdr hdr;
int32_t volt;
- uint32_t base, addr;
+ uint32_t base;
uint16_t val;
int i;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
-
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s begin\n", __func__);
/* Read regulatory domain (4 ASCII characters). */
iwn_read_prom_data(sc, IWN5000_EEPROM_REG, &val, 2);
base = le16toh(val);
@@ -1831,16 +1926,12 @@
sc->eeprom_domain, 4);
/* Read the list of authorized channels (20MHz ones only). */
- for (i = 0; i < 7; i++) {
- if (sc->hw_type >= IWN_HW_REV_TYPE_6000)
- addr = base + iwn6000_regulatory_bands[i];
- else
- addr = base + iwn5000_regulatory_bands[i];
- iwn_read_eeprom_channels(sc, i, addr);
+ for (i = 0; i < (IWN_NBANDS - 1); i++) {
+ iwn_read_eeprom_channels(sc, i, base+sc->base_params->regulatory_bands[i]);
}
/* Read enhanced TX power information for 6000 Series. */
- if (sc->hw_type >= IWN_HW_REV_TYPE_6000)
+ if (sc->base_params->enhanced_TX_power)
iwn_read_eeprom_enhinfo(sc);
iwn_read_prom_data(sc, IWN5000_EEPROM_CAL, &val, 2);
@@ -1850,6 +1941,14 @@
"%s: calib version=%u pa type=%u voltage=%u\n", __func__,
hdr.version, hdr.pa_type, le16toh(hdr.volt));
sc->calib_ver = hdr.version;
+
+ if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2) {
+ sc->eeprom_voltage = le16toh(hdr.volt);
+ iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP, &val, 2);
+ sc->eeprom_temp_high=le16toh(val);
+ iwn_read_prom_data(sc, base + IWN5000_EEPROM_VOLT, &val, 2);
+ sc->eeprom_temp = le16toh(val);
+ }
if (sc->hw_type == IWN_HW_REV_TYPE_5150) {
/* Compute temperature offset. */
@@ -1867,9 +1966,8 @@
DPRINTF(sc, IWN_DEBUG_CALIBRATE, "crystal calibration 0x%08x\n",
le32toh(sc->eeprom_crystal));
}
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s end\n", __func__);
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
-
}
/*
@@ -1905,7 +2003,7 @@
uint8_t chan;
int i, nflags;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s begin\n", __func__);
for (i = 0; i < band->nchan; i++) {
if (!(channels[i].flags & IWN_EEPROM_CHAN_VALID)) {
@@ -1950,7 +2048,7 @@
}
}
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s end\n", __func__);
}
@@ -1967,8 +2065,8 @@
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s start\n", __func__);
- if (!(sc->sc_flags & IWN_FLAG_HAS_11N)) {
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end no 11n\n", __func__);
+ if (!(sc->sc_flags & IWN_FLAG_HAS_11N)){
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s end no 11n\n", __func__);
return;
}
@@ -2019,7 +2117,7 @@
c->ic_flags |= IEEE80211_CHAN_HT40D | nflags;
}
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s end\n", __func__);
}
@@ -2104,7 +2202,7 @@
uint8_t flags;
int i, j;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s begin\n", __func__);
iwn_read_prom_data(sc, IWN5000_EEPROM_REG, &val, 2);
base = le16toh(val);
@@ -2157,7 +2255,7 @@
}
}
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s end\n", __func__);
}
@@ -2230,12 +2328,12 @@
/*
* Set the channel width and guard interval.
*/
- if (IEEE80211_IS_CHAN_HT40(ni->ni_chan)) {
- plcp |= IWN_RFLAG_HT40;
- if (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
+ if (IEEE80211_IS_CHAN_HT40(ni->ni_chan)) {
+ plcp |= IWN_RFLAG_HT40;
+ if (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
+ plcp |= IWN_RFLAG_SGI;
+ } else if (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20) {
plcp |= IWN_RFLAG_SGI;
- } else if (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20) {
- plcp |= IWN_RFLAG_SGI;
}
/*
@@ -2245,9 +2343,9 @@
* XXX three stream rates?
*/
if (rate > 0x87)
- plcp |= IWN_RFLAG_ANT(txant1 | txant2);
- else
- plcp |= IWN_RFLAG_ANT(txant1);
+ plcp |= IWN_RFLAG_ANT(txant1 | txant2);
+ else
+ plcp |= IWN_RFLAG_ANT(txant1);
} else {
/*
* Set the initial PLCP - fine for both
@@ -2264,13 +2362,13 @@
*/
ridx = ieee80211_legacy_rate_lookup(ic->ic_rt,
rate & IEEE80211_RATE_VAL);
- if (ridx < IWN_RIDX_OFDM6 &&
- IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
- plcp |= IWN_RFLAG_CCK;
+ if (ridx < IWN_RIDX_OFDM6 &&
+ IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
+ plcp |= IWN_RFLAG_CCK;
/* Set antenna configuration */
- plcp |= IWN_RFLAG_ANT(txant1);
- }
+ plcp |= IWN_RFLAG_ANT(txant1);
+ }
DPRINTF(sc, IWN_DEBUG_TXRATE, "%s: rate=0x%02x, plcp=0x%08x\n",
__func__,
@@ -2305,8 +2403,7 @@
struct iwn_softc *sc = ic->ic_ifp->if_softc;
int error = 0;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
-
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_STATE, "->%s begin\n", __func__);
DPRINTF(sc, IWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
ieee80211_state_name[vap->iv_state], ieee80211_state_name[nstate]);
@@ -2313,6 +2410,8 @@
IEEE80211_UNLOCK(ic);
IWN_LOCK(sc);
callout_stop(&sc->calib_to);
+
+ sc->rxon = &sc->rx_on[IWN_RXON_BSS_CTX];
switch (nstate) {
case IEEE80211_S_ASSOC:
@@ -2327,8 +2426,8 @@
* !AUTH -> AUTH transition requires state reset to handle
* reassociations correctly.
*/
- sc->rxon.associd = 0;
- sc->rxon.filter &= ~htole32(IWN_FILTER_BSS);
+ sc->rxon->associd = 0;
+ sc->rxon->filter &= ~htole32(IWN_FILTER_BSS);
sc->calib.state = IWN_CALIB_STATE_INIT;
if ((error = iwn_auth(sc, vap)) != 0) {
@@ -2367,11 +2466,11 @@
IWN_UNLOCK(sc);
IEEE80211_LOCK(ic);
if (error != 0){
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end in error\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_STATE, "->%s end in error\n", __func__);
return error;
}
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_STATE, "->%s: end\n",__func__);
return ivp->iv_newstate(vap, nstate, arg);
}
@@ -2385,12 +2484,7 @@
/* Force automatic TX power calibration every 60 secs. */
if (++sc->calib_cnt >= 120) {
- uint32_t flags = 0;
-
- DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s\n",
- "sending request for statistics");
- (void)iwn_cmd(sc, IWN_CMD_GET_STATISTICS, &flags,
- sizeof flags, 1);
+ iwn_set_statistics_request(sc,true,false,1);
sc->calib_cnt = 0;
}
callout_reset(&sc->calib_to, msecs_to_ticks(500), iwn_calib_timeout,
@@ -2436,7 +2530,7 @@
uint32_t flags;
int error, len, rssi, nf;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RECV, "->%s begin\n", __func__);
if (desc->type == IWN_MPDU_RX_DONE) {
/* Check for prior RX_PHY notification. */
@@ -2483,7 +2577,7 @@
return;
}
- m1 = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, IWN_RBUF_SIZE);
+ m1 = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, IWN_RBUF_SIZE);
if (m1 == NULL) {
DPRINTF(sc, IWN_DEBUG_ANY, "%s: no mbuf to restock ring\n",
__func__);
@@ -2577,7 +2671,7 @@
IWN_LOCK(sc);
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RECV, "->%s: end\n",__func__);
}
@@ -2600,7 +2694,7 @@
uint8_t tid;
int ackfailcnt = 0, i, lastidx, qid, *res, shift;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RECV, "->%s begin\n", __func__);
bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD);
@@ -2674,7 +2768,7 @@
bitmap >>= 1;
}
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RECV, "->%s: end\n",__func__);
}
@@ -2689,11 +2783,10 @@
struct iwn_phy_calib *calib = (struct iwn_phy_calib *)(desc + 1);
int len, idx = -1;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
-
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_CALIBRATE, "->%s begin\n", __func__);
/* Runtime firmware should not send such a notification. */
if (sc->sc_flags & IWN_FLAG_CALIB_DONE){
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s received after clib done\n",
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_CALIBRATE, "->%s received after clib done\n",
__func__);
return;
}
@@ -2702,29 +2795,30 @@
switch (calib->code) {
case IWN5000_PHY_CALIB_DC:
- if ((sc->sc_flags & IWN_FLAG_INTERNAL_PA) == 0 &&
- (sc->hw_type == IWN_HW_REV_TYPE_5150 ||
- sc->hw_type >= IWN_HW_REV_TYPE_6000) &&
- sc->hw_type != IWN_HW_REV_TYPE_6050)
+ if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_DC)
idx = 0;
break;
case IWN5000_PHY_CALIB_LO:
- idx = 1;
+ if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_LO)
+ idx = 1;
break;
case IWN5000_PHY_CALIB_TX_IQ:
- idx = 2;
+ if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TX_IQ)
+ idx = 2;
break;
case IWN5000_PHY_CALIB_TX_IQ_PERIODIC:
- if (sc->hw_type < IWN_HW_REV_TYPE_6000 &&
- sc->hw_type != IWN_HW_REV_TYPE_5150)
+ if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TX_IQ_PERIODIC)
idx = 3;
break;
case IWN5000_PHY_CALIB_BASE_BAND:
- idx = 4;
+ if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_BASE_BAND)
+ idx = 4;
break;
}
- if (idx == -1) /* Ignore other results. */
+ if (idx == -1) { /* Ignore other results. */
+ DPRINTF(sc,IWN_DEBUG_CALIBRATE,"Ignoring calib result %d",calib->code);
return;
+ }
/* Save calibration result. */
if (sc->calibcmd[idx].buf != NULL)
@@ -2740,6 +2834,7 @@
"saving calibration result code=%d len=%d\n", calib->code, len);
sc->calibcmd[idx].len = len;
memcpy(sc->calibcmd[idx].buf, calib, len);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_CALIBRATE, "->%s end\n", __func__);
}
/*
@@ -2756,18 +2851,60 @@
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct iwn_calib_state *calib = &sc->calib;
struct iwn_stats *stats = (struct iwn_stats *)(desc + 1);
+ struct ieee80211_node *ni = vap->iv_bss;
+ struct ieee80211_nodestats ns = ni->ni_stats;
+ struct bintime bt;
+
+ struct ieee80211vap *vap1;
+
int temp;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_CALIBRATE, "->%s begin\n", __func__);
/* Ignore statistics received during a scan. */
if (vap->iv_state != IEEE80211_S_RUN ||
(ic->ic_flags & IEEE80211_F_SCAN)){
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s received during calib\n",
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_CALIBRATE, "->%s received during calib\n",
__func__);
return;
}
+ if(sc->ctx == IWN_RXON_PAN_CTX) {
+ vap1 = sc->ivap[IWN_RXON_PAN_CTX];
+ /* Ignore statistics received during a scan. */
+ if (vap1->iv_state != IEEE80211_S_RUN ||
+ (ic->ic_flags & IEEE80211_F_SCAN))
+ return;
+ }
+ getbinuptime(&bt);
+ sc->sc_led.led_cur_time = bt.sec;
+ int time_diff = (sc->sc_led.led_cur_time - sc->sc_led.led_last_time);
+
+ if(time_diff >= 4) {
+ if(vap->iv_state == IEEE80211_S_RUN) {
+ sc->sc_led.led_cur_bt = (ns.ns_rx_bytes + ns.ns_tx_bytes);
+ if(sc->sc_led.led_cur_bt < sc->sc_led.led_last_bt) {
+ sc->sc_led.led_cur_bt = 0;
+ sc->sc_led.led_last_bt = 0;
+ }
+ sc->sc_led.led_bt_diff = (sc->sc_led.led_cur_bt - sc->sc_led.led_last_bt);
+ sc->sc_led.led_last_bt = sc->sc_led.led_cur_bt;
+ sc->sc_led.led_cur_tpt = (sc->sc_led.led_bt_diff / time_diff);
+ sc->sc_led.led_last_time = sc->sc_led.led_cur_time;
+
+ if(sc->sc_led.led_cur_tpt > 0) {
+ sc->sc_led.led_cur_mode = IWN_LED_INT_BLINK;
+ iwn_led_pattern(sc);
+ } else {
+ sc->sc_led.led_cur_mode = IWN_LED_STATIC_ON;
+ iwn_set_led(sc, IWN_LED_LINK, 0, 1, IWN_LED_STATIC_ON);
+ }
+
+ sc->sc_led.led_last_tpt = sc->sc_led.led_cur_tpt;
+ }
+ }
+
+
bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD);
DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s: received statistics, cmd %d\n",
@@ -2805,7 +2942,7 @@
else if (calib->state == IWN_CALIB_STATE_RUN)
iwn_tune_sensitivity(sc, &stats->rx);
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_CALIBRATE, "->%s: end\n",__func__);
}
/*
@@ -2881,21 +3018,38 @@
struct ifnet *ifp = sc->sc_ifp;
struct iwn_tx_ring *ring = &sc->txq[desc->qid & 0xf];
struct iwn_tx_data *data = &ring->data[desc->idx];
+
+ struct iwn_tx_cmd *cmd;
+ struct iwn_cmd_data *tx;
+
struct mbuf *m;
struct ieee80211_node *ni;
struct ieee80211vap *vap;
+ struct ieee80211_frame *wh;
KASSERT(data->ni != NULL, ("no node"));
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT, "->%s begin\n", __func__);
/* Unmap and free mbuf. */
+ uint8_t ridx;
bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(ring->data_dmat, data->map);
m = data->m, data->m = NULL;
ni = data->ni, data->ni = NULL;
+ uint8_t type;
vap = ni->ni_vap;
+ cmd = &ring->cmd[desc->idx];
+ tx = (struct iwn_cmd_data *)cmd->data;
+ wh = (struct ieee80211_frame *)(tx + 1);
+
+ struct ieee80211com *ic = ni->ni_ic;
+
+ type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
+
+
+
if (m->m_flags & M_TXCB) {
/*
* Channels marked for "radar" require traffic to be received
@@ -2919,6 +3073,9 @@
(status & IWN_TX_FAIL) != 0);
}
+
+ ridx = ic->ic_rt->rateCodeToIndex[ni->ni_txrate];
+
/*
* Update rate control statistics for the node.
*/
@@ -2944,7 +3101,7 @@
}
}
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT, "->%s: end\n",__func__);
}
@@ -2955,12 +3112,24 @@
static void
iwn_cmd_done(struct iwn_softc *sc, struct iwn_rx_desc *desc)
{
- struct iwn_tx_ring *ring = &sc->txq[4];
+ struct iwn_tx_ring *ring;
struct iwn_tx_data *data;
+ int cmd_queue_num;
- if ((desc->qid & 0xf) != 4)
+ if(sc->sc_flags & IWN_FLAG_PAN_SUPPORT)
+ cmd_queue_num = IWN_PAN_CMD_QUEUE;
+ else
+ cmd_queue_num = IWN_CMD_QUEUE_NUM;
+
+
+ DPRINTF(sc, IWN_DEBUG_CMD, "%s: qid: %d PAN Active : %d\n",
+ __func__, (desc->qid & 0xf),(sc->sc_flags & IWN_FLAG_PAN_SUPPORT) );
+
+
+ if ((desc->qid & 0xf) != cmd_queue_num)
return; /* Not a command ack. */
-
+
+ ring = &sc->txq[cmd_queue_num];
data = &ring->data[desc->idx];
/* If the command was mapped in an mbuf, free it. */
@@ -2993,7 +3162,7 @@
uint8_t tid;
int bit, i, lastidx, *res, seqno, shift, start;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT, "->%s begin\n", __func__);
#ifdef NOT_YET
if (nframes == 1) {
@@ -3082,7 +3251,7 @@
}
}
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT, "->%s: end\n",__func__);
}
@@ -3095,7 +3264,9 @@
struct iwn_ops *ops = &sc->ops;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
- struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ struct ieee80211_scan_state *ss = ic->ic_scan;
+ struct ieee80211vap *vapscan = ss->ss_vap;
+
uint16_t hw;
bus_dmamap_sync(sc->rxq.stat_dma.tag, sc->rxq.stat_dma.map,
@@ -3150,7 +3321,12 @@
struct iwn_beacon_missed *miss =
(struct iwn_beacon_missed *)(desc + 1);
int misses;
+ int iv_bmissthreshold;
+ int DoReinit =0 ;
+ struct ieee80211vap *vap0 = sc->ivap[IWN_RXON_BSS_CTX];
+ struct ieee80211vap *vap1 = sc->ivap[IWN_RXON_PAN_CTX];
+
bus_dmamap_sync(sc->rxq.data_dmat, data->map,
BUS_DMASYNC_POSTREAD);
misses = le32toh(miss->consecutive);
@@ -3158,15 +3334,28 @@
DPRINTF(sc, IWN_DEBUG_STATE,
"%s: beacons missed %d/%d\n", __func__,
misses, le32toh(miss->total));
+
+ iv_bmissthreshold = vap0->iv_bmissthreshold;
+
+ if(sc->ctx == IWN_RXON_PAN_CTX) {
+ iv_bmissthreshold = vap1->iv_bmissthreshold;
+ if (vap0->iv_state == IEEE80211_S_RUN &&
+ vap1->iv_state == IEEE80211_S_RUN &&
+ (ic->ic_flags & IEEE80211_F_SCAN) == 0)
+ DoReinit = 1;
+ }
+ else if (vap0->iv_state == IEEE80211_S_RUN &&
+ (ic->ic_flags & IEEE80211_F_SCAN) == 0)
+ DoReinit = 1;
+
/*
* If more than 5 consecutive beacons are missed,
* reinitialize the sensitivity state machine.
*/
- if (vap->iv_state == IEEE80211_S_RUN &&
- (ic->ic_flags & IEEE80211_F_SCAN) == 0) {
+ if (DoReinit==1) {
if (misses > 5)
(void)iwn_init_sensitivity(sc);
- if (misses >= vap->iv_bmissthreshold) {
+ if (misses >= iv_bmissthreshold) {
IWN_UNLOCK(sc);
ieee80211_beacon_miss(ic);
IWN_LOCK(sc);
@@ -3176,6 +3365,13 @@
}
case IWN_UC_READY:
{
+/**
+ * uCode issues this "alive" notification once the runtime image is ready
+ * to receive commands from the driver. This is the *second* "alive"
+ * notification that the driver will receive after rebooting uCode;
+ * this "alive" is indicated by subtype field != 9.
+ *
+ **/
struct iwn_ucode_info *uc =
(struct iwn_ucode_info *)(desc + 1);
@@ -3210,36 +3406,62 @@
* get both the enable/disble intr.
*/
bus_dmamap_sync(sc->rxq.data_dmat, data->map,
- BUS_DMASYNC_POSTREAD);
- DPRINTF(sc, IWN_DEBUG_INTR, "state changed to %x\n",
+ BUS_DMASYNC_POSTREAD);
+ if (*status & (IWN_STATE_CHANGE_HW_CARD_DISABLED | IWN_STATE_CHANGE_CT_CARD_DISABLED |IWN_STATE_CHANGE_SW_CARD_DISABLED)){
+ IWN_WRITE(sc, IWN_UCODE_GP1_SET, IWN_UCODE_GP1_CMD_BLOCKED);
+ IWN_WRITE(sc,IWN_TARG_MBX_C, 0x00000004);
+
+ if (!(*status & IWN_STATE_CHANGE_RXON_CARD_DISABLED)) {
+ IWN_WRITE(sc, IWN_UCODE_GP1_CLR, IWN_UCODE_GP1_CMD_BLOCKED);
+ IWN_WRITE(sc, IWN_TARG_MBX_C, 0x00000004);
+ }
+
+ if(*status & IWN_STATE_CHANGE_CT_CARD_DISABLED) {
+ device_printf(sc->sc_dev,"critical temp. reached\n");
+ /* XXX: enter CT kill */
+ }
+ }
+ if(!(*status & IWN_STATE_CHANGE_CT_CARD_DISABLED)){
+ callout_stop(&sc->ct_kill_exit_to);
+ /* XXX: exit CT kill */
+ }
+ /*
+ * State change allows hardware switch change to be
+ * noted. However, we handle this in iwn_intr as we
+ * get both the enable/disble intr.
+ */
+
+ DPRINTF(sc, IWN_DEBUG_INTR, "state changed to %x\n",
le32toh(*status));
break;
}
case IWN_START_SCAN:
{
+ bus_dmamap_sync(sc->rxq.data_dmat, data->map,
+ BUS_DMASYNC_POSTREAD);
+#ifdef IWN_DEBUG
struct iwn_start_scan *scan =
(struct iwn_start_scan *)(desc + 1);
-
- bus_dmamap_sync(sc->rxq.data_dmat, data->map,
- BUS_DMASYNC_POSTREAD);
DPRINTF(sc, IWN_DEBUG_ANY,
"%s: scanning channel %d status %x\n",
__func__, scan->chan, le32toh(scan->status));
+#endif
break;
}
case IWN_STOP_SCAN:
{
+ bus_dmamap_sync(sc->rxq.data_dmat, data->map,
+ BUS_DMASYNC_POSTREAD);
+#ifdef IWN_DEBUG
struct iwn_stop_scan *scan =
(struct iwn_stop_scan *)(desc + 1);
-
- bus_dmamap_sync(sc->rxq.data_dmat, data->map,
- BUS_DMASYNC_POSTREAD);
DPRINTF(sc, IWN_DEBUG_STATE,
"scan finished nchan=%d status=%d chan=%d\n",
scan->nchan, scan->status, scan->chan);
+#endif
IWN_UNLOCK(sc);
- ieee80211_scan_next(vap);
+ ieee80211_scan_next(vapscan);
IWN_LOCK(sc);
break;
}
@@ -3251,7 +3473,11 @@
sc->sc_flags |= IWN_FLAG_CALIB_DONE;
wakeup(sc);
break;
+ default:
+ DPRINTF(sc,IWN_DEBUG_INTR,"Interrupt type %d not managed\n",
+ desc->type);
}
+
sc->rxq.cur = (sc->rxq.cur + 1) % IWN_RX_RING_COUNT;
}
@@ -3309,6 +3535,7 @@
struct iwn_fw_dump dump;
int i;
+ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
IWN_LOCK_ASSERT(sc);
/* Force a complete recalibration on next init. */
@@ -3358,6 +3585,7 @@
i, ring->qid, ring->cur, ring->queued);
}
printf(" rx ring: cur=%d\n", sc->rxq.cur);
+ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
}
static void
@@ -3394,9 +3622,7 @@
r2 = IWN_READ(sc, IWN_FH_INT);
}
- DPRINTF(sc, IWN_DEBUG_INTR, "interrupt reg1=0x%08x reg2=0x%08x\n"
- , r1, r2);
-
+
if (r1 == 0 && r2 == 0)
goto done; /* Interrupt not for us. */
@@ -3405,6 +3631,9 @@
if (!(sc->sc_flags & IWN_FLAG_USE_ICT))
IWN_WRITE(sc, IWN_FH_INT, r2);
+
+ DPRINTF(sc, IWN_DEBUG_INTR, "Acked interupt reg1=0x%08x reg2=0x%08x\n", r1, r2);
+
if (r1 & IWN_INT_RF_TOGGLED) {
iwn_rftoggle_intr(sc);
goto done;
@@ -3413,9 +3642,13 @@
device_printf(sc->sc_dev, "%s: critical temperature reached!\n",
__func__);
}
+ /* Todo : Make separate action for HW Error and SW_error. SW Error maybe require just a restart */
if (r1 & (IWN_INT_SW_ERR | IWN_INT_HW_ERR)) {
device_printf(sc->sc_dev, "%s: fatal firmware error\n",
__func__);
+#ifdef IWN_DEBUG
+ iwn_debug_register(sc);
+#endif
/* Dump firmware error log and stop. */
iwn_fatal_intr(sc);
ifp->if_flags &= ~IFF_UP;
@@ -3504,7 +3737,7 @@
{
uint16_t *w = &sc->sched[qid * IWN5000_SCHED_COUNT + idx];
- DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->Doing %s\n", __func__);
*w = (*w & htole16(0xf000)) | htole16(1);
bus_dmamap_sync(sc->sched_dma.tag, sc->sched_dma.map,
@@ -3539,9 +3772,10 @@
bus_dma_segment_t *seg, segs[IWN_MAX_SCATTER];
uint8_t tid, ridx, txant, type;
int ac, i, totlen, error, pad, nsegs = 0, rate;
+ struct iwn_vap *ivp = IWN_VAP(vap);
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
-
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT, "->%s begin\n", __func__);
+
IWN_LOCK_ASSERT(sc);
wh = mtod(m, struct ieee80211_frame *);
@@ -3556,21 +3790,24 @@
qos = 0;
tid = 0;
}
- ac = M_WME_GETAC(m);
- if (m->m_flags & M_AMPDU_MPDU) {
+
+ if(ivp->ctx == IWN_RXON_PAN_CTX)
+ ac = iwn_pan_ac_to_queue[M_WME_GETAC(m)];
+ else
+ ac = iwn_bss_ac_to_queue[M_WME_GETAC(m)];
+
+
+ if (IEEE80211_QOS_HAS_SEQ(wh) &&
+ IEEE80211_AMPDU_RUNNING(&ni->ni_tx_ampdu[ac])) {
struct ieee80211_tx_ampdu *tap = &ni->ni_tx_ampdu[ac];
- if (!IEEE80211_AMPDU_RUNNING(tap)) {
- m_freem(m);
- return EINVAL;
- }
-
- ac = *(int *)tap->txa_private;
+ ring = &sc->txq[*(int *)tap->txa_private];
*(uint16_t *)wh->i_seq =
htole16(ni->ni_txseqs[tid] << IEEE80211_SEQ_SEQ_SHIFT);
ni->ni_txseqs[tid]++;
- }
- ring = &sc->txq[ac];
+ } else
+ ring = &sc->txq[ac];
+
desc = &ring->desc[ring->cur];
data = &ring->data[ring->cur];
@@ -3662,10 +3899,12 @@
}
}
- if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
- type != IEEE80211_FC0_TYPE_DATA)
- tx->id = sc->broadcast_id;
- else
+ if (IEEE80211_IS_MULTICAST(wh->i_addr1) || type != IEEE80211_FC0_TYPE_DATA) {
+ if(ivp->ctx == IWN_RXON_PAN_CTX)
+ tx->id = IWN_PAN_BCAST_ID;
+ else
+ tx->id = IWN_BROADCAST_ID;
+ } else
tx->id = wn->id;
if (type == IEEE80211_FC0_TYPE_MGT) {
@@ -3695,7 +3934,7 @@
tx->data_ntries = 15;
tx->lifetime = htole32(IWN_LIFETIME_INFINITE);
tx->rate = iwn_rate_to_plcp(sc, ni, rate);
- if (tx->id == sc->broadcast_id) {
+ if ((tx->id == IWN_PAN_BCAST_ID) || (tx->id == IWN_BROADCAST_ID)) {
/* Group or management frame. */
tx->linkq = 0;
/* XXX Alternate between antenna A and B? */
@@ -3727,7 +3966,7 @@
return error;
}
/* Too many DMA segments, linearize mbuf. */
- m1 = m_collapse(m, M_NOWAIT, IWN_MAX_SCATTER);
+ m1 = m_collapse(m, M_DONTWAIT, IWN_MAX_SCATTER);
if (m1 == NULL) {
device_printf(sc->sc_dev,
"%s: could not defrag mbuf\n", __func__);
@@ -3786,9 +4025,8 @@
/* Mark TX ring as full if we reach a certain threshold. */
if (++ring->queued > IWN_TX_RING_HIMARK)
sc->qfullmsk |= 1 << ring->qid;
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT, "->%s: end\n",__func__);
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
-
return 0;
}
@@ -3812,9 +4050,9 @@
u_int hdrlen;
int ac, totlen, error, pad, nsegs = 0, i, rate;
uint8_t ridx, type, txant;
+ struct iwn_vap *ivp = IWN_VAP(vap);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT, "->%s begin\n", __func__);
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
-
IWN_LOCK_ASSERT(sc);
wh = mtod(m, struct ieee80211_frame *);
@@ -3902,7 +4140,10 @@
tx->len = htole16(totlen);
tx->tid = 0;
- tx->id = sc->broadcast_id;
+ if(ivp->ctx == IWN_RXON_PAN_CTX)
+ tx->id = IWN_PAN_BCAST_ID;
+ else
+ tx->id = IWN_BROADCAST_ID;
tx->rts_ntries = params->ibp_try1;
tx->data_ntries = params->ibp_try0;
tx->lifetime = htole32(IWN_LIFETIME_INFINITE);
@@ -3912,12 +4153,10 @@
if (ridx < IWN_RIDX_OFDM6 &&
IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
tx->rate |= htole32(IWN_RFLAG_CCK);
-
/* Group or management frame. */
tx->linkq = 0;
txant = IWN_LSB(sc->txchainmask);
tx->rate |= htole32(IWN_RFLAG_ANT(txant));
-
/* Set physical address of "scratch area". */
tx->loaddr = htole32(IWN_LOADDR(data->scratch_paddr));
tx->hiaddr = IWN_HIADDR(data->scratch_paddr);
@@ -3940,7 +4179,7 @@
return error;
}
/* Too many DMA segments, linearize mbuf. */
- m1 = m_collapse(m, M_NOWAIT, IWN_MAX_SCATTER);
+ m1 = m_collapse(m, M_DONTWAIT, IWN_MAX_SCATTER);
if (m1 == NULL) {
device_printf(sc->sc_dev,
"%s: could not defrag mbuf\n", __func__);
@@ -4000,7 +4239,7 @@
if (++ring->queued > IWN_TX_RING_HIMARK)
sc->qfullmsk |= 1 << ring->qid;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT, "->%s: end\n",__func__);
return 0;
}
@@ -4014,7 +4253,7 @@
struct iwn_softc *sc = ifp->if_softc;
int error = 0;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT, "->%s begin\n", __func__);
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
ieee80211_free_node(ni);
@@ -4045,7 +4284,7 @@
IWN_UNLOCK(sc);
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT, "->%s: end\n",__func__);
return error;
}
@@ -4097,12 +4336,15 @@
struct iwn_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211_scan_state *ss = ic->ic_scan;
+ struct ieee80211vap *vapscan = ss->ss_vap;
+
IWN_LOCK_ASSERT(sc);
KASSERT(ifp->if_drv_flags & IFF_DRV_RUNNING, ("not running"));
- DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->Doing %s\n", __func__);
if (sc->sc_tx_timer > 0) {
if (--sc->sc_tx_timer == 0) {
@@ -4111,6 +4353,12 @@
return;
}
}
+
+ if (sc->sc_scan_timer > 0) {
+ if (--sc->sc_scan_timer == 0)
+ ieee80211_scan_next(vapscan);
+ }
+
callout_reset(&sc->watchdog_to, hz, iwn_watchdog, sc);
}
@@ -4163,7 +4411,7 @@
static int
iwn_cmd(struct iwn_softc *sc, int code, const void *buf, int size, int async)
{
- struct iwn_tx_ring *ring = &sc->txq[4];
+ struct iwn_tx_ring *ring ;
struct iwn_tx_desc *desc;
struct iwn_tx_data *data;
struct iwn_tx_cmd *cmd;
@@ -4170,12 +4418,25 @@
struct mbuf *m;
bus_addr_t paddr;
int totlen, error;
+ int cmd_queue_num;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+ if((sc->uc_scan_progress == 1) && (code != IWN_CMD_SCAN)) {
+ DPRINTF(sc,IWN_DEBUG_CMD,"Scanning in progress..not sending cmd %x.\n",code);
+ return 0;
+ }
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_CMD, "->%s begin\n", __func__);
+
if (async == 0)
IWN_LOCK_ASSERT(sc);
+
+ if(sc->sc_flags & IWN_FLAG_PAN_SUPPORT)
+ cmd_queue_num = IWN_PAN_CMD_QUEUE;
+ else
+ cmd_queue_num = IWN_CMD_QUEUE_NUM;
+ ring = &sc->txq[cmd_queue_num];
+
desc = &ring->desc[ring->cur];
data = &ring->data[ring->cur];
totlen = 4 + size;
@@ -4184,7 +4445,7 @@
/* Command is too large to fit in a descriptor. */
if (totlen > MCLBYTES)
return EINVAL;
- m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUMPAGESIZE);
+ m = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, MJUMPAGESIZE);
if (m == NULL)
return ENOMEM;
cmd = mtod(m, struct iwn_tx_cmd *);
@@ -4210,8 +4471,8 @@
desc->segs[0].addr = htole32(IWN_LOADDR(paddr));
desc->segs[0].len = htole16(IWN_HIADDR(paddr) | totlen << 4);
- DPRINTF(sc, IWN_DEBUG_CMD, "%s: %s (0x%x) flags %d qid %d idx %d\n",
- __func__, iwn_intr_str(cmd->code), cmd->code,
+ DPRINTF(sc, IWN_DEBUG_CMD, "Sending %s (0x%x) flags %d qid %d idx %d\n",
+ iwn_intr_str(cmd->code), cmd->code,
cmd->flags, cmd->qid, cmd->idx);
if (size > sizeof cmd->data) {
@@ -4228,7 +4489,7 @@
ring->cur = (ring->cur + 1) % IWN_TX_RING_COUNT;
IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur);
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_CMD, "->%s: end\n",__func__);
return async ? 0 : msleep(desc, &sc->sc_mtx, PCATCH, "iwncmd", hz);
}
@@ -4267,6 +4528,10 @@
static int
iwn_set_link_quality(struct iwn_softc *sc, struct ieee80211_node *ni)
{
+
+ DPRINTF(sc,IWN_DEBUG_RESET,"Disabled %s reached\n",__func__);
+ return 0;
+
#define RV(v) ((v) & IEEE80211_RATE_VAL)
struct iwn_node *wn = (void *)ni;
struct ieee80211_rateset *rs = &ni->ni_rates;
@@ -4334,11 +4599,13 @@
uint8_t txant;
int i, error;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s: begin\n",__func__);
+ sc->rxon = &sc->rx_on[IWN_RXON_BSS_CTX];
+
memset(&node, 0, sizeof node);
IEEE80211_ADDR_COPY(node.macaddr, ifp->if_broadcastaddr);
- node.id = sc->broadcast_id;
+ node.id = IWN_BROADCAST_ID;
DPRINTF(sc, IWN_DEBUG_RESET, "%s: adding broadcast node\n", __func__);
if ((error = ops->add_node(sc, &node, async)) != 0)
return error;
@@ -4347,7 +4614,7 @@
txant = IWN_LSB(sc->txchainmask);
memset(&linkq, 0, sizeof linkq);
- linkq.id = sc->broadcast_id;
+ linkq.id = IWN_BROADCAST_ID;
linkq.antmsk_1stream = txant;
linkq.antmsk_2stream = IWN_ANT_AB;
linkq.ampdu_max = 64;
@@ -4365,7 +4632,7 @@
linkq.retry[i] = linkq.retry[0];
}
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s: end\n",__func__);
return iwn_cmd(sc, IWN_CMD_LINK_QUALITY, &linkq, sizeof linkq, async);
}
@@ -4409,23 +4676,31 @@
/* Ignore */
}
+
static void
-iwn_set_led(struct iwn_softc *sc, uint8_t which, uint8_t off, uint8_t on)
+iwn_set_led(struct iwn_softc *sc, uint8_t which, uint8_t off, uint8_t on, uint8_t mode)
{
struct iwn_cmd_led led;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_LED, "->Doing %s\n", __func__);
/* Clear microcode LED ownership. */
IWN_CLRBITS(sc, IWN_LED, IWN_LED_BSM_CTRL);
led.which = which;
- led.unit = htole32(10000); /* on/off in unit of 100ms */
+
+ if(mode == IWN_LED_SLOW_BLINK)
+ led.unit = htole32(IWN_LED_UNIT * 5); /* on/off in unit of 10ms */
+ else
+ led.unit = htole32(IWN_LED_UNIT);
+
led.off = off;
- led.on = on;
+ led.on = on;
+
(void)iwn_cmd(sc, IWN_CMD_SET_LED, &led, sizeof led, 1);
}
+
/*
* Set the critical temperature at which the firmware will stop the radio
* and notify us.
@@ -4434,21 +4709,30 @@
iwn_set_critical_temp(struct iwn_softc *sc)
{
struct iwn_critical_temp crit;
- int32_t temp;
+ int32_t ct_enter,ct_exit;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->Doing %s\n", __func__);
IWN_WRITE(sc, IWN_UCODE_GP1_CLR, IWN_UCODE_GP1_CTEMP_STOP_RF);
- if (sc->hw_type == IWN_HW_REV_TYPE_5150)
- temp = (IWN_CTOK(110) - sc->temp_off) * -5;
- else if (sc->hw_type == IWN_HW_REV_TYPE_4965)
- temp = IWN_CTOK(110);
- else
- temp = 110;
+ ct_enter = IWN_CT_KILL_THRESHOLD;
+ ct_exit = IWN_CT_KILL_EXIT_THRESHOLD;
+
+ if (sc->hw_type == IWN_HW_REV_TYPE_5150) {
+ ct_enter = (IWN_CTOK(IWN_CT_KILL_THRESHOLD) - sc->temp_off) * -5;
+ ct_exit = 0;
+ } else if (sc->hw_type == IWN_HW_REV_TYPE_4965) {
+ ct_enter = IWN_CTOK(IWN_CT_KILL_THRESHOLD);
+ ct_exit = 0;
+ } else {
+ ct_enter = IWN_CT_KILL_THRESHOLD;
+ ct_exit = IWN_CT_KILL_EXIT_THRESHOLD;
+ }
+
memset(&crit, 0, sizeof crit);
- crit.tempR = htole32(temp);
- DPRINTF(sc, IWN_DEBUG_RESET, "setting critical temp to %d\n", temp);
+ crit.tempR = htole32(ct_enter);
+ crit.tempM = htole32(ct_exit);
+ DPRINTF(sc, IWN_DEBUG_RESET, "setting critical temp to %d and exit to %d \n", ct_enter,ct_exit);
return iwn_cmd(sc, IWN_CMD_SET_CRITICAL_TEMP, &crit, sizeof crit, 0);
}
@@ -4457,9 +4741,9 @@
{
struct iwn_cmd_timing cmd;
uint64_t val, mod;
+
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->Doing %s\n", __func__);
- DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
-
memset(&cmd, 0, sizeof cmd);
memcpy(&cmd.tstamp, ni->ni_tstamp.data, sizeof (uint64_t));
cmd.bintval = htole16(ni->ni_intval);
@@ -4470,10 +4754,12 @@
mod = le64toh(cmd.tstamp) % val;
cmd.binitval = htole32((uint32_t)(val - mod));
+// cmd.dtim_period=1; //XXX It's defined in linux kernel
+
DPRINTF(sc, IWN_DEBUG_RESET, "timing bintval=%u tstamp=%ju, init=%u\n",
- ni->ni_intval, le64toh(cmd.tstamp), (uint32_t)(val - mod));
+ le16toh(cmd.bintval), le64toh(cmd.tstamp), (uint32_t)(val - mod));
- return iwn_cmd(sc, IWN_CMD_TIMING, &cmd, sizeof cmd, 1);
+ return iwn_cmd(sc, IWN_CMD_TIMING | IWN_DEBUG_RESET, &cmd, sizeof cmd, 0);
}
static void
@@ -4482,7 +4768,7 @@
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_CALIBRATE, "->Doing %s\n", __func__);
/* Adjust TX power if need be (delta >= 3 degC). */
DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s: temperature %d->%d\n",
@@ -4519,8 +4805,9 @@
int i, c, grp, maxpwr;
uint8_t chan;
+ sc->rxon = &sc->rx_on[IWN_RXON_BSS_CTX];
/* Retrieve current channel from last RXON. */
- chan = sc->rxon.chan;
+ chan = sc->rxon->chan;
DPRINTF(sc, IWN_DEBUG_RESET, "setting TX power for channel %d\n",
chan);
@@ -4649,6 +4936,11 @@
#undef fdivround
}
+/*
+ * Set TX power for current channel (each rate has its own power settings).
+ * This function takes into account the regulatory information from EEPROM,
+ * the current temperature and the current voltage.
+ */
static int
iwn5000_set_txpower(struct iwn_softc *sc, struct ieee80211_channel *ch,
int async)
@@ -4655,7 +4947,7 @@
{
struct iwn5000_cmd_txpower cmd;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_TXPOW, "->Doing %s\n", __func__);
/*
* TX power calibration is handled automatically by the firmware
@@ -4679,7 +4971,7 @@
uint8_t mask, agc;
int rssi;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RECV, "->Doing %s\n", __func__);
mask = (le16toh(phy->antenna) >> 4) & IWN_ANT_ABC;
agc = (le16toh(phy->agc) >> 7) & 0x7f;
@@ -4706,7 +4998,7 @@
uint8_t agc;
int rssi;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RECV, "->Doing %s\n", __func__);
agc = (le32toh(phy->agc) >> 9) & 0x7f;
@@ -4775,7 +5067,7 @@
{
int32_t temp;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_CALIBRATE, "->Doing %s\n", __func__);
/*
* Temperature is not used by the driver for 5000 Series because
@@ -4786,6 +5078,8 @@
temp = (temp / -5) + sc->temp_off;
temp = IWN_KTOC(temp);
}
+ DPRINTF(sc,IWN_DEBUG_CALIBRATE,"Temperature %d\n",temp);
+ //XXX: handle thermal throttling state machine
return temp;
}
@@ -4797,10 +5091,9 @@
{
struct iwn_ops *ops = &sc->ops;
struct iwn_calib_state *calib = &sc->calib;
- uint32_t flags;
int error;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->Doing %s\n", __func__);
/* Reset calibration state machine. */
memset(calib, 0, sizeof (*calib));
@@ -4811,9 +5104,10 @@
calib->ofdm_mrc_x1 = sc->limits->min_ofdm_mrc_x1;
calib->ofdm_x4 = sc->limits->min_ofdm_x4;
calib->ofdm_mrc_x4 = sc->limits->min_ofdm_mrc_x4;
- calib->cck_x4 = 125;
+ calib->cck_x4 = sc->limits->min_cck_x4;
calib->cck_mrc_x4 = sc->limits->min_cck_mrc_x4;
calib->energy_cck = sc->limits->energy_cck;
+ calib->corr_barker_mrc = sc->limits->min_corr_barker_mrc;
/* Write initial sensitivity. */
if ((error = iwn_send_sensitivity(sc)) != 0)
@@ -4824,10 +5118,7 @@
return error;
/* Request statistics at each beacon interval. */
- flags = 0;
- DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s: sending request for statistics\n",
- __func__);
- return iwn_cmd(sc, IWN_CMD_GET_STATISTICS, &flags, sizeof flags, 1);
+ return iwn_set_statistics_request(sc,true,false,1);
}
/*
@@ -4846,7 +5137,7 @@
uint32_t val;
int i;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_CALIBRATE, "->%s begin\n", __func__);
/* Accumulate RSSI and noise for all 3 antennas. */
for (i = 0; i < 3; i++) {
@@ -4879,8 +5170,8 @@
#ifdef notyet
/* XXX Disable RX chains with no antennas connected. */
- sc->rxon.rxchain = htole16(IWN_RXCHAIN_SEL(sc->chainmask));
- (void)iwn_cmd(sc, IWN_CMD_RXON, &sc->rxon, sc->rxonsz, 1);
+ sc->rxon->rxchain = htole16(IWN_RXCHAIN_SEL(sc->chainmask));
+ (void)iwn_cmd(sc, IWN_CMD_RXON, sc->rxon, sc->rxonsz, 1);
#endif
/* Enable power-saving mode if requested by user. */
@@ -4887,7 +5178,7 @@
if (ic->ic_flags & IEEE80211_F_PMGTON)
(void)iwn_set_pslevel(sc, 0, 3, 1);
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_CALIBRATE, "->%s: end\n",__func__);
}
@@ -4911,7 +5202,7 @@
{
struct iwn_phy_calib cmd;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_CALIBRATE, "->Doing %s\n", __func__);
memset(&cmd, 0, sizeof cmd);
cmd.code = sc->reset_noise_gain;
@@ -4929,7 +5220,7 @@
struct iwn_phy_calib_gain cmd;
int i, delta, noise;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_CALIBRATE, "->Doing %s\n", __func__);
/* Get minimal noise among connected antennas. */
noise = INT_MAX; /* NB: There's at least one antenna. */
@@ -4964,7 +5255,7 @@
struct iwn_phy_calib_gain cmd;
int i, ant, div, delta;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_CALIBRATE, "->Doing %s\n", __func__);
/* We collected 20 beacons and !=6050 need a 1.5 factor. */
div = (sc->hw_type == IWN_HW_REV_TYPE_6050) ? 20 : 30;
@@ -5024,11 +5315,11 @@
uint8_t noise[3], noise_ref;
int i, needs_update = 0;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_CALIBRATE, "->%s begin\n", __func__);
/* Check that we've been enabled long enough. */
if ((rxena = le32toh(stats->general.load)) == 0){
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end not so long\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_CALIBRATE, "->%s end not so long\n", __func__);
return;
}
@@ -5149,7 +5440,7 @@
if (needs_update)
(void)iwn_send_sensitivity(sc);
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_CALIBRATE, "->%s: end\n",__func__);
#undef dec
#undef inc
@@ -5170,15 +5461,15 @@
cmd.corr_ofdm_mrc_x1 = htole16(calib->ofdm_mrc_x1);
cmd.corr_ofdm_x4 = htole16(calib->ofdm_x4);
cmd.corr_ofdm_mrc_x4 = htole16(calib->ofdm_mrc_x4);
- cmd.energy_ofdm = htole16(sc->limits->energy_ofdm);
- cmd.energy_ofdm_th = htole16(62);
+ cmd.energy_ofdm = htole16(calib->energy_ofdm);
+ cmd.energy_ofdm_th = htole16(62); //Value doesn't change in linux Kernel
/* CCK modulation. */
cmd.corr_cck_x4 = htole16(calib->cck_x4);
cmd.corr_cck_mrc_x4 = htole16(calib->cck_mrc_x4);
cmd.energy_cck = htole16(calib->energy_cck);
/* Barker modulation: use default values. */
- cmd.corr_barker = htole16(190);
- cmd.corr_barker_mrc = htole16(390);
+ cmd.corr_barker = htole16(190); //Value doesn't change in linux Kernel
+ cmd.corr_barker_mrc = htole16(calib->corr_barker_mrc);
DPRINTF(sc, IWN_DEBUG_CALIBRATE,
"%s: set sensitivity %d/%d/%d/%d/%d/%d/%d\n", __func__,
@@ -5205,6 +5496,8 @@
/*
* Set STA mode power saving level (between 0 and 5).
* Level 0 is CAM (Continuously Aware Mode), 5 is for maximum power saving.
+ * DTIM value passed in will if so configured, be ignored and taken from
+ * the value set at the AP.
*/
static int
iwn_set_pslevel(struct iwn_softc *sc, int dtim, int level, int async)
@@ -5213,8 +5506,25 @@
const struct iwn_pmgt *pmgt;
uint32_t max, skip_dtim;
uint32_t reg;
- int i;
+ int i, retval;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+ if(!TAILQ_EMPTY(&ic->ic_vaps)) {
+ /* At present the driver supports only a single vap. */
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+
+ /* XXX confirm PS level setting validity for various modes */
+ if(vap->iv_opmode == IEEE80211_M_HOSTAP ||
+ vap->iv_opmode == IEEE80211_M_MONITOR)
+ return 0;
+
+ #ifdef IWN_DTIM_INDICATES_UNICAST_PENDING_AT_AP
+ if (vap->iv_state == IEEE80211_S_RUN)
+ dtim = vap->iv_bss->ni_dtim_period;
+ #endif
+ }
+
DPRINTF(sc, IWN_DEBUG_PWRSAVE,
"%s: dtim=%d, level=%d, async=%d\n",
__func__,
@@ -5221,7 +5531,7 @@
dtim,
level,
async);
-
+
/* Select which PS parameters to use. */
if (dtim <= 2)
pmgt = &iwn_pmgt[0][level];
@@ -5232,7 +5542,7 @@
memset(&cmd, 0, sizeof cmd);
if (level != 0) /* not CAM */
- cmd.flags |= htole16(IWN_PS_ALLOW_SLEEP);
+ cmd.flags |= htole16(IWN_PS_ALLOW_SLEEP)|htole16(IWN_PS_ADVANCED_PM);
if (level == 5)
cmd.flags |= htole16(IWN_PS_FAST_PD);
/* Retrieve PCIe Active State Power Management (ASPM). */
@@ -5259,9 +5569,18 @@
for (i = 0; i < 5; i++)
cmd.intval[i] = htole32(MIN(max, pmgt->intval[i]));
- DPRINTF(sc, IWN_DEBUG_RESET, "setting power saving level to %d\n",
+ DPRINTF(sc, IWN_DEBUG_PWRSAVE, "setting power saving level to %d\n",
level);
- return iwn_cmd(sc, IWN_CMD_SET_POWER_MODE, &cmd, sizeof cmd, async);
+ retval = iwn_cmd(sc, IWN_CMD_SET_POWER_MODE, &cmd, sizeof cmd, async);
+ /*
+ * XXX: update current_pwrsave_level using completion notification
+ * in case of async mode
+ */
+ if(retval==0)
+ sc->current_pwrsave_level = level;
+
+ return retval;
+
}
static int
@@ -5286,26 +5605,63 @@
0xcc00ff28, 0x0000aaaa, 0xcc00aaaa, 0x0000aaaa,
0xc0004000, 0x00004000, 0xf0005000, 0xf0005000,
};
+
struct iwn6000_btcoex_config btconfig;
+ struct iwn2000_btcoex_config btconfig2k;
struct iwn_btcoex_priotable btprio;
struct iwn_btcoex_prot btprot;
int error, i;
-
+ uint8_t flags;
+
memset(&btconfig, 0, sizeof btconfig);
- btconfig.flags = 145;
- btconfig.max_kill = 5;
- btconfig.bt3_t7_timer = 1;
- btconfig.kill_ack = htole32(0xffff0000);
- btconfig.kill_cts = htole32(0xffff0000);
- btconfig.sample_time = 2;
- btconfig.bt3_t2_timer = 0xc;
- for (i = 0; i < 12; i++)
- btconfig.lookup_table[i] = htole32(btcoex_3wire[i]);
- btconfig.valid = htole16(0xff);
- btconfig.prio_boost = 0xf0;
- DPRINTF(sc, IWN_DEBUG_RESET,
- "%s: configuring advanced bluetooth coexistence\n", __func__);
- error = iwn_cmd(sc, IWN_CMD_BT_COEX, &btconfig, sizeof(btconfig), 1);
+ memset(&btconfig2k, 0, sizeof btconfig2k);
+
+ flags = IWN_BT_FLAG_COEX6000_MODE_3W << IWN_BT_FLAG_COEX6000_MODE_SHIFT; // Done as is in linux kernel 3.2
+
+ if (sc->base_params->bt_sco_disable)
+ flags &= ~IWN_BT_FLAG_SYNC_2_BT_DISABLE;
+ else
+ flags |= IWN_BT_FLAG_SYNC_2_BT_DISABLE;
+
+ flags |= IWN_BT_FLAG_COEX6000_CHAN_INHIBITION;
+
+
+ /* Default flags result is 145 as old value */
+
+ /* Flags value has to be review. Values must change if we which to disable it */
+ if (sc->base_params->bt_session_2) {
+ btconfig2k.flags = flags;
+ btconfig2k.max_kill = 5;
+ btconfig2k.bt3_t7_timer = 1;
+ btconfig2k.kill_ack = htole32(0xffff0000);
+ btconfig2k.kill_cts = htole32(0xffff0000);
+ btconfig2k.sample_time = 2;
+ btconfig2k.bt3_t2_timer = 0xc;
+
+ for (i = 0; i < 12; i++)
+ btconfig2k.lookup_table[i] = htole32(btcoex_3wire[i]);
+ btconfig2k.valid = htole16(0xff);
+ btconfig2k.prio_boost = htole32(0xf0);
+ DPRINTF(sc, IWN_DEBUG_RESET,
+ "%s: configuring advanced bluetooth coexistence session 2, flags : 0X%x\n", __func__,flags);
+ error = iwn_cmd(sc, IWN_CMD_BT_COEX, &btconfig2k, sizeof(btconfig2k), 1);
+ } else {
+ btconfig.flags = flags;
+ btconfig.max_kill = 5;
+ btconfig.bt3_t7_timer = 1;
+ btconfig.kill_ack = htole32(0xffff0000);
+ btconfig.kill_cts = htole32(0xffff0000);
+ btconfig.sample_time = 2;
+ btconfig.bt3_t2_timer = 0xc;
+
+ for (i = 0; i < 12; i++)
+ btconfig.lookup_table[i] = htole32(btcoex_3wire[i]);
+ btconfig.valid = htole16(0xff);
+ btconfig.prio_boost = 0xf0;
+ DPRINTF(sc, IWN_DEBUG_RESET,
+ "%s: configuring advanced bluetooth coexistence, flags : 0X%x\n", __func__,flags);
+ error = iwn_cmd(sc, IWN_CMD_BT_COEX, &btconfig, sizeof(btconfig), 1);
+ }
if (error != 0)
return error;
@@ -5336,19 +5692,6 @@
}
static int
-iwn5000_runtime_calib(struct iwn_softc *sc)
-{
- struct iwn5000_calib_config cmd;
-
- memset(&cmd, 0, sizeof cmd);
- cmd.ucode.once.enable = 0xffffffff;
- cmd.ucode.once.start = IWN5000_CALIB_DC;
- DPRINTF(sc, IWN_DEBUG_CALIBRATE,
- "%s: configuring runtime calibration\n", __func__);
- return iwn_cmd(sc, IWN5000_CMD_CALIB_CONFIG, &cmd, sizeof(cmd), 0);
-}
-
-static int
iwn_config(struct iwn_softc *sc)
{
struct iwn_ops *ops = &sc->ops;
@@ -5357,34 +5700,47 @@
uint32_t txmask;
uint16_t rxchain;
int error;
+
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s begin\n", __func__);
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
-
- if (sc->hw_type == IWN_HW_REV_TYPE_6005) {
- /* Set radio temperature sensor offset. */
+ if ((sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET) && (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2)) {
+ device_printf(sc->sc_dev,"%s: temp_offset and temp_offsetv2 are exclusive each together. Review NIC config file. Conf : 0x%08x Flags : 0x%08x \n", __func__,sc->base_params->calib_need,(IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET | IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2));
+ return EINVAL;
+ }
+ /* Compute temperature calib if needed. Will be send by send calib */
+ if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET) {
error = iwn5000_temp_offset_calib(sc);
if (error != 0) {
device_printf(sc->sc_dev,
- "%s: could not set temperature offset\n", __func__);
+ "%s: could not compute temperature offset\n", __func__);
return error;
}
- }
-
- if (sc->hw_type == IWN_HW_REV_TYPE_6050) {
- /* Configure runtime DC calibration. */
- error = iwn5000_runtime_calib(sc);
+ } else if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2) {
+ error = iwn5000_temp_offset_calibv2(sc);
if (error != 0) {
device_printf(sc->sc_dev,
- "%s: could not configure runtime calibration\n",
- __func__);
+ "%s: could not compute temperature offset v2\n", __func__);
return error;
}
}
+ /* Configure bluetooth coexistence. */
+ if (sc->base_params->advanced_bt_coexist)
+ error = iwn_send_advanced_btcoex(sc);
+ else
+ error = iwn_send_btcoex(sc);
+
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "%s: could not configure bluetooth coexistence, error %d\n",
+ __func__, error);
+ return error;
+ }
+
/* Configure valid TX chains for >=5000 Series. */
if (sc->hw_type != IWN_HW_REV_TYPE_4965) {
txmask = htole32(sc->txchainmask);
- DPRINTF(sc, IWN_DEBUG_RESET,
+ DPRINTF(sc, IWN_DEBUG_RESET ,
"%s: configuring valid TX chains 0x%x\n", __func__, txmask);
error = iwn_cmd(sc, IWN5000_CMD_TX_ANT_CONFIG, &txmask,
sizeof txmask, 0);
@@ -5396,34 +5752,24 @@
}
}
- /* Configure bluetooth coexistence. */
- if (sc->sc_flags & IWN_FLAG_ADV_BTCOEX)
- error = iwn_send_advanced_btcoex(sc);
- else
- error = iwn_send_btcoex(sc);
- if (error != 0) {
- device_printf(sc->sc_dev,
- "%s: could not configure bluetooth coexistence, error %d\n",
- __func__, error);
- return error;
- }
-
+
/* Set mode, channel, RX filter and enable RX. */
- memset(&sc->rxon, 0, sizeof (struct iwn_rxon));
- IEEE80211_ADDR_COPY(sc->rxon.myaddr, IF_LLADDR(ifp));
- IEEE80211_ADDR_COPY(sc->rxon.wlap, IF_LLADDR(ifp));
- sc->rxon.chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
- sc->rxon.flags = htole32(IWN_RXON_TSF | IWN_RXON_CTS_TO_SELF);
+ sc->rxon = &sc->rx_on[IWN_RXON_BSS_CTX];
+ memset(sc->rxon, 0, sizeof (struct iwn_rxon));
+ IEEE80211_ADDR_COPY(sc->rxon->myaddr, IF_LLADDR(ifp));
+ IEEE80211_ADDR_COPY(sc->rxon->wlap, IF_LLADDR(ifp));
+ sc->rxon->chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
+ sc->rxon->flags = htole32(IWN_RXON_TSF | IWN_RXON_CTS_TO_SELF);
if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
- sc->rxon.flags |= htole32(IWN_RXON_AUTO | IWN_RXON_24GHZ);
+ sc->rxon->flags |= htole32(IWN_RXON_AUTO | IWN_RXON_24GHZ);
switch (ic->ic_opmode) {
case IEEE80211_M_STA:
- sc->rxon.mode = IWN_MODE_STA;
- sc->rxon.filter = htole32(IWN_FILTER_MULTICAST);
+ sc->rxon->mode = IWN_MODE_STA;
+ sc->rxon->filter = htole32(IWN_FILTER_MULTICAST);
break;
case IEEE80211_M_MONITOR:
- sc->rxon.mode = IWN_MODE_MONITOR;
- sc->rxon.filter = htole32(IWN_FILTER_MULTICAST |
+ sc->rxon->mode = IWN_MODE_MONITOR;
+ sc->rxon->filter = htole32(IWN_FILTER_MULTICAST |
IWN_FILTER_CTL | IWN_FILTER_PROMISC);
break;
default:
@@ -5430,24 +5776,26 @@
/* Should not get there. */
break;
}
- sc->rxon.cck_mask = 0x0f; /* not yet negotiated */
- sc->rxon.ofdm_mask = 0xff; /* not yet negotiated */
- sc->rxon.ht_single_mask = 0xff;
- sc->rxon.ht_dual_mask = 0xff;
- sc->rxon.ht_triple_mask = 0xff;
+
+ sc->rxon->cck_mask = 0x0f; /* not yet negotiated */
+ sc->rxon->ofdm_mask = 0xff; /* not yet negotiated */
+ sc->rxon->ht_single_mask = 0xff;
+ sc->rxon->ht_dual_mask = 0xff;
+ sc->rxon->ht_triple_mask = 0xff;
rxchain =
IWN_RXCHAIN_VALID(sc->rxchainmask) |
IWN_RXCHAIN_MIMO_COUNT(2) |
IWN_RXCHAIN_IDLE_COUNT(2);
- sc->rxon.rxchain = htole16(rxchain);
+ sc->rxon->rxchain = htole16(rxchain);
+
DPRINTF(sc, IWN_DEBUG_RESET, "%s: setting configuration\n", __func__);
- error = iwn_cmd(sc, IWN_CMD_RXON, &sc->rxon, sc->rxonsz, 0);
+ error = iwn_cmd(sc, IWN_CMD_RXON, sc->rxon, sc->rxonsz, 0);
if (error != 0) {
device_printf(sc->sc_dev, "%s: RXON command failed\n",
__func__);
return error;
}
-
+
if ((error = iwn_add_broadcast_node(sc, 0)) != 0) {
device_printf(sc->sc_dev, "%s: could not add broadcast node\n",
__func__);
@@ -5467,14 +5815,24 @@
return error;
}
- /* Set power saving level to CAM during initialization. */
- if ((error = iwn_set_pslevel(sc, 0, 0, 0)) != 0) {
+ /*
+ * Any vap's iv_flags are cloned from ic->ic_flags. Setting the flags
+ * on ic will allow a vap to get the correct powersave level once
+ * it is created.
+ */
+ if(sc->desired_pwrsave_level!=IWN_POWERSAVE_LVL_NONE)
+ ic->ic_flags |= IEEE80211_F_PMGTON;
+ else
+ ic->ic_flags &= ~IEEE80211_F_PMGTON;
+
+ if ((error = iwn_set_pslevel(sc, IWN_POWERSAVE_DTIM_VOIP_COMPATIBLE,
+ sc->desired_pwrsave_level, 0)) != 0) {
device_printf(sc->sc_dev,
"%s: could not set power saving level\n", __func__);
return error;
}
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_RESET, "->%s: end\n",__func__);
return 0;
}
@@ -5509,9 +5867,20 @@
uint16_t rxchain;
uint8_t txant;
int buflen, error;
+ uint8_t new_scan_threshold;
+ struct iwn_eeprom_chan *channel;
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+
+ struct ieee80211vap *vap = ni->ni_vap;
+ struct iwn_vap *ivp = IWN_VAP(vap);
+
+ if(ivp->ctx == IWN_RXON_BSS_CTX)
+ sc->rxon = &sc->rx_on[IWN_RXON_BSS_CTX];
+ else if(ivp->ctx == IWN_RXON_PAN_CTX)
+ sc->rxon = &sc->rx_on[IWN_RXON_PAN_CTX];
+
buf = malloc(IWN_SCAN_MAXSZ, M_DEVBUF, M_NOWAIT | M_ZERO);
if (buf == NULL) {
device_printf(sc->sc_dev,
@@ -5543,7 +5912,11 @@
tx = (struct iwn_cmd_data *)(hdr + 1);
tx->flags = htole32(IWN_TX_AUTO_SEQ);
- tx->id = sc->broadcast_id;
+ if(ivp->ctx == IWN_RXON_PAN_CTX)
+ tx->id = IWN_PAN_BCAST_ID;
+ else
+ tx->id = IWN_BROADCAST_ID;
+
tx->lifetime = htole32(IWN_LIFETIME_INFINITE);
if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) {
@@ -5553,7 +5926,7 @@
} else {
hdr->flags = htole32(IWN_RXON_24GHZ | IWN_RXON_AUTO);
if (sc->hw_type == IWN_HW_REV_TYPE_4965 &&
- sc->rxon.associd && sc->rxon.chan > 14)
+ sc->rxon->associd && sc->rxon->chan > 14)
tx->rate = htole32(0xd);
else {
/* Send probe requests at 1Mbps. */
@@ -5580,7 +5953,7 @@
IEEE80211_FC0_SUBTYPE_PROBE_REQ;
wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
IEEE80211_ADDR_COPY(wh->i_addr1, ifp->if_broadcastaddr);
- IEEE80211_ADDR_COPY(wh->i_addr2, IF_LLADDR(ifp));
+ IEEE80211_ADDR_COPY(wh->i_addr2, ivp->macaddr);
IEEE80211_ADDR_COPY(wh->i_addr3, ifp->if_broadcastaddr);
*(uint16_t *)&wh->i_dur[0] = 0; /* filled by HW */
*(uint16_t *)&wh->i_seq[0] = 0; /* filled by HW */
@@ -5602,36 +5975,65 @@
chan->flags = 0;
if (ss->ss_nssid > 0)
chan->flags |= htole32(IWN_CHAN_NPBREQS(1));
- chan->dsp_gain = 0x6e;
- if (IEEE80211_IS_CHAN_5GHZ(c) &&
- !(c->ic_flags & IEEE80211_CHAN_PASSIVE)) {
- chan->rf_gain = 0x3b;
- chan->active = htole16(24);
- chan->passive = htole16(110);
- chan->flags |= htole32(IWN_CHAN_ACTIVE);
- } else if (IEEE80211_IS_CHAN_5GHZ(c)) {
- chan->rf_gain = 0x3b;
- chan->active = htole16(24);
- if (sc->rxon.associd)
- chan->passive = htole16(78);
+ /*
+ * If active scanning is requested but a certain channel is
+ * marked passive, we can do active scanning if we detect
+ * transmissions.
+ *
+ * There is an issue with some firmware versions that triggers
+ * a sysassert on a "good CRC threshold" of zero (== disabled),
+ * on a radar channel even though this means that we should NOT
+ * send probes.
+ *
+ * The "good CRC threshold" is the number of frames that we
+ * need to receive during our dwell time on a channel before
+ * sending out probes -- setting this to a huge value will
+ * mean we never reach it, but at the same time work around
+ * the aforementioned issue. Thus use IWN_SCAN_CRC_TH_NEVER
+ * here instead of IWN_SCAN_CRC_TH_DISABLED.
+ *
+ * This was fixed in later versions along with some other
+ * scan changes, and the threshold behaves as a flag in those
+ * versions.
+ */
+
+ channel = iwn_find_eeprom_channel(sc, c);
+ if (channel == NULL) {
+ if_printf(ic->ic_ifp,
+ "%s: invalid channel %u freq %u/0x%x\n",
+ __func__, c->ic_ieee, c->ic_freq, c->ic_flags);
+ return EINVAL;
+ }
+
+ new_scan_threshold = ((sc->tlv_feature_flags &
+ (1<<IWN_FW_TLV_FLAGS_NEW_SCAN_BITPOS)) >> IWN_FW_TLV_FLAGS_NEW_SCAN_BITPOS);
+
+ /* Selection criteria for Active/Passive scanning */
+ if ((ss->ss_nssid == 0) || ((channel->flags & IWN_EEPROM_CHAN_ACTIVE) == 0) ||
+ (c->ic_flags & IEEE80211_CHAN_PASSIVE)) {
+ chan->flags |= htole32(IWN_CHAN_PASSIVE);
+ if (new_scan_threshold == 1)
+ hdr->crc_threshold = IWN_SCAN_CRC_TH_DISABLED;
else
- chan->passive = htole16(110);
- hdr->crc_threshold = 0xffff;
- } else if (!(c->ic_flags & IEEE80211_CHAN_PASSIVE)) {
- chan->rf_gain = 0x28;
- chan->active = htole16(36);
- chan->passive = htole16(120);
+ hdr->crc_threshold = IWN_SCAN_CRC_TH_NEVER;
+ } else {
chan->flags |= htole32(IWN_CHAN_ACTIVE);
- } else {
- chan->rf_gain = 0x28;
- chan->active = htole16(36);
- if (sc->rxon.associd)
- chan->passive = htole16(88);
- else
- chan->passive = htole16(120);
- hdr->crc_threshold = 0xffff;
+ hdr->crc_threshold = IWN_SCAN_CRC_TH_DEFAULT;
}
+
+ chan->dsp_gain = 0x6e;
+ if (IEEE80211_IS_CHAN_5GHZ(c))
+ chan->rf_gain = 0x3b;
+ else
+ chan->rf_gain = 0x28;
+
+
+ chan->active = htole16(iwn_get_active_dwell(sc, c));
+ chan->passive = htole16(iwn_get_passive_dwell(sc, c));
+
+
+
DPRINTF(sc, IWN_DEBUG_STATE,
"%s: chan %u flags 0x%x rf_gain 0x%x "
"dsp_gain 0x%x active 0x%x passive 0x%x\n", __func__,
@@ -5645,6 +6047,9 @@
DPRINTF(sc, IWN_DEBUG_STATE, "sending scan command nchan=%d\n",
hdr->nchan);
+
+ sc->sc_scan_timer = IWN_SCAN_CHAN_TIMEOUT;
+
error = iwn_cmd(sc, IWN_CMD_SCAN, buf, buflen, 1);
free(buf, M_DEVBUF);
@@ -5664,31 +6069,32 @@
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+ sc->rxon = &sc->rx_on[IWN_RXON_BSS_CTX];
/* Update adapter configuration. */
- IEEE80211_ADDR_COPY(sc->rxon.bssid, ni->ni_bssid);
- sc->rxon.chan = ieee80211_chan2ieee(ic, ni->ni_chan);
- sc->rxon.flags = htole32(IWN_RXON_TSF | IWN_RXON_CTS_TO_SELF);
+ IEEE80211_ADDR_COPY(sc->rxon->bssid, ni->ni_bssid);
+ sc->rxon->chan = ieee80211_chan2ieee(ic, ni->ni_chan);
+ sc->rxon->flags = htole32(IWN_RXON_TSF | IWN_RXON_CTS_TO_SELF);
if (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
- sc->rxon.flags |= htole32(IWN_RXON_AUTO | IWN_RXON_24GHZ);
+ sc->rxon->flags |= htole32(IWN_RXON_AUTO | IWN_RXON_24GHZ);
if (ic->ic_flags & IEEE80211_F_SHSLOT)
- sc->rxon.flags |= htole32(IWN_RXON_SHSLOT);
+ sc->rxon->flags |= htole32(IWN_RXON_SHSLOT);
if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
- sc->rxon.flags |= htole32(IWN_RXON_SHPREAMBLE);
+ sc->rxon->flags |= htole32(IWN_RXON_SHPREAMBLE);
if (IEEE80211_IS_CHAN_A(ni->ni_chan)) {
- sc->rxon.cck_mask = 0;
- sc->rxon.ofdm_mask = 0x15;
+ sc->rxon->cck_mask = 0;
+ sc->rxon->ofdm_mask = 0x15;
} else if (IEEE80211_IS_CHAN_B(ni->ni_chan)) {
- sc->rxon.cck_mask = 0x03;
- sc->rxon.ofdm_mask = 0;
+ sc->rxon->cck_mask = 0x03;
+ sc->rxon->ofdm_mask = 0;
} else {
/* Assume 802.11b/g. */
- sc->rxon.cck_mask = 0x0f;
- sc->rxon.ofdm_mask = 0x15;
+ sc->rxon->cck_mask = 0x0f;
+ sc->rxon->ofdm_mask = 0x15;
}
DPRINTF(sc, IWN_DEBUG_STATE, "rxon chan %d flags %x cck %x ofdm %x\n",
- sc->rxon.chan, sc->rxon.flags, sc->rxon.cck_mask,
- sc->rxon.ofdm_mask);
- error = iwn_cmd(sc, IWN_CMD_RXON, &sc->rxon, sc->rxonsz, 1);
+ sc->rxon->chan, sc->rxon->flags, sc->rxon->cck_mask,
+ sc->rxon->ofdm_mask);
+ error = iwn_cmd(sc, IWN_CMD_RXON, sc->rxon, sc->rxonsz, 1);
if (error != 0) {
device_printf(sc->sc_dev, "%s: RXON command failed, error %d\n",
__func__, error);
@@ -5705,7 +6111,7 @@
* Reconfiguring RXON clears the firmware nodes table so we must
* add the broadcast node again.
*/
- if ((error = iwn_add_broadcast_node(sc, 1)) != 0) {
+ if ((error = iwn_add_broadcast_node(sc, 0)) != 0) {
device_printf(sc->sc_dev,
"%s: could not add broadcast node, error %d\n", __func__,
error);
@@ -5730,9 +6136,20 @@
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+ sc->rxon = &sc->rx_on[IWN_RXON_BSS_CTX];
+
+ if(sc->ctx == IWN_RXON_PAN_CTX) {
+ if ((error = iwn_set_pan_params(sc)) != 0) {
+ device_printf(sc->sc_dev,
+ "%s: iwn_set_pan_params error %d\n", __func__, error);
+ return error;
+ }
+ }
+
+
if (ic->ic_opmode == IEEE80211_M_MONITOR) {
/* Link LED blinks while monitoring. */
- iwn_set_led(sc, IWN_LED_LINK, 5, 5);
+ iwn_set_led(sc, IWN_LED_LINK, 5, 5,IWN_LED_INT_BLINK);
return 0;
}
if ((error = iwn_set_timing(sc, ni)) != 0) {
@@ -5742,26 +6159,26 @@
}
/* Update adapter configuration. */
- IEEE80211_ADDR_COPY(sc->rxon.bssid, ni->ni_bssid);
- sc->rxon.associd = htole16(IEEE80211_AID(ni->ni_associd));
- sc->rxon.chan = ieee80211_chan2ieee(ic, ni->ni_chan);
- sc->rxon.flags = htole32(IWN_RXON_TSF | IWN_RXON_CTS_TO_SELF);
+ IEEE80211_ADDR_COPY(sc->rxon->bssid, ni->ni_bssid);
+ sc->rxon->associd = htole16(IEEE80211_AID(ni->ni_associd));
+ sc->rxon->chan = ieee80211_chan2ieee(ic, ni->ni_chan);
+ sc->rxon->flags = htole32(IWN_RXON_TSF | IWN_RXON_CTS_TO_SELF);
if (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
- sc->rxon.flags |= htole32(IWN_RXON_AUTO | IWN_RXON_24GHZ);
+ sc->rxon->flags |= htole32(IWN_RXON_AUTO | IWN_RXON_24GHZ);
if (ic->ic_flags & IEEE80211_F_SHSLOT)
- sc->rxon.flags |= htole32(IWN_RXON_SHSLOT);
+ sc->rxon->flags |= htole32(IWN_RXON_SHSLOT);
if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
- sc->rxon.flags |= htole32(IWN_RXON_SHPREAMBLE);
+ sc->rxon->flags |= htole32(IWN_RXON_SHPREAMBLE);
if (IEEE80211_IS_CHAN_A(ni->ni_chan)) {
- sc->rxon.cck_mask = 0;
- sc->rxon.ofdm_mask = 0x15;
+ sc->rxon->cck_mask = 0;
+ sc->rxon->ofdm_mask = 0x15;
} else if (IEEE80211_IS_CHAN_B(ni->ni_chan)) {
- sc->rxon.cck_mask = 0x03;
- sc->rxon.ofdm_mask = 0;
+ sc->rxon->cck_mask = 0x03;
+ sc->rxon->ofdm_mask = 0;
} else {
/* Assume 802.11b/g. */
- sc->rxon.cck_mask = 0x0f;
- sc->rxon.ofdm_mask = 0x15;
+ sc->rxon->cck_mask = 0x0f;
+ sc->rxon->ofdm_mask = 0x15;
}
if (IEEE80211_IS_CHAN_HT(ni->ni_chan)) {
htflags |= IWN_RXON_HT_PROTMODE(ic->ic_curhtprotmode);
@@ -5778,11 +6195,11 @@
if (IEEE80211_IS_CHAN_HT40D(ni->ni_chan))
htflags |= IWN_RXON_HT_HT40MINUS;
}
- sc->rxon.flags |= htole32(htflags);
- sc->rxon.filter |= htole32(IWN_FILTER_BSS);
+ sc->rxon->flags |= htole32(htflags);
+ sc->rxon->filter |= htole32(IWN_FILTER_BSS);
DPRINTF(sc, IWN_DEBUG_STATE, "rxon chan %d flags %x\n",
- sc->rxon.chan, sc->rxon.flags);
- error = iwn_cmd(sc, IWN_CMD_RXON, &sc->rxon, sc->rxonsz, 1);
+ sc->rxon->chan, sc->rxon->flags);
+ error = iwn_cmd(sc, IWN_CMD_RXON, sc->rxon, sc->rxonsz, 1);
if (error != 0) {
device_printf(sc->sc_dev,
"%s: could not update configuration, error %d\n", __func__,
@@ -5820,12 +6237,13 @@
node.htflags |= htole32(IWN_NODE_HT40);
}
DPRINTF(sc, IWN_DEBUG_STATE, "%s: adding BSS node\n", __func__);
- error = ops->add_node(sc, &node, 1);
+ error = ops->add_node(sc, &node, 0);
if (error != 0) {
device_printf(sc->sc_dev,
"%s: could not add BSS node, error %d\n", __func__, error);
return error;
}
+ /*XXX Not done in iwl
DPRINTF(sc, IWN_DEBUG_STATE, "%s: setting link quality for node %d\n",
__func__, node.id);
if ((error = iwn_set_link_quality(sc, ni)) != 0) {
@@ -5841,18 +6259,26 @@
error);
return error;
}
- /* Start periodic calibration timer. */
+ // Start periodic calibration timer.
sc->calib.state = IWN_CALIB_STATE_ASSOC;
sc->calib_cnt = 0;
callout_reset(&sc->calib_to, msecs_to_ticks(500), iwn_calib_timeout,
sc);
+ */
+
/* Link LED always on while associated. */
- iwn_set_led(sc, IWN_LED_LINK, 0, 1);
+ iwn_set_led(sc, IWN_LED_LINK, 0, 1,IWN_LED_STATIC_ON);
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
- return 0;
+#ifdef IWN_DTIM_INDICATES_UNICAST_PENDING_AT_AP
+ return iwn_set_pslevel(sc, IWN_POWERSAVE_DTIM_VOIP_COMPATIBLE,
+ sc->desired_pwrsave_level, 0);
+#else
+ return 0;
+#endif
+
}
/*
@@ -5986,7 +6412,7 @@
iwn_ampdu_tx_start(struct ieee80211com *ic, struct ieee80211_node *ni,
uint8_t tid)
{
- struct ieee80211_tx_ampdu *tap = &ni->ni_tx_ampdu[tid];
+ struct ieee80211_tx_ampdu *tap = &ni->ni_tx_ampdu[TID_TO_WME_AC(tid)];
struct iwn_softc *sc = ni->ni_ic->ic_ifp->if_softc;
struct iwn_ops *ops = &sc->ops;
struct iwn_node *wn = (void *)ni;
@@ -6205,9 +6631,15 @@
{
int idx, error;
- for (idx = 0; idx < 5; idx++) {
- if (sc->calibcmd[idx].buf == NULL)
- continue; /* No results available. */
+ for (idx = 0; idx < IWN5000_PHY_CALIB_MAX_RESULT ; idx++) {
+ if (!(sc->base_params->calib_need & (1<<idx))) {
+ DPRINTF(sc,IWN_DEBUG_CALIBRATE, "No need of calib %d\n",idx);
+ continue; /* no need for this calib */
+ }
+ if (sc->calibcmd[idx].buf == NULL) {
+ DPRINTF(sc, IWN_DEBUG_CALIBRATE, "Need calib idx : %d but no available data\n",idx);
+ continue;
+ }
DPRINTF(sc, IWN_DEBUG_CALIBRATE,
"send calibration result idx=%d len=%d\n", idx,
sc->calibcmd[idx].len);
@@ -6279,11 +6711,43 @@
cmd.offset = htole16(sc->eeprom_temp);
else
cmd.offset = htole16(IWN_DEFAULT_TEMP_OFFSET);
+
+
DPRINTF(sc, IWN_DEBUG_CALIBRATE, "setting radio sensor offset to %d\n",
le16toh(cmd.offset));
return iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 0);
+
+
+
}
+static int
+iwn5000_temp_offset_calibv2(struct iwn_softc *sc)
+{
+ struct iwn5000_phy_calib_temp_offsetv2 cmd;
+
+ memset(&cmd, 0, sizeof cmd);
+ cmd.code = IWN5000_PHY_CALIB_TEMP_OFFSET;
+ cmd.ngroups = 1;
+ cmd.isvalid = 1;
+ if (sc->eeprom_temp != 0) {
+ cmd.offset_low = htole16(sc->eeprom_temp);
+ cmd.offset_high = htole16(sc->eeprom_temp_high);
+ } else {
+ cmd.offset_low = htole16(IWN_DEFAULT_TEMP_OFFSET);
+ cmd.offset_high = htole16(IWN_DEFAULT_TEMP_OFFSET);
+ }
+ cmd.burntVoltageRef = htole16(sc->eeprom_voltage);
+
+ DPRINTF(sc, IWN_DEBUG_CALIBRATE, "setting radio sensor low offset to %d, high offset to %d, voltage to %d\n",
+ le16toh(cmd.offset_low),
+ le16toh(cmd.offset_high),
+ le16toh(cmd.burntVoltageRef));
+
+ return iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 0);
+}
+
+
/*
* This function is called after the runtime firmware notifies us of its
* readiness (called in a process context).
@@ -6353,10 +6817,8 @@
/* Switch to using ICT interrupt mode. */
iwn5000_ict_reset(sc);
- if ((error = iwn_nic_lock(sc)) != 0){
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end in error\n", __func__);
+ if ((error = iwn_nic_lock(sc)) != 0)
return error;
- }
/* Clear TX scheduler state in SRAM. */
sc->sched_base = iwn_prph_read(sc, IWN_SCHED_SRAM_ADDR);
@@ -6369,7 +6831,11 @@
IWN_SETBITS(sc, IWN_FH_TX_CHICKEN, IWN_FH_TX_CHICKEN_SCHED_RETRY);
/* Enable chain mode for all queues, except command queue. */
- iwn_prph_write(sc, IWN5000_SCHED_QCHAIN_SEL, 0xfffef);
+ if(sc->sc_flags & IWN_FLAG_PAN_SUPPORT)
+ iwn_prph_write(sc, IWN5000_SCHED_QCHAIN_SEL, 0xffdff);
+ else
+ iwn_prph_write(sc, IWN5000_SCHED_QCHAIN_SEL, 0xfffef);
+
iwn_prph_write(sc, IWN5000_SCHED_AGGR_SEL, 0);
for (qid = 0; qid < IWN5000_NTXQUEUES; qid++) {
@@ -6389,32 +6855,29 @@
/* Identify TX FIFO rings (0-7). */
iwn_prph_write(sc, IWN5000_SCHED_TXFACT, 0xff);
- /* Mark TX rings (4 EDCA + cmd + 2 HCCA) as active. */
- for (qid = 0; qid < 7; qid++) {
- static uint8_t qid2fifo[] = { 3, 2, 1, 0, 7, 5, 6 };
- iwn_prph_write(sc, IWN5000_SCHED_QUEUE_STATUS(qid),
- IWN5000_TXQ_STATUS_ACTIVE | qid2fifo[qid]);
+ if(sc->sc_flags & IWN_FLAG_PAN_SUPPORT) {
+ /* Mark TX rings as active. */
+ for (qid = 0; qid < 11; qid++) {
+ static uint8_t qid2fifo[] = { 3, 2, 1, 0, 0, 4, 2, 5, 4, 7, 5 };
+ iwn_prph_write(sc, IWN5000_SCHED_QUEUE_STATUS(qid),
+ IWN5000_TXQ_STATUS_ACTIVE | qid2fifo[qid]);
+ }
+ } else {
+ /* Mark TX rings (4 EDCA + cmd + 2 HCCA) as active. */
+ for (qid = 0; qid < 7; qid++) {
+ static uint8_t qid2fifo[] = { 3, 2, 1, 0, 7, 5, 6 };
+ iwn_prph_write(sc, IWN5000_SCHED_QUEUE_STATUS(qid),
+ IWN5000_TXQ_STATUS_ACTIVE | qid2fifo[qid]);
+ }
}
iwn_nic_unlock(sc);
- /* Configure WiMAX coexistence for combo adapters. */
- error = iwn5000_send_wimax_coex(sc);
- if (error != 0) {
- device_printf(sc->sc_dev,
- "%s: could not configure WiMAX coexistence, error %d\n",
- __func__, error);
+
+ if ((error=iwn_cfg_ucode_post_alive(sc))!=0) {
+ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end in error\n", __func__);
return error;
}
- if (sc->hw_type != IWN_HW_REV_TYPE_5150) {
- /* Perform crystal calibration. */
- error = iwn5000_crystal_calib(sc);
- if (error != 0) {
- device_printf(sc->sc_dev,
- "%s: crystal calibration failed, error %d\n",
- __func__, error);
- return error;
- }
- }
+
if (!(sc->sc_flags & IWN_FLAG_CALIB_DONE)) {
/* Query calibration from the initialization firmware. */
if ((error = iwn5000_query_calibration(sc)) != 0) {
@@ -6423,6 +6886,7 @@
__func__, error);
return error;
}
+
/*
* We have the calibration results now, reboot with the
* runtime firmware (call ourselves recursively!)
@@ -6432,10 +6896,9 @@
} else {
/* Send calibration results to runtime firmware. */
error = iwn5000_send_calibration(sc);
+
}
-
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
-
+ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
return error;
}
@@ -6764,6 +7227,25 @@
sc->noise_gain = tmp + 1;
}
break;
+ case IWN_FW_TLV_PAN:
+ sc->sc_flags |= IWN_FLAG_PAN_SUPPORT;
+ DPRINTF(sc, IWN_DEBUG_RESET,"PAN Support found : %d\n", 1);
+ break;
+ case IWN_FW_TLV_FLAGS :
+ sc->tlv_feature_flags = htole32(*ptr);
+ break;
+ case IWN_FW_TLV_PBREQ_MAXLEN:
+ case IWN_FW_TLV_RUNT_EVTLOG_PTR:
+ case IWN_FW_TLV_RUNT_EVTLOG_SIZE:
+ case IWN_FW_TLV_RUNT_ERRLOG_PTR:
+ case IWN_FW_TLV_INIT_EVTLOG_PTR:
+ case IWN_FW_TLV_INIT_EVTLOG_SIZE:
+ case IWN_FW_TLV_INIT_ERRLOG_PTR:
+ case IWN_FW_TLV_WOWLAN_INST:
+ case IWN_FW_TLV_WOWLAN_DATA:
+ DPRINTF(sc, IWN_DEBUG_RESET,
+ "TLV type %d reconized but not handled\n", le16toh(tlv->type));
+ break;
default:
DPRINTF(sc, IWN_DEBUG_RESET,
"TLV type %d not handled\n", le16toh(tlv->type));
@@ -6885,9 +7367,8 @@
else
IWN_CLRBITS(sc, IWN_GIO, IWN_GIO_L0S_ENA);
- if (sc->hw_type != IWN_HW_REV_TYPE_4965 &&
- sc->hw_type <= IWN_HW_REV_TYPE_1000)
- IWN_SETBITS(sc, IWN_ANA_PLL, IWN_ANA_PLL_INIT);
+ if (sc->base_params->pll_cfg_val)
+ IWN_SETBITS(sc, IWN_ANA_PLL, sc->base_params->pll_cfg_val);
/* Wait for clock stabilization before accessing prph. */
if ((error = iwn_clock_wait(sc)) != 0)
@@ -6931,13 +7412,20 @@
static void
iwn_apm_stop(struct iwn_softc *sc)
{
+ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+
iwn_apm_stop_master(sc);
+
/* Reset the entire device. */
IWN_SETBITS(sc, IWN_RESET, IWN_RESET_SW);
DELAY(10);
/* Clear "initialization complete" bit. */
IWN_CLRBITS(sc, IWN_GP_CNTRL, IWN_GP_CNTRL_INIT_DONE);
+
+ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
+
+
}
static int
@@ -6999,13 +7487,15 @@
/* Use internal power amplifier only. */
IWN_WRITE(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_RADIO_2X2_IPA);
}
- if ((sc->hw_type == IWN_HW_REV_TYPE_6050 ||
- sc->hw_type == IWN_HW_REV_TYPE_6005) && sc->calib_ver >= 6) {
+ if (sc->base_params->additional_nic_config && sc->calib_ver >= 6) {
/* Indicate that ROM calibration version is >=6. */
IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_CALIB_VER6);
}
- if (sc->hw_type == IWN_HW_REV_TYPE_6005)
- IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_6050_1X2);
+ if (sc->base_params->additional_gp_drv_bit)
+ IWN_SETBITS(sc, IWN_GP_DRIVER, sc->base_params->additional_gp_drv_bit);
+/* if (sc->base_params->iq_invert)
+ IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_REG_BIT_RADIO_IQ_INVERT);
+*/ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
return 0;
}
@@ -7018,13 +7508,15 @@
int ntries;
DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
-
+
/* Check if hardware is ready. */
IWN_SETBITS(sc, IWN_HW_IF_CONFIG, IWN_HW_IF_CONFIG_NIC_READY);
for (ntries = 0; ntries < 5; ntries++) {
if (IWN_READ(sc, IWN_HW_IF_CONFIG) &
- IWN_HW_IF_CONFIG_NIC_READY)
- return 0;
+ IWN_HW_IF_CONFIG_NIC_READY) {
+ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
+ return 0;
+ }
DELAY(10);
}
@@ -7036,18 +7528,24 @@
break;
DELAY(10);
}
- if (ntries == 15000)
+ if (ntries == 15000) {
+ DPRINTF(sc, IWN_DEBUG_RESET, "->%s end timeout\n", __func__);
return ETIMEDOUT;
+ }
/* Hardware should be ready now. */
IWN_SETBITS(sc, IWN_HW_IF_CONFIG, IWN_HW_IF_CONFIG_NIC_READY);
for (ntries = 0; ntries < 5; ntries++) {
if (IWN_READ(sc, IWN_HW_IF_CONFIG) &
- IWN_HW_IF_CONFIG_NIC_READY)
- return 0;
+ IWN_HW_IF_CONFIG_NIC_READY) {
+ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
+ return 0;
+ }
DELAY(10);
}
+ DPRINTF(sc, IWN_DEBUG_RESET, "->%s end timeout\n", __func__);
return ETIMEDOUT;
+
}
static int
@@ -7060,7 +7558,7 @@
/* Clear pending interrupts. */
IWN_WRITE(sc, IWN_INT, 0xffffffff);
-
+
if ((error = iwn_apm_init(sc)) != 0) {
device_printf(sc->sc_dev,
"%s: could not power ON adapter, error %d\n", __func__,
@@ -7140,7 +7638,7 @@
IWN_WRITE(sc, IWN_UCODE_GP1_CLR, IWN_UCODE_GP1_RFKILL);
/* Enable shadow registers. */
- if (sc->hw_type >= IWN_HW_REV_TYPE_6000)
+ if (sc->base_params->shadow_reg_enable)
IWN_SETBITS(sc, IWN_SHADOW_REG_CTRL, 0x800fffff);
if ((error = ops->load_firmware(sc)) != 0) {
@@ -7211,6 +7709,12 @@
iwn_nic_unlock(sc);
}
DELAY(5);
+
+ if (sc->sc_led.led_cur_mode != IWN_LED_STATIC_OFF) {
+ sc->sc_led.led_cur_mode = IWN_LED_STATIC_OFF;
+ iwn_set_led(sc, IWN_LED_LINK, 1, 0, IWN_LED_STATIC_OFF);
+ }
+
/* Power OFF adapter. */
iwn_apm_stop(sc);
}
@@ -7259,7 +7763,6 @@
int error;
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
-
IWN_LOCK_ASSERT(sc);
if ((error = iwn_hw_prepare(sc)) != 0) {
@@ -7329,6 +7832,7 @@
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
+
IWN_LOCK(sc);
iwn_init_locked(sc);
IWN_UNLOCK(sc);
@@ -7345,6 +7849,7 @@
IWN_LOCK_ASSERT(sc);
sc->sc_tx_timer = 0;
+ sc->sc_scan_timer = 0;
callout_stop(&sc->watchdog_to);
callout_stop(&sc->calib_to);
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
@@ -7369,10 +7874,24 @@
{
struct ifnet *ifp = ic->ic_ifp;
struct iwn_softc *sc = ifp->if_softc;
+ struct ieee80211_scan_state *ss = ic->ic_scan;
+ struct ieee80211vap *vap = ss->ss_vap;
+
IWN_LOCK(sc);
+
+ sc->uc_scan_progress = 1;
+ if(sc->ctx == IWN_RXON_PAN_CTX)
+ iwn_set_pan_params(sc);
+
/* make the link LED blink while we're scanning */
- iwn_set_led(sc, IWN_LED_LINK, 20, 2);
+ if (vap->iv_state != IEEE80211_S_RUN) {
+ if(sc->sc_led.led_cur_mode != IWN_LED_SLOW_BLINK) {
+ sc->sc_led.led_cur_mode = IWN_LED_SLOW_BLINK;
+ iwn_set_led(sc, IWN_LED_LINK, 190, 10,IWN_LED_SLOW_BLINK);
+ }
+ }
+
IWN_UNLOCK(sc);
}
@@ -7384,12 +7903,20 @@
{
struct ifnet *ifp = ic->ic_ifp;
struct iwn_softc *sc = ifp->if_softc;
- struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ struct ieee80211_scan_state *ss = ic->ic_scan;
+ struct ieee80211vap *vap = ss->ss_vap;
+
IWN_LOCK(sc);
+
+ sc->uc_scan_progress = 0;
+ sc->sc_scan_timer = 0;
+ if(sc->ctx == IWN_RXON_PAN_CTX)
+ iwn_set_pan_params(sc);
+
if (vap->iv_state == IEEE80211_S_RUN) {
- /* Set link LED to ON status if we are associated */
- iwn_set_led(sc, IWN_LED_LINK, 0, 1);
+ sc->sc_led.led_cur_mode = IWN_LED_STATIC_ON;
+ iwn_set_led(sc, IWN_LED_LINK, 0, 1,IWN_LED_STATIC_ON);
}
IWN_UNLOCK(sc);
}
@@ -7437,10 +7964,14 @@
int error;
IWN_LOCK(sc);
+ sc->sc_scan_timer = 0;
error = iwn_scan(sc);
IWN_UNLOCK(sc);
- if (error != 0)
+ if (error != 0) {
+ sc->uc_scan_progress = 0;
+ sc->sc_scan_timer = 0;
ieee80211_cancel_scan(vap);
+ }
}
/*
@@ -7467,3 +7998,1140 @@
iwn_init(sc);
ieee80211_notify_radio(ic, 1);
}
+#ifdef IWN_DEBUG
+#define IWN_DESC(x) case x: return #x
+#define COUNTOF(array) (sizeof(array) / sizeof(array[0]))
+
+/*
+ * Transate CSR code to string
+ */
+static char *iwn_get_csr_string(int csr)
+{
+ switch (csr) {
+ IWN_DESC(IWN_HW_IF_CONFIG);
+ IWN_DESC(IWN_INT_COALESCING);
+ IWN_DESC(IWN_INT);
+ IWN_DESC(IWN_INT_MASK);
+ IWN_DESC(IWN_FH_INT);
+ IWN_DESC(IWN_GPIO_IN);
+ IWN_DESC(IWN_RESET);
+ IWN_DESC(IWN_GP_CNTRL);
+ IWN_DESC(IWN_HW_REV);
+ IWN_DESC(IWN_EEPROM);
+ IWN_DESC(IWN_EEPROM_GP);
+ IWN_DESC(IWN_OTP_GP);
+ IWN_DESC(IWN_GIO);
+ IWN_DESC(IWN_GP_UCODE);
+ IWN_DESC(IWN_GP_DRIVER);
+ IWN_DESC(IWN_UCODE_GP1);
+ IWN_DESC(IWN_UCODE_GP2);
+ IWN_DESC(IWN_LED);
+ IWN_DESC(IWN_DRAM_INT_TBL);
+ IWN_DESC(IWN_GIO_CHICKEN);
+ IWN_DESC(IWN_ANA_PLL);
+ IWN_DESC(IWN_HW_REV_WA);
+ IWN_DESC(IWN_DBG_HPET_MEM);
+ default:
+ return "UNKNOWN CSR";
+ }
+}
+
+/*
+ * This function print firmawre register
+ */
+static void
+iwn_debug_register(struct iwn_softc *sc)
+{
+ int i;
+ static const uint32_t csr_tbl[] = {
+ IWN_HW_IF_CONFIG,
+ IWN_INT_COALESCING,
+ IWN_INT,
+ IWN_INT_MASK,
+ IWN_FH_INT,
+ IWN_GPIO_IN,
+ IWN_RESET,
+ IWN_GP_CNTRL,
+ IWN_HW_REV,
+ IWN_EEPROM,
+ IWN_EEPROM_GP,
+ IWN_OTP_GP,
+ IWN_GIO,
+ IWN_GP_UCODE,
+ IWN_GP_DRIVER,
+ IWN_UCODE_GP1,
+ IWN_UCODE_GP2,
+ IWN_LED,
+ IWN_DRAM_INT_TBL,
+ IWN_GIO_CHICKEN,
+ IWN_ANA_PLL,
+ IWN_HW_REV_WA,
+ IWN_DBG_HPET_MEM,
+ };
+ DPRINTF(sc, IWN_DEBUG_REGISTER,
+ "CSR values: (2nd byte of IWN_INT_COALESCING is IWN_INT_PERIODIC)%s",
+ "\n");
+ for (i = 0; i < COUNTOF(csr_tbl); i++){
+ DPRINTF(sc, IWN_DEBUG_REGISTER," %10s: 0x%08x ",
+ iwn_get_csr_string(csr_tbl[i]), IWN_READ(sc, csr_tbl[i]));
+ if ((i+1) % 3 == 0)
+ DPRINTF(sc, IWN_DEBUG_REGISTER,"%s","\n");
+ }
+ DPRINTF(sc, IWN_DEBUG_REGISTER,"%s","\n");
+}
+#endif
+
+
+/* Define specific configuration based on device id and subdevice id */
+/* pid : PCI device id */
+static int
+iwn_config_specific(struct iwn_softc *sc,uint16_t pid)
+{
+ switch(pid) {
+/* 1000 Series */
+ case IWN_DID_1000_1:
+ case IWN_DID_1000_2:
+ switch(sc->subdevice_id) {
+ case IWN_SDID_1000_1:
+ case IWN_SDID_1000_2:
+ case IWN_SDID_1000_3:
+ case IWN_SDID_1000_4:
+ case IWN_SDID_1000_5:
+ case IWN_SDID_1000_6:
+ case IWN_SDID_1000_7:
+ case IWN_SDID_1000_8:
+ case IWN_SDID_1000_9:
+ case IWN_SDID_1000_10:
+ case IWN_SDID_1000_11:
+ case IWN_SDID_1000_12:
+ sc->limits = &iwn1000_sensitivity_limits;
+ sc->base_params = &iwn_1000_base_params;
+ sc->fwname = "iwn1000fw";
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id : 0x%04x rev %d not supported (subdevice) \n",pid,sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+/* 6x00 Series */
+ case IWN_DID_6x00_2:
+ case IWN_DID_6x00_4:
+ case IWN_DID_6x00_1:
+ case IWN_DID_6x00_3:
+ sc->fwname = "iwn6000fw";
+ sc->limits = &iwn6000_sensitivity_limits;
+ switch(sc->subdevice_id) {
+
+ case IWN_SDID_6x00_1:
+ case IWN_SDID_6x00_2:
+ case IWN_SDID_6x00_8:
+ //iwl6000_3agn_cfg
+ sc->base_params = &iwn_6000_base_params;
+ break;
+ case IWN_SDID_6x00_3:
+ case IWN_SDID_6x00_6:
+ case IWN_SDID_6x00_9:
+ ////iwl6000i_2agn
+ case IWN_SDID_6x00_4:
+ case IWN_SDID_6x00_7:
+ case IWN_SDID_6x00_10:
+ //iwl6000i_2abg_cfg
+ case IWN_SDID_6x00_5:
+ //iwl6000i_2bg_cfg
+ sc->base_params = &iwn_6000i_base_params;
+ sc->sc_flags |= IWN_FLAG_INTERNAL_PA;
+ sc->txchainmask = IWN_ANT_BC;
+ sc->rxchainmask = IWN_ANT_BC;
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id : 0x%04x rev %d not supported (subdevice) \n",pid,sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+/* 6x05 Series */
+ case IWN_DID_6x05_1:
+ case IWN_DID_6x05_2:
+ switch(sc->subdevice_id) {
+ case IWN_SDID_6x05_1:
+ case IWN_SDID_6x05_4:
+ case IWN_SDID_6x05_6:
+ //iwl6005_2agn_cfg
+ case IWN_SDID_6x05_2:
+ case IWN_SDID_6x05_5:
+ case IWN_SDID_6x05_7:
+ //iwl6005_2abg_cfg
+ case IWN_SDID_6x05_3:
+ //iwl6005_2bg_cfg
+ case IWN_SDID_6x05_8:
+ case IWN_SDID_6x05_9:
+ //iwl6005_2agn_sff_cfg
+ case IWN_SDID_6x05_10:
+ //iwl6005_2agn_d_cfg
+ case IWN_SDID_6x05_11:
+ //iwl6005_2agn_mow1_cfg
+ case IWN_SDID_6x05_12:
+ //iwl6005_2agn_mow2_cfg
+ sc->fwname = "iwn6000g2afw";
+ sc->limits = &iwn6000_sensitivity_limits;
+ sc->base_params = &iwn_6000g2_base_params;
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id : 0x%04x rev %d not supported (subdevice) \n",pid,sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+/* 6x35 Series */
+ case IWN_DID_6035_1:
+ case IWN_DID_6035_2:
+ switch(sc->subdevice_id) {
+ case IWN_SDID_6035_1:
+ case IWN_SDID_6035_2:
+ case IWN_SDID_6035_3:
+ case IWN_SDID_6035_4:
+ sc->fwname = "iwn6000g2bfw";
+ sc->limits = &iwn6000_sensitivity_limits;
+ sc->base_params = &iwn_6000g2b_base_params;
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id : 0x%04x rev %d not supported (subdevice) \n",pid,sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+/* 6x50 WiFi/WiMax Series */
+ case IWN_DID_6050_1:
+ case IWN_DID_6050_2:
+ switch(sc->subdevice_id) {
+ case IWN_SDID_6050_1:
+ case IWN_SDID_6050_3:
+ case IWN_SDID_6050_5:
+ //iwl6050_2agn_cfg
+ case IWN_SDID_6050_2:
+ case IWN_SDID_6050_4:
+ case IWN_SDID_6050_6:
+ //iwl6050_2abg_cfg
+ sc->fwname = "iwn6050fw";
+ sc->txchainmask = IWN_ANT_AB;
+ sc->rxchainmask = IWN_ANT_AB;
+ sc->limits = &iwn6000_sensitivity_limits;
+ sc->base_params = &iwn_6050_base_params;
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id : 0x%04x rev %d not supported (subdevice) \n",pid,sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+/* 6150 WiFi/WiMax Series */
+ case IWN_DID_6150_1:
+ case IWN_DID_6150_2:
+ switch(sc->subdevice_id) {
+ case IWN_SDID_6150_1:
+ case IWN_SDID_6150_3:
+ case IWN_SDID_6150_5:
+ // iwl6150_bgn_cfg
+ case IWN_SDID_6150_2:
+ case IWN_SDID_6150_4:
+ case IWN_SDID_6150_6:
+ //iwl6150_bg_cfg
+ sc->fwname = "iwn6050fw";
+ sc->limits = &iwn6000_sensitivity_limits;
+ sc->base_params = &iwn_6150_base_params;
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id : 0x%04x rev %d not supported (subdevice) \n",pid,sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+/* 6030 Series and 1030 Series */
+ case IWN_DID_x030_1:
+ case IWN_DID_x030_2:
+ case IWN_DID_x030_3:
+ case IWN_DID_x030_4:
+ switch(sc->subdevice_id) {
+ case IWN_SDID_x030_1:
+ case IWN_SDID_x030_3:
+ case IWN_SDID_x030_5:
+ // iwl1030_bgn_cfg
+
+ case IWN_SDID_x030_2:
+ case IWN_SDID_x030_4:
+ case IWN_SDID_x030_6:
+ //iwl1030_bg_cfg
+
+ case IWN_SDID_x030_7:
+ case IWN_SDID_x030_10:
+ case IWN_SDID_x030_14:
+ //iwl6030_2agn_cfg
+
+ case IWN_SDID_x030_8:
+ case IWN_SDID_x030_11:
+ case IWN_SDID_x030_15:
+ // iwl6030_2bgn_cfg
+
+ case IWN_SDID_x030_9:
+ case IWN_SDID_x030_12:
+ case IWN_SDID_x030_16:
+ // iwl6030_2abg_cfg
+
+ case IWN_SDID_x030_13:
+ //iwl6030_2bg_cfg
+ sc->fwname = "iwn6000g2bfw";
+ sc->limits = &iwn6000_sensitivity_limits;
+ sc->base_params = &iwn_6000g2b_base_params;
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id : 0x%04x rev %d not supported (subdevice) \n",pid,sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+/* 130 Series WiFi */
+/* XXX: This series will need adjustement for rate see rx_with_siso_diversity in linux kernel */
+ case IWN_DID_130_1:
+ case IWN_DID_130_2:
+ switch(sc->subdevice_id) {
+ case IWN_SDID_130_1:
+ case IWN_SDID_130_3:
+ case IWN_SDID_130_5:
+ //iwl130_bgn_cfg
+ case IWN_SDID_130_2:
+ case IWN_SDID_130_4:
+ case IWN_SDID_130_6:
+ //iwl130_bg_cfg
+ sc->fwname = "iwn6000g2bfw";
+ sc->limits = &iwn6000_sensitivity_limits;
+ sc->base_params = &iwn_6000g2b_base_params;
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id : 0x%04x rev %d not supported (subdevice) \n",pid,sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+/* 100 Series WiFi */
+ case IWN_DID_100_1:
+ case IWN_DID_100_2:
+ switch(sc->subdevice_id) {
+ case IWN_SDID_100_1:
+ case IWN_SDID_100_2:
+ case IWN_SDID_100_3:
+ case IWN_SDID_100_4:
+ case IWN_SDID_100_5:
+ case IWN_SDID_100_6:
+ sc->limits = &iwn1000_sensitivity_limits;
+ sc->base_params = &iwn_1000_base_params;
+ sc->fwname = "iwn100fw";
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id : 0x%04x rev %d not supported (subdevice) \n",pid,sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+
+/* 2x30 Series */
+ case IWN_DID_2x30_1:
+ case IWN_DID_2x30_2:
+ switch(sc->subdevice_id) {
+ case IWN_SDID_2x30_1:
+ case IWN_SDID_2x30_3:
+ case IWN_SDID_2x30_5:
+ //iwl100_bgn_cfg
+ case IWN_SDID_2x30_2:
+ case IWN_SDID_2x30_4:
+ case IWN_SDID_2x30_6:
+ //iwl100_bg_cfg
+ sc->limits = &iwn2030_sensitivity_limits;
+ sc->base_params = &iwn2030_base_params;
+ sc->fwname = "iwn2030fw";
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id : 0x%04x rev %d not supported (subdevice) \n",pid,sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+/* 5x00 Series */
+ case IWN_DID_5x00_1:
+ case IWN_DID_5x00_2:
+ case IWN_DID_5x00_3:
+ case IWN_DID_5x00_4:
+ sc->limits = &iwn5000_sensitivity_limits;
+ sc->base_params = &iwn_default_base_params;
+ sc->fwname = "iwn5000fw";
+ switch(sc->subdevice_id) {
+ case IWN_SDID_5x00_1:
+ case IWN_SDID_5x00_2:
+ case IWN_SDID_5x00_3:
+ case IWN_SDID_5x00_4:
+ case IWN_SDID_5x00_9:
+ case IWN_SDID_5x00_10:
+ case IWN_SDID_5x00_11:
+ case IWN_SDID_5x00_12:
+ case IWN_SDID_5x00_17:
+ case IWN_SDID_5x00_18:
+ case IWN_SDID_5x00_19:
+ case IWN_SDID_5x00_20:
+ //iwl5100_agn_cfg
+ sc->txchainmask = IWN_ANT_B;
+ sc->rxchainmask = IWN_ANT_AB;
+ break;
+ case IWN_SDID_5x00_5:
+ case IWN_SDID_5x00_6:
+ case IWN_SDID_5x00_13:
+ case IWN_SDID_5x00_14:
+ case IWN_SDID_5x00_21:
+ case IWN_SDID_5x00_22:
+ //iwl5100_bgn_cfg
+ sc->txchainmask = IWN_ANT_B;
+ sc->rxchainmask = IWN_ANT_AB;
+ break;
+ case IWN_SDID_5x00_7:
+ case IWN_SDID_5x00_8:
+ case IWN_SDID_5x00_15:
+ case IWN_SDID_5x00_16:
+ case IWN_SDID_5x00_23:
+ case IWN_SDID_5x00_24:
+ //iwl5100_abg_cfg
+ sc->txchainmask = IWN_ANT_B;
+ sc->rxchainmask = IWN_ANT_AB;
+ break;
+
+ case IWN_SDID_5x00_25:
+ case IWN_SDID_5x00_26:
+ case IWN_SDID_5x00_27:
+ case IWN_SDID_5x00_28:
+ case IWN_SDID_5x00_29:
+ case IWN_SDID_5x00_30:
+ case IWN_SDID_5x00_31:
+ case IWN_SDID_5x00_32:
+ case IWN_SDID_5x00_33:
+ case IWN_SDID_5x00_34:
+ case IWN_SDID_5x00_35:
+ case IWN_SDID_5x00_36:
+ //iwl5300_agn_cfg
+ sc->txchainmask = IWN_ANT_ABC;
+ sc->rxchainmask = IWN_ANT_ABC;
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id : 0x%04x rev %d not supported (subdevice) \n",pid,sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+/* 5x50 Series */
+ case IWN_DID_5x50_1:
+ case IWN_DID_5x50_2:
+ case IWN_DID_5x50_3:
+ case IWN_DID_5x50_4:
+ sc->limits = &iwn5000_sensitivity_limits;
+ sc->base_params = &iwn_default_base_params;
+ sc->fwname = "iwn5000fw";
+ switch(sc->subdevice_id) {
+ case IWN_SDID_5x50_1:
+ case IWN_SDID_5x50_2:
+ case IWN_SDID_5x50_3:
+ //iwl5350_agn_cfg
+ sc->limits = &iwn5000_sensitivity_limits;
+ sc->base_params = &iwn_default_base_params;
+ sc->fwname = "iwn5000fw";
+ break;
+
+ case IWN_SDID_5x50_4:
+ case IWN_SDID_5x50_5:
+ case IWN_SDID_5x50_8:
+ case IWN_SDID_5x50_9:
+ case IWN_SDID_5x50_10:
+ case IWN_SDID_5x50_11:
+ //iwl5150_agn_cfg
+ case IWN_SDID_5x50_6:
+ case IWN_SDID_5x50_7:
+ case IWN_SDID_5x50_12:
+ case IWN_SDID_5x50_13:
+ //iwl5150_abg_cfg
+ sc->limits = &iwn5000_sensitivity_limits;
+ sc->fwname = "iwn5150fw";
+ sc->base_params = &iwn_5x50_base_params;
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id : 0x%04x rev %d not supported (subdevice) \n",pid,sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id : 0x%04x rev 0x%08x not supported (device) \n",pid,sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ return 0;
+}
+/*
+ * Send IWN_CMD_GET_STATISTICS to ucode.
+ * @enable: activate sending statistics from uCode
+ * @clear : ask uCode to clear internal counter
+ * @async : Sync mode for command (1= ASYNC, 0=SYNC)
+*/
+static int
+iwn_set_statistics_request(struct iwn_softc *sc,bool enable,bool clear,int async)
+{
+ struct iwn_statistics_cmd cmd;
+
+ if (enable)
+ cmd.configuration_flags= clear ? IWN_STATS_CONF_CLEAR_STATS :0;
+ else
+ cmd.configuration_flags= IWN_STATS_CONF_DISABLE_NOTIF;
+
+
+ DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s: sending request for statistics flags : 0x%x\n",
+ __func__,cmd.configuration_flags);
+ return iwn_cmd(sc, IWN_CMD_GET_STATISTICS, &cmd, sizeof cmd, async ? 1:0);
+}
+
+static int
+iwn_cfg_ucode_post_alive(struct iwn_softc *sc)
+{
+ int error;
+
+ /* Configure WiMAX coexistence for combo adapters. */
+ error = iwn5000_send_wimax_coex(sc);
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "%s: could not configure WiMAX coexistence, error %d\n",
+ __func__, error);
+ return error;
+ }
+
+ if (!(sc->base_params->no_crystal_calibration)) {
+ DPRINTF(sc, IWN_DEBUG_RESET, "Doing calib in %s\n",__func__);
+ error = iwn5000_crystal_calib(sc);
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "%s: crystal calibration failed, error %d\n",
+ __func__, error);
+ return error;
+ }
+ } else {
+ DPRINTF(sc, IWN_DEBUG_RESET, "Crystal calibration disable in %s\n",__func__);
+ }
+
+ return 0;
+}
+//----------------- NEW----------------------
+/*
+ * Handles ioctl change requests for power management state etc.
+ */
+static int iwn_iv_reset(struct ieee80211vap *vap, u_long cmd)
+{
+ int error = 0;
+ switch (cmd) {
+ case IEEE80211_IOC_POWERSAVE:{
+ struct iwn_softc * sc = (struct iwn_softc *)
+ (vap->iv_ic->ic_ifp->if_softc);
+ IWN_LOCK(sc);
+
+ /* XXX to discuss */
+ int dtim = IWN_POWERSAVE_DTIM_VOIP_COMPATIBLE;
+
+ int async = 0;
+
+ /*
+ * At present the powersave level is set to 0 (receiver
+ * continuously on) if power save is disabled, and set to
+ * IWN_POWERSAVE_LVL_VOIP_COMPATIBLE otherwise.
+ * Later the power levels 0-5 could be exposed to the user.
+ */
+ if (vap->iv_flags & IEEE80211_F_PMGTON) {
+ /*
+ * In ieee80211_vap_setup() we have:
+ * vap->iv_flags = ic->ic_flags;
+ * i.e. any vap's iv_flags initialize to ic->ic_flags.
+ * Setting the flags on ic will allow a vap to get
+ * the correct powersave level once it is created.
+ */
+ vap->iv_ic->ic_flags |= IEEE80211_F_PMGTON;
+ sc->desired_pwrsave_level =
+ IWN_POWERSAVE_LVL_VOIP_COMPATIBLE;
+ } else {
+ vap->iv_ic->ic_flags &= ~IEEE80211_F_PMGTON;
+ sc->desired_pwrsave_level = IWN_POWERSAVE_LVL_NONE;
+ }
+ error = iwn_set_pslevel(sc, dtim, sc->desired_pwrsave_level,
+ async);
+ IWN_UNLOCK(sc);
+ }
+ break;
+ default:
+ /*
+ * For unhandled ioctls, ENETRESET has to be passed back to
+ * net80211 layer, which will in turn call the function to
+ * reinitialize the entire device.
+ */
+ error = ENETRESET;
+ break;
+ }
+ return error;
+}
+
+static int
+iwn_newstate_u1(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
+{
+ struct iwn_vap *ivp = IWN_VAP(vap);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct iwn_softc *sc = ic->ic_ifp->if_softc;
+
+ int error = 0;
+
+ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+
+ DPRINTF(sc, IWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
+ ieee80211_state_name[vap->iv_state], ieee80211_state_name[nstate]);
+
+ IEEE80211_UNLOCK(ic);
+ IWN_LOCK(sc);
+ callout_stop(&sc->calib_to);
+
+ sc->rxon = &sc->rx_on[IWN_RXON_PAN_CTX];
+
+ switch (nstate) {
+ case IEEE80211_S_ASSOC:
+ if (vap->iv_state != IEEE80211_S_RUN)
+ break;
+ /* FALLTHROUGH */
+ case IEEE80211_S_AUTH:
+ if (vap->iv_state == IEEE80211_S_AUTH)
+ break;
+
+ /*
+ * !AUTH -> AUTH transition requires state reset to handle
+ * reassociations correctly.
+ */
+ sc->rxon->associd = 0;
+ sc->rxon->filter &= ~htole32(IWN_FILTER_BSS);
+ sc->calib.state = IWN_CALIB_STATE_INIT;
+
+ if ((error = iwn_auth_u1(sc, vap)) != 0) {
+ device_printf(sc->sc_dev,
+ "%s: could not move to auth state\n", __func__);
+ }
+ break;
+
+ case IEEE80211_S_SCAN:
+
+
+ if ((error = iwn_set_timing_u1(sc)) != 0) {
+ device_printf(sc->sc_dev,
+ "%s: iwn_set_timing_u1 error %d\n", __func__, error);
+ return error;
+ }
+
+ break;
+
+ case IEEE80211_S_RUN:
+
+ /*
+ * RUN -> RUN transition; Just restart the timers.
+ */
+ if (vap->iv_state == IEEE80211_S_RUN) {
+ sc->calib_cnt = 0;
+ break;
+ }
+
+ /*
+ * !RUN -> RUN requires setting the association id
+ * which is done with a firmware cmd. We also defer
+ * starting the timers until that work is done.
+ */
+ if ((error = iwn_run_u1(sc, vap)) != 0) {
+ device_printf(sc->sc_dev,
+ "%s: could not move to run state\n", __func__);
+ }
+ break;
+
+ case IEEE80211_S_INIT:
+ sc->calib.state = IWN_CALIB_STATE_INIT;
+ break;
+
+ default:
+ break;
+ }
+ IWN_UNLOCK(sc);
+ IEEE80211_LOCK(ic);
+ if (error != 0) {
+ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end in error\n", __func__);
+ return error;
+ }
+ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
+ return ivp->iv_newstate(vap, nstate, arg);
+}
+
+static int
+iwn_auth_u1(struct iwn_softc *sc, struct ieee80211vap *vap)
+{
+ struct iwn_ops *ops = &sc->ops;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211_node *ni = vap->iv_bss;
+ int error;
+ struct iwn_vap *ivp = IWN_VAP(vap);
+
+ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+
+ sc->rxon = &sc->rx_on[IWN_RXON_PAN_CTX];
+ IEEE80211_ADDR_COPY(sc->rxon->myaddr, ivp->macaddr);
+ IEEE80211_ADDR_COPY(sc->rxon->wlap, IF_LLADDR(ifp));
+ /* Update adapter configuration. */
+ IEEE80211_ADDR_COPY(sc->rxon->bssid, ni->ni_bssid);
+ sc->rxon->chan = ieee80211_chan2ieee(ic, ni->ni_chan);
+ sc->rxon->flags = htole32(IWN_RXON_TSF | IWN_RXON_CTS_TO_SELF);
+ if (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
+ sc->rxon->flags |= htole32(IWN_RXON_AUTO | IWN_RXON_24GHZ);
+ if (ic->ic_flags & IEEE80211_F_SHSLOT)
+ sc->rxon->flags |= htole32(IWN_RXON_SHSLOT);
+ if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
+ sc->rxon->flags |= htole32(IWN_RXON_SHPREAMBLE);
+ if (IEEE80211_IS_CHAN_A(ni->ni_chan)) {
+ sc->rxon->cck_mask = 0;
+ sc->rxon->ofdm_mask = 0x15;
+ } else if (IEEE80211_IS_CHAN_B(ni->ni_chan)) {
+ sc->rxon->cck_mask = 0x03;
+ sc->rxon->ofdm_mask = 0;
+ } else {
+ /* Assume 802.11b/g. */
+ sc->rxon->cck_mask = 0x0f;
+ sc->rxon->ofdm_mask = 0x15;
+ }
+ DPRINTF(sc, IWN_DEBUG_STATE, "rxon chan %d flags %x cck %x ofdm %x\n",
+ sc->rxon->chan, sc->rxon->flags, sc->rxon->cck_mask,
+ sc->rxon->ofdm_mask);
+ sc->rxon->mode = IWN_MODE_2STA;
+ error = iwn_cmd(sc, IWN_CMD_WIPAN_RXON, sc->rxon, sc->rxonsz, 0);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "%s: RXON command failed, error %d\n",
+ __func__, error);
+ return error;
+ }
+
+ /* Configuration has changed, set TX power accordingly. */
+ if ((error = ops->set_txpower(sc, ni->ni_chan, 1)) != 0) {
+ device_printf(sc->sc_dev,
+ "%s: could not set TX power, error %d\n", __func__, error);
+ return error;
+ }
+ /*
+ * Reconfiguring RXON clears the firmware nodes table so we must
+ * add the broadcast node again.
+ */
+ if ((error = iwn_add_broadcast_node_u1(sc, 0)) != 0) {
+ device_printf(sc->sc_dev,
+ "%s: could not add broadcast node, error %d\n", __func__,
+ error);
+ return error;
+ }
+ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
+
+ return 0;
+}
+
+static int
+iwn_run_u1(struct iwn_softc *sc, struct ieee80211vap *vap)
+{
+ struct iwn_ops *ops = &sc->ops;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211_node *ni = vap->iv_bss;
+ struct iwn_node_info node;
+ uint32_t htflags = 0;
+ int error;
+ struct iwn_vap *ivp = IWN_VAP(vap);
+
+ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+
+ if (ic->ic_opmode == IEEE80211_M_MONITOR) {
+ /* Link LED blinks while monitoring. */
+ return 0;
+ }
+
+ if ((error = iwn_set_timing_u1(sc)) != 0) {
+ device_printf(sc->sc_dev,
+ "%s: could not set timing, error %d\n", __func__, error);
+ }
+
+ if ((error = iwn_updateedca_u1(ic)) != 0) {
+ device_printf(sc->sc_dev,
+ "%s: iwn_updateedca_u1, error %d\n", __func__, error);
+ return error;
+ }
+
+ sc->rxon = &sc->rx_on[IWN_RXON_PAN_CTX];
+ IEEE80211_ADDR_COPY(sc->rxon->myaddr, ivp->macaddr);
+ IEEE80211_ADDR_COPY(sc->rxon->wlap, IF_LLADDR(ifp));
+ /* Update adapter configuration. */
+ IEEE80211_ADDR_COPY(sc->rxon->bssid, ni->ni_bssid);
+ sc->rxon->associd = htole16(IEEE80211_AID(ni->ni_associd));
+ sc->rxon->chan = ieee80211_chan2ieee(ic, ni->ni_chan);
+ sc->rxon->flags = htole32(IWN_RXON_TSF | IWN_RXON_CTS_TO_SELF);
+ if (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
+ sc->rxon->flags |= htole32(IWN_RXON_AUTO | IWN_RXON_24GHZ);
+ if (ic->ic_flags & IEEE80211_F_SHSLOT)
+ sc->rxon->flags |= htole32(IWN_RXON_SHSLOT);
+ if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
+ sc->rxon->flags |= htole32(IWN_RXON_SHPREAMBLE);
+ if (IEEE80211_IS_CHAN_A(ni->ni_chan)) {
+ sc->rxon->cck_mask = 0;
+ sc->rxon->ofdm_mask = 0x15;
+ } else if (IEEE80211_IS_CHAN_B(ni->ni_chan)) {
+ sc->rxon->cck_mask = 0x03;
+ sc->rxon->ofdm_mask = 0;
+ } else {
+ /* Assume 802.11b/g. */
+ sc->rxon->cck_mask = 0x0f;
+ sc->rxon->ofdm_mask = 0x15;
+ }
+ if (IEEE80211_IS_CHAN_HT(ni->ni_chan)) {
+ htflags |= IWN_RXON_HT_PROTMODE(ic->ic_curhtprotmode);
+ if (IEEE80211_IS_CHAN_HT40(ni->ni_chan)) {
+ switch (ic->ic_curhtprotmode) {
+ case IEEE80211_HTINFO_OPMODE_HT20PR:
+ htflags |= IWN_RXON_HT_MODEPURE40;
+ break;
+ default:
+ htflags |= IWN_RXON_HT_MODEMIXED;
+ break;
+ }
+ }
+ if (IEEE80211_IS_CHAN_HT40D(ni->ni_chan))
+ htflags |= IWN_RXON_HT_HT40MINUS;
+ }
+ sc->rxon->flags |= htole32(htflags);
+ sc->rxon->filter |= htole32(IWN_FILTER_BSS);
+ DPRINTF(sc, IWN_DEBUG_STATE, "rxon chan %d flags %x\n",
+ sc->rxon->chan, sc->rxon->flags);
+ sc->rxon->mode = IWN_MODE_2STA;
+ error = iwn_cmd(sc, IWN_CMD_WIPAN_RXON, sc->rxon, sc->rxonsz, 0);
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "%s: could not update configuration, error %d\n", __func__,
+ error);
+ return error;
+ }
+
+ /* Configuration has changed, set TX power accordingly. */
+ if ((error = ops->set_txpower(sc, ni->ni_chan, 1)) != 0) {
+ device_printf(sc->sc_dev,
+ "%s: could not set TX power, error %d\n", __func__, error);
+ return error;
+ }
+
+ /* Fake a join to initialize the TX rate. */
+ ((struct iwn_node *)ni)->id = IWN_STA_ID;
+ iwn_newassoc(ni, 1);
+
+ /* Add BSS node. */
+ memset(&node, 0, sizeof node);
+ node.htflags |= htole32(IWN_STA_FLAG_PAN_STATION);
+ IEEE80211_ADDR_COPY(node.macaddr, ni->ni_macaddr);
+ node.id = IWN_STA_ID;
+ if (IEEE80211_IS_CHAN_HT(ni->ni_chan)) {
+ switch (ni->ni_htcap & IEEE80211_HTCAP_SMPS) {
+ case IEEE80211_HTCAP_SMPS_ENA:
+ node.htflags |= htole32(IWN_SMPS_MIMO_DIS);
+ break;
+ case IEEE80211_HTCAP_SMPS_DYNAMIC:
+ node.htflags |= htole32(IWN_SMPS_MIMO_PROT);
+ break;
+ }
+ node.htflags |= htole32(IWN_AMDPU_SIZE_FACTOR(3) |
+ IWN_AMDPU_DENSITY(5)); /* 4us */
+ if (IEEE80211_IS_CHAN_HT40(ni->ni_chan))
+ node.htflags |= htole32(IWN_NODE_HT40);
+ }
+ DPRINTF(sc, IWN_DEBUG_STATE, "%s: adding BSS node1\n", __func__);
+ error = ops->add_node(sc, &node, 0);
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "%s: could not add BSS node1, error %d\n", __func__, error);
+ return error;
+ }
+
+ /* Setting the initial rate for node */
+ ni->ni_txrate = ni->ni_rates.rs_rates[0];
+
+ /* XXX: init rate scaling */
+
+ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
+
+ #ifdef IWN_DTIM_INDICATES_UNICAST_PENDING_AT_AP
+ return iwn_set_pslevel(sc, IWN_POWERSAVE_DTIM_VOIP_COMPATIBLE,
+ sc->desired_pwrsave_level, 0);
+ #else
+ return 0;
+ #endif
+
+}
+
+static int
+iwn_set_timing_u1(struct iwn_softc *sc)
+{
+ struct iwn_cmd_timing cmd;
+ int error = 0;
+ struct ieee80211vap *vap;
+ struct iwn_vap *ivp;
+
+ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+
+ vap = sc->ivap[IWN_RXON_PAN_CTX];
+ ivp = IWN_VAP(vap);
+
+ if ((error = iwn_config_u1(sc)) != 0) {
+ device_printf(sc->sc_dev,
+ "%s: iwn_config1 error %d\n", __func__, error);
+ return error;
+ }
+
+ if ((error = iwn_set_pan_params(sc)) != 0) {
+ device_printf(sc->sc_dev,
+ "%s: iwn_set_pan_params error %d\n", __func__, error);
+ return error;
+ }
+
+ memset(&cmd, 0, sizeof cmd);
+ cmd.lintval = htole16(10);
+ cmd.bintval = htole16(IWN_BEACON_INTERVAL_DEFAULT);
+ ivp->beacon_int = cmd.bintval;
+ cmd.binitval = htole32(0x032000);
+ cmd.dtim_period = 1;
+
+ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
+
+ return iwn_cmd(sc, IWN_CMD_WIPAN_RXON_TIMING, &cmd, sizeof cmd, 0);
+}
+
+static int
+iwn_config_u1(struct iwn_softc *sc)
+{
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+ uint16_t rxchain;
+ int error;
+ struct ieee80211vap *vap = sc->ivap[IWN_RXON_PAN_CTX];
+ struct iwn_vap *ivp = IWN_VAP(vap);
+
+ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+
+ sc->rxon = &sc->rx_on[IWN_RXON_PAN_CTX];
+ IEEE80211_ADDR_COPY(sc->rxon->myaddr, ivp->macaddr);
+ IEEE80211_ADDR_COPY(sc->rxon->wlap, IF_LLADDR(ifp));
+ sc->rxon->chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
+ sc->rxon->flags = htole32(IWN_RXON_TSF);
+ if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
+ sc->rxon->flags |= htole32(IWN_RXON_AUTO | IWN_RXON_24GHZ);
+ sc->rxon->mode = IWN_MODE_P2P;
+ sc->rxon->filter = htole32(IWN_FILTER_MULTICAST);
+ sc->rxon->cck_mask = 0x0f; /* not yet negotiated */
+ sc->rxon->ofdm_mask = 0xff; /* not yet negotiated */
+ sc->rxon->ht_single_mask = 0xff;
+ sc->rxon->ht_dual_mask = 0xff;
+ sc->rxon->ht_triple_mask = 0xff;
+ rxchain =
+ IWN_RXCHAIN_VALID(sc->rxchainmask) |
+ IWN_RXCHAIN_MIMO_COUNT(2) |
+ IWN_RXCHAIN_IDLE_COUNT(2);
+ sc->rxon->rxchain = htole16(rxchain);
+ sc->rxon->associd = 0;
+ sc->rxon->filter &= ~htole32(IWN_FILTER_BSS);
+
+ error = iwn_cmd(sc, IWN_CMD_WIPAN_RXON, sc->rxon, sc->rxonsz, 0);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "%s: IWN_CMD_WIPAN_RXON command failed\n",
+ __func__);
+ return error;
+ }
+ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
+
+ return 0;
+}
+
+static int
+iwn_set_pan_params(struct iwn_softc *sc)
+{
+ struct iwn_pan_params_cmd cmd;
+ int slot0 = 300, slot1 = 0;
+ int bcnint;
+ int error = 0;
+
+ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+
+ /*
+ * If the PAN context is inactive, then we don't need
+ * to update the PAN parameters
+ */
+ if (sc->ctx != IWN_RXON_PAN_CTX) {
+ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end with no need to do that\n", __func__);
+ return 0;
+ }
+
+ memset(&cmd, 0, sizeof(cmd));
+
+ /* only 2 slots are currently allowed */
+ cmd.num_slots = 2;
+
+ cmd.slots[0].type = IWN_RXON_BSS_CTX; /* BSS */
+ cmd.slots[1].type = IWN_RXON_PAN_CTX; /* PAN */
+
+ cmd.flags |= htole16(IWN_PAN_PARAMS_FLG_SLOTTED_MODE);
+ bcnint = IWN_BEACON_INTERVAL_DEFAULT;
+ slot0 = (bcnint >> 1);
+ slot1 = (bcnint - slot0);
+
+ if(sc->uc_scan_progress == 1) {
+ slot0 = bcnint * 3 - IWN_SLOT_TIME_MIN;
+ slot1 = IWN_SLOT_TIME_MIN;
+ }
+ cmd.slots[0].time = htole16(slot0);
+ cmd.slots[1].time = htole16(slot1);
+
+ error = iwn_cmd(sc, IWN_CMD_WIPAN_PARAMS, &cmd, sizeof(cmd), 0);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "%s: IWN_CMD_WIPAN_PARAMS command failed, error %d\n",
+ __func__, error);
+ return error;
+ }
+
+ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
+
+ return 0;
+}
+
+static int
+iwn_updateedca_u1(struct ieee80211com *ic)
+{
+#define IWN_EXP2(x) ((1 << (x)) - 1) /* CWmin = 2^ECWmin - 1 */
+ struct iwn_softc *sc = ic->ic_ifp->if_softc;
+ struct iwn_edca_params cmd;
+ int aci;
+
+ memset(&cmd, 0, sizeof cmd);
+ cmd.flags = htole32(IWN_EDCA_UPDATE);
+ for (aci = 0; aci < WME_NUM_AC; aci++) {
+ const struct wmeParams *ac =
+ &ic->ic_wme.wme_chanParams.cap_wmeParams[aci];
+ cmd.ac[aci].aifsn = ac->wmep_aifsn;
+ cmd.ac[aci].cwmin = htole16(IWN_EXP2(ac->wmep_logcwmin));
+ cmd.ac[aci].cwmax = htole16(IWN_EXP2(ac->wmep_logcwmax));
+ cmd.ac[aci].txoplimit =
+ htole16(IEEE80211_TXOP_TO_US(ac->wmep_txopLimit));
+ }
+ return iwn_cmd(sc, IWN_CMD_WIPAN_QOS_PARAM, &cmd, sizeof cmd, 1);
+#undef IWN_EXP2
+}
+
+/*
+ * Broadcast node is used to send group-addressed and management frames.
+ */
+static int
+iwn_add_broadcast_node_u1(struct iwn_softc *sc, int async)
+{
+ struct iwn_ops *ops = &sc->ops;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+ struct iwn_node_info node;
+ struct iwn_cmd_link_quality linkq;
+ uint8_t txant;
+ int i, error;
+
+ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+
+ sc->rxon = &sc->rx_on[IWN_RXON_PAN_CTX];
+
+ memset(&node, 0, sizeof node);
+ IEEE80211_ADDR_COPY(node.macaddr, ifp->if_broadcastaddr);
+
+ node.id = IWN_PAN_BCAST_ID;
+ node.htflags |= htole32(IWN_STA_FLAG_PAN_STATION);
+ DPRINTF(sc, IWN_DEBUG_RESET, "%s: adding broadcast node1\n", __func__);
+ if ((error = ops->add_node(sc, &node, async)) != 0)
+ return error;
+
+ /* Use the first valid TX antenna. */
+ txant = IWN_LSB(sc->txchainmask);
+
+ memset(&linkq, 0, sizeof linkq);
+ linkq.id = IWN_PAN_BCAST_ID;
+ linkq.antmsk_1stream = txant;
+ linkq.antmsk_2stream = IWN_ANT_AB;
+ linkq.ampdu_max = 64;
+ linkq.ampdu_threshold = 3;
+ linkq.ampdu_limit = htole16(4000); /* 4ms */
+
+ /* Use lowest mandatory bit-rate. */
+ if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
+ linkq.retry[0] = htole32(0xd);
+ else
+ linkq.retry[0] = htole32(10 | IWN_RFLAG_CCK);
+ linkq.retry[0] |= htole32(IWN_RFLAG_ANT(txant));
+ /* Use same bit-rate for all TX retries. */
+ for (i = 1; i < IWN_MAX_TX_RETRIES; i++) {
+ linkq.retry[i] = linkq.retry[0];
+ }
+ DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
+
+ return iwn_cmd(sc, IWN_CMD_LINK_QUALITY, &linkq, sizeof linkq, async);
+}
+
+static uint16_t
+iwn_get_active_dwell(struct iwn_softc *sc, struct ieee80211_channel *c)
+{
+ int n_probes = 1;
+
+ if (IEEE80211_IS_CHAN_5GHZ(c))
+ return IWN_ACTIVE_DWELL_TIME_52 +
+ IWN_ACTIVE_DWELL_FACTOR_52 * (n_probes + 1);
+ else
+ return IWN_ACTIVE_DWELL_TIME_24 +
+ IWN_ACTIVE_DWELL_FACTOR_24 * (n_probes + 1);
+}
+
+static uint16_t
+iwn_get_passive_dwell(struct iwn_softc *sc, struct ieee80211_channel *c)
+{
+ uint8_t ctx_id = 0;
+ uint16_t beacon_int;
+ struct ieee80211vap *vap;
+ struct iwn_vap *ivp;
+ uint16_t dwell_time;
+
+ dwell_time = (IEEE80211_IS_CHAN_2GHZ(c)) ?
+ IWN_PASSIVE_DWELL_BASE + IWN_PASSIVE_DWELL_TIME_24 :
+ IWN_PASSIVE_DWELL_BASE + IWN_PASSIVE_DWELL_TIME_52;
+
+ for (ctx_id = 0; ctx_id < IWN_NUM_RXON_CTX; ctx_id++) {
+ vap = sc->ivap[ctx_id];
+ ivp = IWN_VAP(vap);
+ sc->rxon = &sc->rx_on[ctx_id];
+ if (!sc->rxon->associd)
+ continue;
+ beacon_int = ivp->beacon_int;
+ if (!beacon_int)
+ beacon_int = IWN_PASSIVE_DWELL_BASE;
+ beacon_int = (beacon_int * 98) / 100 - IWN_CHANNEL_TUNE_TIME * 2;
+ dwell_time = min(beacon_int, dwell_time);
+ if(sc->ctx != IWN_RXON_PAN_CTX) break;
+ }
+
+ return dwell_time;
+}
+static void
+iwn_led_pattern(struct iwn_softc *sc)
+{
+ int i,j;
+
+ for(i = 0; i < IWN_MAX_BLINK_TBL; i++) {
+ if((sc->sc_led.led_last_tpt) > (blink_tbl[i].tpt * 1024 * 1024))
+ break;
+ }
+
+ for(j = 0; j < IWN_MAX_BLINK_TBL; j++) {
+ if((sc->sc_led.led_cur_tpt) > (blink_tbl[j].tpt * 1024 * 1024))
+ break;
+ }
+
+ if (i != j)
+ iwn_set_led(sc, IWN_LED_LINK,blink_tbl[j].off_time,
+ blink_tbl[j].on_time, IWN_LED_INT_BLINK);
+}
+
+
+
Index: sys/dev/iwn/if_iwnreg.h
===================================================================
--- sys/dev/iwn/if_iwnreg.h (revision 253707)
+++ sys/dev/iwn/if_iwnreg.h (working copy)
@@ -2,6 +2,8 @@
/* $OpenBSD: if_iwnreg.h,v 1.40 2010/05/05 19:41:57 damien Exp $ */
/*-
+ * Copyright (c) 2013 Cedric GROSS <c.gross@kreiz-it.fr>
+ * Copyright (c) 2011 Intel Corporation
* Copyright (c) 2007, 2008
* Damien Bergamini <damien.bergamini@free.fr>
*
@@ -17,7 +19,267 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+
+#define IWN_CT_KILL_THRESHOLD 114 /* in Celsius */
+#define IWN_CT_KILL_EXIT_THRESHOLD 95 /* in Celsius */
+
+/* ============================================================================
+ * DEVICE ID BLOCK
+ * ============================================================================
+*/
+/*
+ * -----------------------------------------------------------------------------
+ * Device ID for 2x30 series
+ * -----------------------------------------------------------------------------
+ */
+#define IWN_DID_2x30_1 0x0887
+#define IWN_DID_2x30_2 0x0888
+/* SubDevice ID */
+#define IWN_SDID_2x30_1 0x4062 // "2000 Series 2x2 BGN/BT"
+#define IWN_SDID_2x30_2 0x4262 // "2000 Series 2x2 BGN/BT"
+#define IWN_SDID_2x30_3 0x4462 // "2000 Series 2x2 BGN/BT"
+#define IWN_SDID_2x30_4 0x4066 // "2000 Series 2x2 BG/BT"
+#define IWN_SDID_2x30_5 0x4266 // "2000 Series 2x2 BG/BT"
+#define IWN_SDID_2x30_6 0x4466 // "2000 Series 2x2 BG/BT"
+
+/*
+ * -----------------------------------------------------------------------------
+ * Device ID for 1000 series
+ * -----------------------------------------------------------------------------
+ */
+#define IWN_DID_1000_1 0x0083
+#define IWN_DID_1000_2 0x0084
+
+/* SubDevice ID */
+#define IWN_SDID_1000_1 0x1205 // iwl1000_bgn_cfg
+#define IWN_SDID_1000_2 0x1305 // iwl1000_bgn_cfg
+#define IWN_SDID_1000_3 0x1225 // iwl1000_bgn_cfg
+#define IWN_SDID_1000_4 0x1325 // iwl1000_bgn_cfg
+#define IWN_SDID_1000_5 0x1215 // iwl1000_bgn_cfg
+#define IWN_SDID_1000_6 0x1315 // iwl1000_bgn_cfg
+
+#define IWN_SDID_1000_7 0x1206 // iwl1000_bg_cfg
+#define IWN_SDID_1000_8 0x1306 // iwl1000_bg_cfg
+#define IWN_SDID_1000_9 0x1226 // iwl1000_bg_cfg
+#define IWN_SDID_1000_10 0x1326 // iwl1000_bg_cfg
+#define IWN_SDID_1000_11 0x1216 // iwl1000_bg_cfg
+#define IWN_SDID_1000_12 0x1316 // iwl1000_bg_cfg
+
+/*
+ * -----------------------------------------------------------------------------
+ * Device ID for 6x00 series
+ * -----------------------------------------------------------------------------
+ */
+#define IWN_DID_6x00_1 0x422B
+#define IWN_DID_6x00_2 0x422C
+#define IWN_DID_6x00_3 0x4238
+#define IWN_DID_6x00_4 0x4239
+/* SubDevice ID */
+#define IWN_SDID_6x00_1 0x1101 // iwl6000_3agn_cfg
+#define IWN_SDID_6x00_2 0x1121 // iwl6000_3agn_cfg
+#define IWN_SDID_6x00_3 0x1301 // iwl6000i_2agn_cfg
+#define IWN_SDID_6x00_4 0x1306 // iwl6000i_2abg_cfg
+#define IWN_SDID_6x00_5 0x1307 // iwl6000i_2bg_cfg
+#define IWN_SDID_6x00_6 0x1321 // iwl6000i_2agn_cfg
+#define IWN_SDID_6x00_7 0x1326 // iwl6000i_2abg_cfg
+#define IWN_SDID_6x00_8 0x1111 // iwl6000_3agn_cfg
+#define IWN_SDID_6x00_9 0x1311 // iwl6000i_2agn_cfg
+#define IWN_SDID_6x00_10 0x1316 // iwl6000i_2abg_cfg
+/*
+ * -----------------------------------------------------------------------------
+ * Device ID for 6x05 series
+ * -----------------------------------------------------------------------------
+ */
+#define IWN_DID_6x05_1 0x0082
+#define IWN_DID_6x05_2 0x0085
+/* SubDevice ID */
+#define IWN_SDID_6x05_1 0x1301 //iwl6005_2agn_cfg
+#define IWN_SDID_6x05_2 0x1306 //iwl6005_2abg_cfg
+#define IWN_SDID_6x05_3 0x1307 //iwl6005_2bg_cfg
+#define IWN_SDID_6x05_4 0x1321 //iwl6005_2agn_cfg
+#define IWN_SDID_6x05_5 0x1326 //iwl6005_2abg_cfg
+#define IWN_SDID_6x05_6 0x1311 //iwl6005_2agn_cfg
+#define IWN_SDID_6x05_7 0x1316 //iwl6005_2abg_cfg
+#define IWN_SDID_6x05_8 0xC020 //iwl6005_2agn_sff_cfg
+#define IWN_SDID_6x05_9 0xC220 //iwl6005_2agn_sff_cfg
+#define IWN_SDID_6x05_10 0x4820 //iwl6005_2agn_d_cfg
+#define IWN_SDID_6x05_11 0x1304 //iwl6005_2agn_mow1_cfg/* low 5GHz active */
+#define IWN_SDID_6x05_12 0x1305 //iwl6005_2agn_mow2_cfg/* high 5GHz active */
+
+/*
+ * -----------------------------------------------------------------------------
+ * Device ID for 6050 WiFi/WiMax Series
+ * -----------------------------------------------------------------------------
+ */
+#define IWN_DID_6050_1 0x0087
+#define IWN_DID_6050_2 0x0089
+
+#define IWN_SDID_6050_1 0x1301 //iwl6050_2agn_cfg
+#define IWN_SDID_6050_2 0x1306 //iwl6050_2abg_cfg
+#define IWN_SDID_6050_3 0x1321 //iwl6050_2agn_cfg
+#define IWN_SDID_6050_4 0x1326 //iwl6050_2abg_cfg
+#define IWN_SDID_6050_5 0x1311 //iwl6050_2agn_cfg
+#define IWN_SDID_6050_6 0x1316 //iwl6050_2abg_cfg
+
+/*
+ * -----------------------------------------------------------------------------
+ * Device ID for 6150 Series
+ * -----------------------------------------------------------------------------
+ */
+
+#define IWN_DID_6150_1 0x0885
+#define IWN_DID_6150_2 0x0886
+
+#define IWN_SDID_6150_1 0x1305 // iwl6150_bgn_cfg
+#define IWN_SDID_6150_2 0x1307 // iwl6150_bg_cfg)
+#define IWN_SDID_6150_3 0x1325 // iwl6150_bgn_cfg
+#define IWN_SDID_6150_4 0x1327 // iwl6150_bg_cfg)
+#define IWN_SDID_6150_5 0x1315 // iwl6150_bgn_cfg
+#define IWN_SDID_6150_6 0x1317 // iwl6150_bg_cfg)
+
+/*
+ * -----------------------------------------------------------------------------
+ * Device ID for 6035 Series
+ * -----------------------------------------------------------------------------
+ */
+#define IWN_DID_6035_1 0x088E
+#define IWN_DID_6035_2 0x088F
+
+#define IWN_SDID_6035_1 0x4060 // iwl6035_2agn_cfg
+#define IWN_SDID_6035_2 0x4260 // iwl6035_2agn_cfg
+#define IWN_SDID_6035_3 0x4460 // iwl6035_2agn_cfg
+#define IWN_SDID_6035_4 0x4860 // iwl6035_2agn_cfg
+
+/*
+ * -----------------------------------------------------------------------------
+ * Device ID for 1030 and 6030 Series
+ * -----------------------------------------------------------------------------
+ */
+#define IWN_DID_x030_1 0x008A
+#define IWN_DID_x030_2 0x008B
+#define IWN_DID_x030_3 0x0090
+#define IWN_DID_x030_4 0x0091
+
+#define IWN_SDID_x030_1 0x5305 // iwl1030_bgn_cfg
+#define IWN_SDID_x030_2 0x5307 // iwl1030_bg_cfg
+#define IWN_SDID_x030_3 0x5325 // iwl1030_bgn_cfg
+#define IWN_SDID_x030_4 0x5327 // iwl1030_bg_cfg
+#define IWN_SDID_x030_5 0x5315 // iwl1030_bgn_cfg
+#define IWN_SDID_x030_6 0x5317 // iwl1030_bg_cfg
+#define IWN_SDID_x030_7 0x5211 // iwl6030_2agn_cfg
+#define IWN_SDID_x030_8 0x5215 // iwl6030_2bgn_cfg
+#define IWN_SDID_x030_9 0x5216 // iwl6030_2abg_cfg
+#define IWN_SDID_x030_10 0x5201 // iwl6030_2agn_cfg
+#define IWN_SDID_x030_11 0x5205 // iwl6030_2bgn_cfg
+#define IWN_SDID_x030_12 0x5206 // iwl6030_2abg_cfg
+#define IWN_SDID_x030_13 0x5207 // iwl6030_2bg_cfg)
+#define IWN_SDID_x030_14 0x5221 // iwl6030_2agn_cfg
+#define IWN_SDID_x030_15 0x5225 // iwl6030_2bgn_cfg
+#define IWN_SDID_x030_16 0x5226 // iwl6030_2abg_cfg
+
+/*
+ * -----------------------------------------------------------------------------
+ * Device ID for 130 Series
+ * -----------------------------------------------------------------------------
+ */
+#define IWN_DID_130_1 0x0896
+#define IWN_DID_130_2 0x0897
+
+#define IWN_SDID_130_1 0x5005 //iwl130_bgn_cfg
+#define IWN_SDID_130_2 0x5007 //iwl130_bg_cfg
+#define IWN_SDID_130_3 0x5015 //iwl130_bgn_cfg
+#define IWN_SDID_130_4 0x5017 //iwl130_bg_cfg
+#define IWN_SDID_130_5 0x5025 //iwl130_bgn_cfg
+#define IWN_SDID_130_6 0x5027 //iwl130_bg_cfg
+
+/*
+ * -----------------------------------------------------------------------------
+ * Device ID for 100 Series
+ * -----------------------------------------------------------------------------
+ */
+#define IWN_DID_100_1 0x08AE
+#define IWN_DID_100_2 0x08AF
+
+#define IWN_SDID_100_1 0x1005 //iwl100_bgn_cfg)
+#define IWN_SDID_100_2 0x1007 //iwl100_bg_cfg)}
+#define IWN_SDID_100_3 0x1015 //iwl100_bgn_cfg)
+#define IWN_SDID_100_4 0x1017 //iwl100_bg_cfg)}
+#define IWN_SDID_100_5 0x1025 //iwl100_bgn_cfg)
+#define IWN_SDID_100_6 0x1027 //iwl100_bg_cfg)}
+
+/*
+ * -----------------------------------------------------------------------------
+ * Device ID for 5x00 Series
+ * -----------------------------------------------------------------------------
+ */
+#define IWN_DID_5x00_1 0x4232
+#define IWN_DID_5x00_2 0x4237
+#define IWN_DID_5x00_3 0x4235
+#define IWN_DID_5x00_4 0x4236
+
+#define IWN_SDID_5x00_1 0x1201 //iwl5100_agn_cfg
+#define IWN_SDID_5x00_2 0x1301 //iwl5100_agn_cfg
+#define IWN_SDID_5x00_3 0x1204 //iwl5100_agn_cfg
+#define IWN_SDID_5x00_4 0x1304 //iwl5100_agn_cfg
+#define IWN_SDID_5x00_5 0x1205 //iwl5100_bgn_cfg
+#define IWN_SDID_5x00_6 0x1305 //iwl5100_bgn_cfg
+#define IWN_SDID_5x00_7 0x1206 //iwl5100_abg_cfg
+#define IWN_SDID_5x00_8 0x1306 //iwl5100_abg_cfg
+#define IWN_SDID_5x00_9 0x1221 //iwl5100_agn_cfg
+#define IWN_SDID_5x00_10 0x1321 //iwl5100_agn_cfg
+#define IWN_SDID_5x00_11 0x1224 //iwl5100_agn_cfg
+#define IWN_SDID_5x00_12 0x1324 //iwl5100_agn_cfg
+#define IWN_SDID_5x00_13 0x1225 //iwl5100_bgn_cfg
+#define IWN_SDID_5x00_14 0x1325 //iwl5100_bgn_cfg
+#define IWN_SDID_5x00_15 0x1226 //iwl5100_abg_cfg
+#define IWN_SDID_5x00_16 0x1326 //iwl5100_abg_cfg
+#define IWN_SDID_5x00_17 0x1211 //iwl5100_agn_cfg
+#define IWN_SDID_5x00_18 0x1311 //iwl5100_agn_cfg
+#define IWN_SDID_5x00_19 0x1214 //iwl5100_agn_cfg
+#define IWN_SDID_5x00_20 0x1314 //iwl5100_agn_cfg
+#define IWN_SDID_5x00_21 0x1215 //iwl5100_bgn_cfg
+#define IWN_SDID_5x00_22 0x1315 //iwl5100_bgn_cfg
+#define IWN_SDID_5x00_23 0x1216 //iwl5100_abg_cfg
+#define IWN_SDID_5x00_24 0x1316 //iwl5100_abg_cfg
+#define IWN_SDID_5x00_25 0x1021 //iwl5300_agn_cfg
+#define IWN_SDID_5x00_26 0x1121 //iwl5300_agn_cfg
+#define IWN_SDID_5x00_27 0x1024 //iwl5300_agn_cfg
+#define IWN_SDID_5x00_28 0x1124 //iwl5300_agn_cfg
+#define IWN_SDID_5x00_29 0x1001 //iwl5300_agn_cfg
+#define IWN_SDID_5x00_30 0x1101 //iwl5300_agn_cfg
+#define IWN_SDID_5x00_31 0x1004 //iwl5300_agn_cfg
+#define IWN_SDID_5x00_32 0x1104 //iwl5300_agn_cfg
+#define IWN_SDID_5x00_33 0x1011 //iwl5300_agn_cfg
+#define IWN_SDID_5x00_34 0x1111 //iwl5300_agn_cfg
+#define IWN_SDID_5x00_35 0x1014 //iwl5300_agn_cfg
+#define IWN_SDID_5x00_36 0x1114 //iwl5300_agn_cfg
+
+/*
+ * -----------------------------------------------------------------------------
+ * Device ID for 5x50 Series
+ * -----------------------------------------------------------------------------
+ */
+#define IWN_DID_5x50_1 0x423A
+#define IWN_DID_5x50_2 0x423B
+#define IWN_DID_5x50_3 0x423C
+#define IWN_DID_5x50_4 0x423D
+
+#define IWN_SDID_5x50_1 0x1001 //iwl5350_agn_cfg
+#define IWN_SDID_5x50_2 0x1021 //iwl5350_agn_cfg
+#define IWN_SDID_5x50_3 0x1011 //iwl5350_agn_cfg
+#define IWN_SDID_5x50_4 0x1201 //iwl5150_agn_cfg
+#define IWN_SDID_5x50_5 0x1301 //iwl5150_agn_cfg
+#define IWN_SDID_5x50_6 0x1206 //iwl5150_abg_cfg
+#define IWN_SDID_5x50_7 0x1306 //iwl5150_abg_cfg
+#define IWN_SDID_5x50_8 0x1221 //iwl5150_agn_cfg
+#define IWN_SDID_5x50_9 0x1321 //iwl5150_agn_cfg
+#define IWN_SDID_5x50_10 0x1211 //iwl5150_agn_cfg
+#define IWN_SDID_5x50_11 0x1311 //iwl5150_agn_cfg
+#define IWN_SDID_5x50_12 0x1216 //iwl5150_abg_cfg
+#define IWN_SDID_5x50_13 0x1316 //iwl5150_abg_cfg
+
+
#define IWN_TX_RING_COUNT 256
#define IWN_TX_RING_LOMARK 192
#define IWN_TX_RING_HIMARK 224
@@ -38,6 +300,11 @@
#define IWN_ICT_SIZE 4096
#define IWN_ICT_COUNT (IWN_ICT_SIZE / sizeof (uint32_t))
+/* For cards with PAN command default is IWN_CMD_QUEUE_NUM */
+#define IWN_CMD_QUEUE_NUM 4
+#define IWN_PAN_CMD_QUEUE 9
+
+
/* Maximum number of DMA segments for TX. */
#define IWN_MAX_SCATTER 20
@@ -62,6 +329,7 @@
#define IWN_INT 0x008
#define IWN_INT_MASK 0x00c
#define IWN_FH_INT 0x010
+#define IWN_GPIO_IN 0x018 /* read external chip pins */
#define IWN_RESET 0x020
#define IWN_GP_CNTRL 0x024
#define IWN_HW_REV 0x028
@@ -69,8 +337,12 @@
#define IWN_EEPROM_GP 0x030
#define IWN_OTP_GP 0x034
#define IWN_GIO 0x03c
+#define IWN_GP_UCODE 0x048
#define IWN_GP_DRIVER 0x050
+#define IWN_UCODE_GP1 0x054
+#define IWN_UCODE_GP1_SET 0x058
#define IWN_UCODE_GP1_CLR 0x05c
+#define IWN_UCODE_GP2 0x060
#define IWN_LED 0x094
#define IWN_DRAM_INT_TBL 0x0a0
#define IWN_SHADOW_REG_CTRL 0x0a8
@@ -79,10 +351,12 @@
#define IWN_HW_REV_WA 0x22c
#define IWN_DBG_HPET_MEM 0x240
#define IWN_DBG_LINK_PWR_MGMT 0x250
+// Need nic_lock for use above
#define IWN_MEM_RADDR 0x40c
#define IWN_MEM_WADDR 0x410
#define IWN_MEM_WDATA 0x418
#define IWN_MEM_RDATA 0x41c
+#define IWN_TARG_MBX_C 0x430
#define IWN_PRPH_WADDR 0x444
#define IWN_PRPH_RADDR 0x448
#define IWN_PRPH_WDATA 0x44c
@@ -187,12 +461,50 @@
#define IWN_RESET_LINK_PWR_MGMT_DIS (1 << 31)
/* Possible flags for register IWN_GP_CNTRL. */
-#define IWN_GP_CNTRL_MAC_ACCESS_ENA (1 << 0)
+/*
+ * GP (general purpose) CONTROL REGISTER
+ * Bit fields:
+ * 27: HW_RF_KILL_SW
+ * Indicates state of (platform's) hardware RF-Kill switch
+ * 26-24: POWER_SAVE_TYPE
+ * Indicates current power-saving mode:
+ * 000 -- No power saving
+ * 001 -- MAC power-down
+ * 010 -- PHY (radio) power-down
+ * 011 -- Error
+ * 9-6: SYS_CONFIG
+ * Indicates current system configuration, reflecting pins on chip
+ * as forced high/low by device circuit board.
+ * 4: GOING_TO_SLEEP
+ * Indicates MAC is entering a power-saving sleep power-down.
+ * Not a good time to access device-internal resources.
+ * 3: MAC_ACCESS_REQ
+ * Host sets this to request and maintain MAC wakeup, to allow host
+ * access to device-internal resources. Host must wait for
+ * MAC_CLOCK_READY (and !GOING_TO_SLEEP) before accessing non-CSR
+ * device registers.
+ * 2: INIT_DONE
+ * Host sets this to put device into fully operational D0 power mode.
+ * Host resets this after SW_RESET to put device into low power mode.
+ * 0: MAC_CLOCK_READY
+ * Indicates MAC (ucode processor, etc.) is powered up and can run.
+ * Internal resources are accessible.
+ * NOTE: This does not indicate that the processor is actually running.
+ * NOTE: This does not indicate that device has completed
+ * init or post-power-down restore of internal SRAM memory.
+ * Use CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP as indication that
+ * SRAM is restored and uCode is in normal operation mode.
+ * Later devices (5xxx/6xxx/1xxx) use non-volatile SRAM, and
+ * do not need to save/restore it.
+ * NOTE: After device reset, this bit remains "0" until host sets
+ * INIT_DONE
+ */
+#define IWN_GP_CNTRL_MAC_ACCESS_ENA (1 << 0) //x00000001
#define IWN_GP_CNTRL_MAC_CLOCK_READY (1 << 0)
-#define IWN_GP_CNTRL_INIT_DONE (1 << 2)
-#define IWN_GP_CNTRL_MAC_ACCESS_REQ (1 << 3)
-#define IWN_GP_CNTRL_SLEEP (1 << 4)
-#define IWN_GP_CNTRL_RFKILL (1 << 27)
+#define IWN_GP_CNTRL_INIT_DONE (1 << 2) //x00000004
+#define IWN_GP_CNTRL_MAC_ACCESS_REQ (1 << 3) //x00000008
+#define IWN_GP_CNTRL_SLEEP (1 << 4) //x00000010
+#define IWN_GP_CNTRL_RFKILL (1 << 27) //x08000000
/* Possible flags for register IWN_HW_REV. */
#define IWN_HW_REV_TYPE_SHIFT 4
@@ -206,6 +518,7 @@
#define IWN_HW_REV_TYPE_6000 7
#define IWN_HW_REV_TYPE_6050 8
#define IWN_HW_REV_TYPE_6005 11
+#define IWN_HW_REV_TYPE_2230 12
/* Possible flags for register IWN_GIO_CHICKEN. */
#define IWN_GIO_CHICKEN_L1A_NO_L0S_RX (1 << 23)
@@ -215,16 +528,20 @@
#define IWN_GIO_L0S_ENA (1 << 1)
/* Possible flags for register IWN_GP_DRIVER. */
-#define IWN_GP_DRIVER_RADIO_3X3_HYB (0 << 0)
-#define IWN_GP_DRIVER_RADIO_2X2_HYB (1 << 0)
-#define IWN_GP_DRIVER_RADIO_2X2_IPA (2 << 0)
-#define IWN_GP_DRIVER_CALIB_VER6 (1 << 2)
-#define IWN_GP_DRIVER_6050_1X2 (1 << 3)
+#define IWN_GP_DRIVER_RADIO_3X3_HYB (0 << 0)
+#define IWN_GP_DRIVER_RADIO_2X2_HYB (1 << 0)
+#define IWN_GP_DRIVER_RADIO_2X2_IPA (2 << 0)
+#define IWN_GP_DRIVER_RADIO_MSK (0x00000003)
+#define IWN_GP_DRIVER_CALIB_VER6 (1 << 2)
+#define IWN_GP_DRIVER_6050_1X2 (1 << 3)
+#define IWN_GP_DRIVER_REG_BIT_RADIO_IQ_INVERT (0x00000080)
+
/* Possible flags for register IWN_UCODE_GP1_CLR. */
#define IWN_UCODE_GP1_RFKILL (1 << 1)
#define IWN_UCODE_GP1_CMD_BLOCKED (1 << 2)
#define IWN_UCODE_GP1_CTEMP_STOP_RF (1 << 3)
+#define IWN_UCODE_GP1_CFG_COMPLETE (1 << 5)
/* Possible flags/values for register IWN_LED. */
#define IWN_LED_BSM_CTRL (1 << 5)
@@ -231,6 +548,32 @@
#define IWN_LED_OFF 0x00000038
#define IWN_LED_ON 0x00000078
+#define IWN_MAX_BLINK_TBL 10
+#define IWN_LED_STATIC_ON 0
+#define IWN_LED_STATIC_OFF 1
+#define IWN_LED_SLOW_BLINK 2
+#define IWN_LED_INT_BLINK 3
+#define IWN_LED_UNIT 0x1388 /* 5 ms */
+
+static const struct {
+ uint16_t tpt; /* Mb/s */
+ uint8_t on_time;
+ uint8_t off_time;
+} blink_tbl[] =
+{
+ {300, 5, 5},
+ {200, 8, 8},
+ {100, 11, 11},
+ {70, 13, 13},
+ {50, 15, 15},
+ {20, 17, 17},
+ {10, 19, 19},
+ {5, 22, 22},
+ {1, 26, 26},
+ {0, 33, 33},
+ /* SOLID_ON */
+};
+
/* Possible flags for register IWN_DRAM_INT_TBL. */
#define IWN_DRAM_INT_TBL_WRAP_CHECK (1 << 27)
#define IWN_DRAM_INT_TBL_ENABLE (1 << 31)
@@ -246,18 +589,19 @@
#define IWN_BSM_WR_CTRL_START (1 << 31)
/* Possible flags for register IWN_INT. */
-#define IWN_INT_ALIVE (1 << 0)
-#define IWN_INT_WAKEUP (1 << 1)
-#define IWN_INT_SW_RX (1 << 3)
-#define IWN_INT_CT_REACHED (1 << 6)
-#define IWN_INT_RF_TOGGLED (1 << 7)
-#define IWN_INT_SW_ERR (1 << 25)
-#define IWN_INT_SCHED (1 << 26)
-#define IWN_INT_FH_TX (1 << 27)
-#define IWN_INT_RX_PERIODIC (1 << 28)
-#define IWN_INT_HW_ERR (1 << 29)
-#define IWN_INT_FH_RX (1 << 31)
+#define IWN_INT_ALIVE (1 << 0) // x00000001
+#define IWN_INT_WAKEUP (1 << 1) // x00000002
+#define IWN_INT_SW_RX (1 << 3) // x00000008
+#define IWN_INT_CT_REACHED (1 << 6) // x00000040
+#define IWN_INT_RF_TOGGLED (1 << 7) // x00000080
+#define IWN_INT_SW_ERR (1 << 25) // x02000000
+#define IWN_INT_SCHED (1 << 26) // x04000000
+#define IWN_INT_FH_TX (1 << 27) // x08000000
+#define IWN_INT_RX_PERIODIC (1 << 28) // x10000000
+#define IWN_INT_HW_ERR (1 << 29) // x20000000
+#define IWN_INT_FH_RX (1 << 31) // x80000000
+
/* Shortcut. */
#define IWN_INT_MASK_DEF \
(IWN_INT_SW_ERR | IWN_INT_HW_ERR | IWN_INT_FH_TX | \
@@ -400,6 +744,12 @@
uint8_t qid;
} __packed;
+/* CARD_STATE_NOTIFICATION */
+#define IWN_STATE_CHANGE_HW_CARD_DISABLED 0x01
+#define IWN_STATE_CHANGE_SW_CARD_DISABLED 0x02
+#define IWN_STATE_CHANGE_CT_CARD_DISABLED 0x04
+#define IWN_STATE_CHANGE_RXON_CARD_DISABLED 0x10
+
/* Possible RX status flags. */
#define IWN_RX_NO_CRC_ERR (1 << 0)
#define IWN_RX_NO_OVFL_ERR (1 << 1)
@@ -423,7 +773,8 @@
#define IWN_CMD_LINK_QUALITY 78
#define IWN_CMD_SET_LED 72
#define IWN5000_CMD_WIMAX_COEX 90
-#define IWN5000_CMD_CALIB_CONFIG 101
+#define IWN_TEMP_NOTIFICATION 98
+#define IWN5000_CMD_CALIB_CONFIG 101 // CALIBRATION_CFG_CMD
#define IWN5000_CMD_CALIB_RESULT 102
#define IWN5000_CMD_CALIB_COMPLETE 103
#define IWN_CMD_SET_POWER_MODE 119
@@ -436,9 +787,20 @@
#define IWN_CMD_GET_STATISTICS 156
#define IWN_CMD_SET_CRITICAL_TEMP 164
#define IWN_CMD_SET_SENSITIVITY 168
-#define IWN_CMD_PHY_CALIB 176
+#define IWN_CMD_PHY_CALIB 176
#define IWN_CMD_BT_COEX_PRIOTABLE 204
#define IWN_CMD_BT_COEX_PROT 205
+#define IWN_CMD_BT_COEX_NOTIF 206
+/* PAN commands */
+#define IWN_CMD_WIPAN_PARAMS 0xb2
+#define IWN_CMD_WIPAN_RXON 0xb3
+#define IWN_CMD_WIPAN_RXON_TIMING 0xb4
+#define IWN_CMD_WIPAN_RXON_ASSOC 0xb6
+#define IWN_CMD_WIPAN_QOS_PARAM 0xb7
+#define IWN_CMD_WIPAN_WEPKEY 0xb8
+#define IWN_CMD_WIPAN_P2P_CHANNEL_SWITCH 0xb9
+#define IWN_CMD_WIPAN_NOA_NOTIFICATION 0xbc
+#define IWN_CMD_WIPAN_DEACTIVATION_COMPLETE 0xbd
uint8_t flags;
uint8_t idx;
@@ -446,6 +808,28 @@
uint8_t data[136];
} __packed;
+/*
+ * Structure for IWN_CMD_GET_STATISTICS = (0x9c) 156
+ * all devices identical.
+ *
+ * This command triggers an immediate response containing uCode statistics.
+ * The response is in the same format as IWN_BEACON_STATISTICS (0x9d) 157.
+ *
+ * If the CLEAR_STATS configuration flag is set, uCode will clear its
+ * internal copy of the statistics (counters) after issuing the response.
+ * This flag does not affect IWN_BEACON_STATISTICS after beacons (see below).
+ *
+ * If the DISABLE_NOTIF configuration flag is set, uCode will not issue
+ * IWN_BEACON_STATISTICS after received beacons. This flag
+ * does not affect the response to the IWN_CMD_GET_STATISTICS 0x9c itself.
+ */
+struct iwn_statistics_cmd {
+ uint32_t configuration_flags; /* IWN_STATS_CONF_* */
+#define IWN_STATS_CONF_CLEAR_STATS htole32(0x1)
+#define IWN_STATS_CONF_DISABLE_NOTIF htole32(0x2)
+
+} __packed;
+
/* Antenna flags, used in various commands. */
#define IWN_ANT_A (1 << 0)
#define IWN_ANT_B (1 << 1)
@@ -452,6 +836,7 @@
#define IWN_ANT_C (1 << 2)
/* Shortcuts. */
#define IWN_ANT_AB (IWN_ANT_A | IWN_ANT_B)
+#define IWN_ANT_AC (IWN_ANT_A | IWN_ANT_C)
#define IWN_ANT_BC (IWN_ANT_B | IWN_ANT_C)
#define IWN_ANT_ABC (IWN_ANT_A | IWN_ANT_B | IWN_ANT_C)
@@ -468,6 +853,8 @@
#define IWN_MODE_STA 3
#define IWN_MODE_IBSS 4
#define IWN_MODE_MONITOR 6
+#define IWN_MODE_2STA 8
+#define IWN_MODE_P2P 9
uint8_t air;
uint16_t rxchain;
@@ -551,7 +938,8 @@
uint16_t atim;
uint32_t binitval;
uint16_t lintval;
- uint16_t reserved;
+ uint8_t dtim_period;
+ uint8_t delta_cp_bss_tbtts;
} __packed;
/* Structure for command IWN_CMD_ADD_NODE. */
@@ -565,6 +953,11 @@
uint16_t reserved2;
uint8_t id;
#define IWN_ID_BSS 0
+#define IWN_STA_ID 1
+
+#define IWN_PAN_BCAST_ID 14
+#define IWN_BROADCAST_ID 15
+
#define IWN5000_ID_BROADCAST 15
#define IWN4965_ID_BROADCAST 31
@@ -766,7 +1159,13 @@
#define IWN_PS_SLEEP_OVER_DTIM (1 << 2)
#define IWN_PS_PCI_PMGT (1 << 3)
#define IWN_PS_FAST_PD (1 << 4)
+#define IWN_PS_BEACON_FILTERING (1 << 5)
+#define IWN_PS_SHADOW_REG (1 << 6)
+#define IWN_PS_CT_KILL (1 << 7)
+#define IWN_PS_BT_SCD (1 << 8)
+#define IWN_PS_ADVANCED_PM (1 << 9)
+
uint8_t keepalive;
uint8_t debug;
uint32_t rxtimeout;
@@ -803,6 +1202,7 @@
struct iwn_scan_chan {
uint32_t flags;
+#define IWN_CHAN_PASSIVE (0 << 0)
#define IWN_CHAN_ACTIVE (1 << 0)
#define IWN_CHAN_NPBREQS(x) (((1 << (x)) - 1) << 1)
@@ -813,9 +1213,26 @@
uint16_t passive; /* msecs */
} __packed;
+#define IWN_SCAN_CRC_TH_DISABLED 0
+#define IWN_SCAN_CRC_TH_DEFAULT htole16(1)
+#define IWN_SCAN_CRC_TH_NEVER htole16(0xffff)
+
+
/* Maximum size of a scan command. */
#define IWN_SCAN_MAXSZ (MCLBYTES - 4)
+#define IWN_ACTIVE_DWELL_TIME_24 (30) /* all times in msec */
+#define IWN_ACTIVE_DWELL_TIME_52 (20)
+#define IWN_ACTIVE_DWELL_FACTOR_24 (3)
+#define IWN_ACTIVE_DWELL_FACTOR_52 (2)
+
+#define IWN_PASSIVE_DWELL_TIME_24 (20) /* all times in msec */
+#define IWN_PASSIVE_DWELL_TIME_52 (10)
+#define IWN_PASSIVE_DWELL_BASE (100)
+#define IWN_CHANNEL_TUNE_TIME (5)
+
+#define IWN_SCAN_CHAN_TIMEOUT 2
+
/* Structure for command IWN_CMD_TXPOWER (4965AGN only.) */
#define IWN_RIDX_MAX 32
struct iwn4965_cmd_txpower {
@@ -860,8 +1277,20 @@
uint32_t kill_cts;
} __packed;
+/* Structures for enhanced command IWN_CMD_BLUETOOTH. */
struct iwn6000_btcoex_config {
uint8_t flags;
+#define IWN_BT_FLAG_COEX6000_CHAN_INHIBITION 1
+#define IWN_BT_FLAG_COEX6000_MODE_MASK ( (1 << 3) | (1 << 4) | (1 <<5 ))
+#define IWN_BT_FLAG_COEX6000_MODE_SHIFT 3
+#define IWN_BT_FLAG_COEX6000_MODE_DISABLED 0
+#define IWN_BT_FLAG_COEX6000_MODE_LEGACY_2W 1
+#define IWN_BT_FLAG_COEX6000_MODE_3W 2
+#define IWN_BT_FLAG_COEX6000_MODE_4W 3
+
+#define IWN_BT_FLAG_UCODE_DEFAULT (1 << 6)
+/* Disable Sync PSPoll on SCO/eSCO */
+#define IWN_BT_FLAG_SYNC_2_BT_DISABLE (1 << 7)
uint8_t lead_time;
uint8_t max_kill;
uint8_t bt3_t7_timer;
@@ -878,6 +1307,29 @@
uint16_t rx_prio_boost;
} __packed;
+/* Structures for enhanced command IWN_CMD_BLUETOOTH for 2000 Series. */
+struct iwn2000_btcoex_config {
+ uint8_t flags; // Cf Flags in iwn6000_btcoex_config
+ uint8_t lead_time;
+ uint8_t max_kill;
+ uint8_t bt3_t7_timer;
+ uint32_t kill_ack;
+ uint32_t kill_cts;
+ uint8_t sample_time;
+ uint8_t bt3_t2_timer;
+ uint16_t bt4_reaction;
+ uint32_t lookup_table[12];
+ uint16_t bt4_decision;
+ uint16_t valid;
+
+ uint32_t prio_boost; // size change prior to iwn6000_btcoex_config
+ uint8_t reserved; // added prior to iwn6000_btcoex_config
+
+ uint8_t tx_prio_boost;
+ uint16_t rx_prio_boost;
+} __packed;
+
+
struct iwn_btcoex_priotable {
uint8_t calib_init1;
uint8_t calib_init2;
@@ -899,8 +1351,8 @@
/* Structure for command IWN_CMD_SET_CRITICAL_TEMP. */
struct iwn_critical_temp {
+ uint32_t tempM;
uint32_t reserved;
- uint32_t tempM;
uint32_t tempR;
/* degK <-> degC conversion macros. */
#define IWN_CTOK(c) ((c) + 273)
@@ -955,6 +1407,10 @@
uint16_t reserved;
} __packed;
+/* Define maximal number of calib result send to runtime firmware
+PS: TEMP_OFFSET count for 2 (std and v2)
+*/
+#define IWN5000_PHY_CALIB_MAX_RESULT 8
/* Structures for command IWN_CMD_PHY_CALIB. */
struct iwn_phy_calib {
uint8_t code;
@@ -962,7 +1418,7 @@
#define IWN5000_PHY_CALIB_DC 8
#define IWN5000_PHY_CALIB_LO 9
#define IWN5000_PHY_CALIB_TX_IQ 11
-#define IWN5000_PHY_CALIB_CRYSTAL 15
+#define IWN5000_PHY_CALIB_CRYSTAL 15 //Linux = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD
#define IWN5000_PHY_CALIB_BASE_BAND 16
#define IWN5000_PHY_CALIB_TX_IQ_PERIODIC 17
#define IWN5000_PHY_CALIB_TEMP_OFFSET 18
@@ -975,6 +1431,15 @@
uint8_t isvalid;
} __packed;
+#define IWN_BUF_IX_PHY_CALIB_DC 0
+#define IWN_BUF_IX_PHY_CALIB_LO 1
+#define IWN_BUF_IX_PHY_CALIB_TX_IQ 2
+#define IWN_BUF_IX_PHY_CALIB_CRYSTAL 3
+#define IWN_BUF_IX_PHY_CALIB_BASE_BAND 4
+#define IWN_BUF_IX_PHY_CALIB_TX_IQ_PERIODIC 5
+#define IWN_BUF_IX_PHY_CALIB_TEMP_OFFSET 6
+#define IWN_BUF_IX_PHY_CALIB_TEMP_OFFSETv2 7
+
struct iwn5000_phy_calib_crystal {
uint8_t code;
uint8_t group;
@@ -996,6 +1461,17 @@
uint16_t reserved;
} __packed;
+struct iwn5000_phy_calib_temp_offsetv2 {
+ uint8_t code;
+ uint8_t group;
+ uint8_t ngroups;
+ uint8_t isvalid;
+ int16_t offset_high;
+ int16_t offset_low;
+ int16_t burntVoltageRef;
+ int16_t reserved;
+} __packed;
+
struct iwn_phy_calib_gain {
uint8_t code;
uint8_t group;
@@ -1366,13 +1842,25 @@
#define IWN_FW_TLV_INIT_DATA 4
#define IWN_FW_TLV_BOOT_TEXT 5
#define IWN_FW_TLV_PBREQ_MAXLEN 6
-#define IWN_FW_TLV_ENH_SENS 14
+#define IWN_FW_TLV_PAN 7
+#define IWN_FW_TLV_RUNT_EVTLOG_PTR 8
+#define IWN_FW_TLV_RUNT_EVTLOG_SIZE 9
+#define IWN_FW_TLV_RUNT_ERRLOG_PTR 10
+#define IWN_FW_TLV_INIT_EVTLOG_PTR 11
+#define IWN_FW_TLV_INIT_EVTLOG_SIZE 12
+#define IWN_FW_TLV_INIT_ERRLOG_PTR 13
+#define IWN_FW_TLV_ENH_SENS 14
#define IWN_FW_TLV_PHY_CALIB 15
+#define IWN_FW_TLV_WOWLAN_INST 16
+#define IWN_FW_TLV_WOWLAN_DATA 17
+#define IWN_FW_TLV_FLAGS 18
uint16_t alt;
uint32_t len;
} __packed;
+#define IWN_FW_TLV_FLAGS_NEW_SCAN_BITPOS 1
+
#define IWN4965_FW_TEXT_MAXSZ ( 96 * 1024)
#define IWN4965_FW_DATA_MAXSZ ( 40 * 1024)
#define IWN5000_FW_TEXT_MAXSZ (256 * 1024)
@@ -1389,8 +1877,8 @@
#define IWN_EEPROM_RFCFG 0x048
#define IWN4965_EEPROM_DOMAIN 0x060
#define IWN4965_EEPROM_BAND1 0x063
-#define IWN5000_EEPROM_REG 0x066
-#define IWN5000_EEPROM_CAL 0x067
+#define IWN5000_EEPROM_REG 0x066
+#define IWN5000_EEPROM_CAL 0x067
#define IWN4965_EEPROM_BAND2 0x072
#define IWN4965_EEPROM_BAND3 0x080
#define IWN4965_EEPROM_BAND4 0x08d
@@ -1402,18 +1890,10 @@
#define IWN4965_EEPROM_BANDS 0x0ea
/* Indirect offsets. */
#define IWN5000_EEPROM_DOMAIN 0x001
-#define IWN5000_EEPROM_BAND1 0x004
-#define IWN5000_EEPROM_BAND2 0x013
-#define IWN5000_EEPROM_BAND3 0x021
-#define IWN5000_EEPROM_BAND4 0x02e
-#define IWN5000_EEPROM_BAND5 0x03a
-#define IWN5000_EEPROM_BAND6 0x041
-#define IWN6000_EEPROM_BAND6 0x040
-#define IWN5000_EEPROM_BAND7 0x049
#define IWN6000_EEPROM_ENHINFO 0x054
-#define IWN5000_EEPROM_CRYSTAL 0x128
-#define IWN5000_EEPROM_TEMP 0x12a
-#define IWN5000_EEPROM_VOLT 0x12b
+#define IWN5000_EEPROM_CRYSTAL 0x128 //XTAL in linux 3.2
+#define IWN5000_EEPROM_TEMP 0x12a //KELVIN_TEMPERATURE in linux 3.2
+#define IWN5000_EEPROM_VOLT 0x12b //RAW_TEMPERATURE in linux 3.2
/* Possible flags for IWN_EEPROM_SKU_CAP. */
#define IWN_EEPROM_SKU_CAP_11N (1 << 6)
@@ -1479,9 +1959,29 @@
struct iwn4965_eeprom_chan_samples chans[2];
} __packed;
+/* ADD / MODIFY STATION Command (Op Code 18) - byte 76-18 -bit13
+ STA_FLAG_PAN_STATION bit:
+ This bit is set (1) for a station in PAN mode */
+#define IWN_STA_FLAG_PAN_STATION (1 << 13)
+
+#define IWN_BEACON_INTERVAL_DEFAULT 200
+#define IWN_SLOT_TIME_MIN 20
+
+
+
/*
* Offsets of channels descriptions in EEPROM.
*/
+#define IWN5000_EEPROM_NO_HT40 0x000 //EEPROM_REGULATORY_BAND_NO_HT40
+#define IWN5000_EEPROM_BAND1 0x004 //EEPROM_REG_BAND_1_CHANNELS
+#define IWN5000_EEPROM_BAND2 0x013 //EEPROM_REG_BAND_2_CHANNELS
+#define IWN5000_EEPROM_BAND3 0x021 //EEPROM_REG_BAND_3_CHANNELS
+#define IWN5000_EEPROM_BAND4 0x02e //EEPROM_REG_BAND_4_CHANNELS
+#define IWN5000_EEPROM_BAND5 0x03a //EEPROM_REG_BAND_5_CHANNELS
+#define IWN5000_EEPROM_BAND6 0x041 //EEPROM_REG_BAND_24_HT40_CHANNELS
+#define IWN6000_EEPROM_BAND6 0x040 //EEPROM_6000_REG_BAND_24_HT40_CHANNELS
+#define IWN5000_EEPROM_BAND7 0x049 //EEPROM_REG_BAND_52_HT40_CHANNELS
+
static const uint32_t iwn4965_regulatory_bands[IWN_NBANDS] = {
IWN4965_EEPROM_BAND1,
IWN4965_EEPROM_BAND2,
@@ -1489,7 +1989,7 @@
IWN4965_EEPROM_BAND4,
IWN4965_EEPROM_BAND5,
IWN4965_EEPROM_BAND6,
- IWN4965_EEPROM_BAND7
+ IWN4965_EEPROM_BAND7 // Should be IWN5000_EEPRON_NO_HT40
};
static const uint32_t iwn5000_regulatory_bands[IWN_NBANDS] = {
@@ -1512,6 +2012,16 @@
IWN5000_EEPROM_BAND7
};
+static const uint32_t iwn1000_regulatory_bands[IWN_NBANDS] = {
+ IWN5000_EEPROM_BAND1,
+ IWN5000_EEPROM_BAND2,
+ IWN5000_EEPROM_BAND3,
+ IWN5000_EEPROM_BAND4,
+ IWN5000_EEPROM_BAND5,
+ IWN5000_EEPROM_BAND6,
+ IWN5000_EEPROM_NO_HT40,
+};
+
#define IWN_CHAN_BANDS_COUNT 7
#define IWN_MAX_CHAN_PER_BAND 14
static const struct iwn_chan_band {
@@ -1531,6 +2041,20 @@
{ 11, { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157 } }
};
+static const uint8_t iwn_bss_ac_to_queue[] = {
+ 2, 3, 1, 0,
+};
+
+static const uint8_t iwn_pan_ac_to_queue[] = {
+ 5, 4, 6, 7,
+};
+
+
+/* OTP */
+/* lower blocks contain EEPROM image and calibration data */
+#define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(int)) /* 2 KB */
+
+
#define IWN1000_OTP_NBLOCKS 3
#define IWN6000_OTP_NBLOCKS 4
#define IWN6050_OTP_NBLOCKS 7
@@ -1541,7 +2065,33 @@
#define IWN4965_MAX_PWR_INDEX 107
+#define IWN_POWERSAVE_LVL_NONE 0
+#define IWN_POWERSAVE_LVL_VOIP_COMPATIBLE 1
+#define IWN_POWERSAVE_LVL_MAX 5
+
+#define IWN_POWERSAVE_LVL_DEFAULT IWN_POWERSAVE_LVL_NONE
+
+/* DTIM value to pass in for IWN_POWERSAVE_LVL_VOIP_COMPATIBLE */
+#define IWN_POWERSAVE_DTIM_VOIP_COMPATIBLE 2
+
+
/*
+ * If IWN_DTIM_INDICATES_UNICAST_PENDING_AT_AP is defined, then power saving
+ * (including the power saving done for unicast traffic) becomes proportional
+ * to the DTIM period received from the AP. Otherwise the constant DTIM
+ * period IWN_POWERSAVE_DTIM_VOIP_COMPATIBLE is used.
+ *
+ * Per the 802.11 spec DTIM value as applicable to power saving seems to be
+ * relevant only for indicating the frequency at which broadcast/multicast
+ * data is sent to the PS STAs.
+ * However in practice some APs may also send the unicast traffic along with
+ * the DTIM.
+ */
+#define IWN_DTIM_INDICATES_UNICAST_PENDING_AT_AP
+
+
+
+/*
* RF Tx gain values from highest to lowest power (values obtained from
* the reference driver.)
*/
@@ -1657,6 +2207,7 @@
uint32_t min_energy_cck;
uint32_t energy_cck;
uint32_t energy_ofdm;
+ uint32_t min_corr_barker_mrc;
};
/*
@@ -1671,7 +2222,8 @@
200, 400,
97,
100,
- 100
+ 100,
+ 390
};
static const struct iwn_sensitivity_limits iwn5000_sensitivity_limits = {
@@ -1683,7 +2235,8 @@
170, 400,
95,
95,
- 95
+ 95,
+ 390
};
static const struct iwn_sensitivity_limits iwn5150_sensitivity_limits = {
@@ -1695,7 +2248,8 @@
170, 400,
95,
95,
- 95
+ 95,
+ 390
};
static const struct iwn_sensitivity_limits iwn1000_sensitivity_limits = {
@@ -1707,10 +2261,23 @@
170, 400,
95,
95,
- 95
+ 95,
+ 390
};
-static const struct iwn_sensitivity_limits iwn6000_sensitivity_limits = {
+/*min_ofdm_x1; // auto_corr_min_ofdm_x1 , max_ofdm_x1; //auto_corr_max_ofdm_x1
+min_ofdm_mrc_x1; //auto_corr_min_ofdm_mrc_x1, max_ofdm_mrc_x1; //auto_corr_max_ofdm_mrc
+min_ofdm_x4; //auto_corr_min_ofdm, max_ofdm_x4; //auto_corr_max_ofdm
+min_ofdm_mrc_x4; //auto_corr_min_ofdm_mrc, max_ofdm_mrc_x4 //max_ofdm_mrc_x4
+min_cck_x4; //auto_corr_min_cck, max_cck_x4:auto_corr_max_cck
+min_cck_mrc_x4 : auto_corr_min_cck_mrc max_cck_mrc_x4: auto_corr_max_cck_mrc
+min_energy_cck: min_nrg_cck
+energy_cck:nrg_th_cck
+energy_ofdm:nrg_th_ofdm
+corr_barker_mrc :barker_corr_th_min_mrc
+*/
+ /* Define several specific values for Intel 6000 series */
+ static const struct iwn_sensitivity_limits iwn6000_sensitivity_limits = {
105, 110,
192, 232,
80, 145,
@@ -1717,11 +2284,13 @@
128, 232,
125, 175,
160, 310,
- 97,
- 97,
- 100
+ 110,
+ 110,
+ 110,
+ 336
};
+
/* Map TID to TX scheduler's FIFO. */
static const uint8_t iwn_tid2fifo[] = {
1, 0, 0, 1, 2, 2, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 3
@@ -1805,3 +2374,364 @@
#define IWN_BARRIER_READ_WRITE(sc) \
bus_space_barrier((sc)->sc_st, (sc)->sc_sh, 0, (sc)->sc_sz, \
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)
+
+
+static const uint32_t iwn2030_regulatory_bands[IWN_NBANDS] = {
+ IWN5000_EEPROM_BAND1,
+ IWN5000_EEPROM_BAND2,
+ IWN5000_EEPROM_BAND3,
+ IWN5000_EEPROM_BAND4,
+ IWN5000_EEPROM_BAND5,
+ IWN6000_EEPROM_BAND6,
+ IWN5000_EEPROM_BAND7
+};
+ /* Get value from linux kernel 3.2.+ in Drivers/net/wireless/iwlwifi/iwl-2000.c*/
+static const struct iwn_sensitivity_limits iwn2030_sensitivity_limits = {
+ 105,110,
+ 128,232,
+ 80,145,
+ 128,232,
+ 125,175,
+ 160,310,
+ 97,
+ 97,
+ 110
+};
+
+
+/* =============================================================================
+ * NIC PARAMETERS
+ *
+ * =============================================================================
+ */
+
+/* Flags for managing calibration result. See calib_need in iwn_base_params struct */
+#define IWN_FLG_NEED_PHY_CALIB_DC (1<<0)
+#define IWN_FLG_NEED_PHY_CALIB_LO (1<<1)
+#define IWN_FLG_NEED_PHY_CALIB_TX_IQ (1<<2)
+#define IWN_FLG_NEED_PHY_CALIB_CRYSTAL (1<<3)
+#define IWN_FLG_NEED_PHY_CALIB_BASE_BAND (1<<4)
+#define IWN_FLG_NEED_PHY_CALIB_TX_IQ_PERIODIC (1<<5)
+#define IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET (1<<6)
+#define IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2 (1<<7)
+
+
+/* Define some parameters for managing different NIC.
+ * Refer to linux specific file like iwl-xxxx.c to determine correct value for NIC
+ *
+ *
+ * @max_ll_items: max number of OTP blocks
+ * @shadow_ram_support: shadow support for OTP memory
+ * @led_compensation: compensate on the led on/off time per HW according
+ * to the deviation to achieve the desired led frequency.
+ * The detail algorithm is described in iwl-led.c
+ * @chain_noise_num_beacons: number of beacons used to compute chain noise
+ * @adv_thermal_throttle: support advance thermal throttle
+ * @support_ct_kill_exit: support ct kill exit condition
+ * @support_wimax_coexist: support wimax/wifi co-exist
+ * @plcp_delta_threshold: plcp error rate threshold used to trigger
+ * radio tuning when there is a high receiving plcp error rate
+ * @chain_noise_scale: default chain noise scale used for gain computation
+ * @wd_timeout: TX queues watchdog timeout
+ * @max_event_log_size: size of event log buffer size for ucode event logging
+ * @shadow_reg_enable: HW shadhow register bit
+ * @no_idle_support: do not support idle mode
+ * @hd_v2: v2 of enhanced sensitivity value, used for 2000 series and up
+ * advanced_bt_coexist : Advanced BT management
+ * bt_session_2 : NIC need a new struct for configure BT coexistence. Needed only if advanced_bt_coexist is true
+ * bt_sco_disable :
+ * additional_nic_config: For 6005 series
+ * iq_invert : ? But need it for N 2000 series
+ * regulatory_bands :
+ * enhanced_TX_power : EEPROM Has advanced TX power options. Set 'True' if update_enhanced_txpower = iwl_eeprom_enhanced_txpower
+ * need_temp_offset_calib : Need to compute some temp offset for calibration.
+ * calib_need : Use IWN_FLG_NEED_PHY_CALIB_* flags to specify which calibration data ucode need. See calib_init_cfg in iwl-xxxx.c linux kernel file
+ * additional_gp_drv_bit : Specific bit to defined during nic_config
+ */
+struct iwn_base_params {
+ uint32_t pll_cfg_val;
+ const uint16_t max_ll_items;
+#define IWN_OTP_MAX_LL_ITEMS_1000 (3) /* OTP blocks for 1000 */
+#define IWN_OTP_MAX_LL_ITEMS_6x00 (4) /* OTP blocks for 6x00 */
+#define IWN_OTP_MAX_LL_ITEMS_6x50 (7) /* OTP blocks for 6x50 */
+#define IWN_OTP_MAX_LL_ITEMS_2x00 (4) /* OTP blocks for 2x00 */
+ const bool shadow_ram_support;
+ uint16_t led_compensation;
+ bool adv_thermal_throttle;
+ bool support_ct_kill_exit;
+ uint8_t plcp_delta_threshold;
+ int chain_noise_scale;
+ unsigned int wd_timeout;
+ uint32_t max_event_log_size;
+ const bool shadow_reg_enable;
+ const bool hd_v2;
+ const bool advanced_bt_coexist;
+ const bool bt_session_2;
+ const bool bt_sco_disable;
+ const bool additional_nic_config;
+ const uint32_t *regulatory_bands;
+ const bool enhanced_TX_power; // See iwl-agn-devices.c file to determine that(enhanced_txpower).
+ const uint16_t calib_need;
+ const bool no_crystal_calibration; // see no_xtal_calib in linux
+ const bool support_hostap; //Define IEEE80211_C_HOSTAP for ic_caps
+ const bool no_multi_vaps; // see iwn_vap_create
+ uint8_t additional_gp_drv_bit; //
+
+};
+
+/* NOTA : Values with comments BEFORE are not yet used in driver */
+static struct iwn_base_params iwn_default_base_params = {
+ IWN_ANA_PLL_INIT, // pll_cfg_val
+ 4, //max_ll_items
+ true, // shadow_ram_support
+ /*.led_compensation = */57,
+ /*.adv_thermal_throttle =*/ true,
+ /*.support_ct_kill_exit = */true,
+ /*.plcp_delta_threshold =*/ 50, /*IWL_MAX_PLCP_ERR_THRESHOLD_DEF,*/
+ /*.chain_noise_scale =*/ 1000,
+ /*.wd_timeout = */2000, /* IWL_LONG_WD_TIMEOUT,*/
+ /*.max_event_log_size =*/ 512,
+ false, //shadow_reg_enable
+ /*.hd_v2 = */true,
+ false, // advanced_bt_coexist
+ false, // bt_session_2
+ true, // bt_sco_disable
+ false, //additional_nic_config
+ iwn5000_regulatory_bands, //regulatory_bands
+ false, //enhanced_TX_power
+ (IWN_FLG_NEED_PHY_CALIB_DC | IWN_FLG_NEED_PHY_CALIB_LO | IWN_FLG_NEED_PHY_CALIB_TX_IQ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND ), //calib_need
+ false, //no_crystal_calibration
+ false, //support_hostap
+ true, // no_multi_vaps
+ 0, //additional_gp_drv_bit
+};
+
+static struct iwn_base_params iwn2030_base_params = {
+ 0, //pll_cfg_val
+ IWN_OTP_MAX_LL_ITEMS_2x00, //max_ll_items
+ true, //shadow_ram_support
+ /*.led_compensation = */ 57,
+ /*.adv_thermal_throttle = */ true,
+ /*.support_ct_kill_exit = */ true,
+ /*.plcp_delta_threshold = */ 50,
+ /*.chain_noise_scale = */ 1000,
+ /*.wd_timeout = */ 2000,
+ /*.max_event_log_size = */ 512,
+ false, //shadow_reg_enable
+ /*.hd_v2 = */ true,
+ true, //advanced_bt_coexist
+ true, //bt_session_2
+ true, //bt_sco_disable
+ false, //additional_nic_config
+ iwn2030_regulatory_bands, //regulatory_bands
+ true, //enhanced_TX_power
+ (IWN_FLG_NEED_PHY_CALIB_DC | IWN_FLG_NEED_PHY_CALIB_LO | IWN_FLG_NEED_PHY_CALIB_TX_IQ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND | IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2 ), //calib_need
+ false, //no_crystal_calibration
+ true, //support_hostap
+ false, //no_multi_vaps
+ IWN_GP_DRIVER_REG_BIT_RADIO_IQ_INVERT, // additional_gp_drv_bit
+};
+
+
+static struct iwn_base_params iwn_1000_base_params = {
+ IWN_ANA_PLL_INIT, //pll_cfg_val
+ IWN_OTP_MAX_LL_ITEMS_1000, //max_ll_items
+ false, //shadow_ram_support
+ /*.led_compensation = */57,
+ /*.adv_thermal_throttle =*/ true,
+ /*.support_ct_kill_exit = */true,
+ /*.plcp_delta_threshold =*/ 50, /*IWL_MAX_PLCP_ERR_THRESHOLD_DEF,*/
+ /*.chain_noise_scale =*/ 1000,
+ /*.wd_timeout = */2000, /* IWL_LONG_WD_TIMEOUT,*/
+ /*.max_event_log_size =*/ 512,
+ false, //shadow_reg_enable
+ /*.hd_v2 = */true,
+ false, //advanced_bt_coexist
+ false, //bt_session_2
+ false, //bt_sco_disable
+ false, //additional_nic_config
+ iwn5000_regulatory_bands, //regulatory_bands
+ false, //enhanced_TX_power
+ ( IWN_FLG_NEED_PHY_CALIB_DC | IWN_FLG_NEED_PHY_CALIB_LO | IWN_FLG_NEED_PHY_CALIB_TX_IQ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND ), //calib_need
+ false, //no_crystal_calibration
+ false, //support_hostap
+ true, //no_multi_vaps
+ 0, //additional_gp_drv_bit
+};
+static struct iwn_base_params iwn_6000_base_params = {
+ 0, //pll_cfg_val
+ IWN_OTP_MAX_LL_ITEMS_6x00, // max_ll_items
+ true, //shadow_ram_support
+ /*.led_compensation = */57,
+ /*.adv_thermal_throttle =*/ true,
+ /*.support_ct_kill_exit = */true,
+ /*.plcp_delta_threshold =*/ 50, /*IWL_MAX_PLCP_ERR_THRESHOLD_DEF,*/
+ /*.chain_noise_scale =*/ 1000,
+ /*.wd_timeout = */2000, /* IWL_LONG_WD_TIMEOUT,*/
+ /*.max_event_log_size =*/ 512,
+ false, //shadow_reg_enable
+ /*.hd_v2 = */true,
+ false, // advanced_bt_coexist
+ false, //bt_session_2
+ false, //bt_sco_disable
+ false, //additional_nic_config
+ iwn6000_regulatory_bands, //regulatory_bands
+ true, //enhanced_TX_power
+ (IWN_FLG_NEED_PHY_CALIB_DC | IWN_FLG_NEED_PHY_CALIB_LO | IWN_FLG_NEED_PHY_CALIB_TX_IQ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND ), //calib_need
+ false, //no_crystal_calibration
+ false, //support_hostap
+ true, //no_multi_vaps
+ 0, //additional_gp_drv_bit
+};
+static struct iwn_base_params iwn_6000i_base_params = {
+ 0, //pll_cfg_val
+ IWN_OTP_MAX_LL_ITEMS_6x00, // max_ll_items
+ true, //shadow_ram_support
+ /*.led_compensation = */57,
+ /*.adv_thermal_throttle =*/ true,
+ /*.support_ct_kill_exit = */true,
+ /*.plcp_delta_threshold =*/ 50, /*IWL_MAX_PLCP_ERR_THRESHOLD_DEF,*/
+ /*.chain_noise_scale =*/ 1000,
+ /*.wd_timeout = */2000, /* IWL_LONG_WD_TIMEOUT,*/
+ /*.max_event_log_size =*/ 512,
+ false, //shadow_reg_enable
+ /*.hd_v2 = */true,
+ false, // advanced_bt_coexist
+ false, //bt_session_2
+ true, //bt_sco_disable
+ false, //additional_nic_config
+ iwn6000_regulatory_bands, //regulatory_bands
+ true, //enhanced_TX_power
+ (IWN_FLG_NEED_PHY_CALIB_DC | IWN_FLG_NEED_PHY_CALIB_LO | IWN_FLG_NEED_PHY_CALIB_TX_IQ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND ), //calib_need
+ false, //no_crystal_calibration
+ false, //support_hostap
+ true, //no_multi_vaps
+ 0, //additional_gp_drv_bit
+};
+static struct iwn_base_params iwn_6000g2_base_params = {
+ 0, //pll_cfg_val
+ IWN_OTP_MAX_LL_ITEMS_6x00, // max_ll_items
+ true, //shadow_ram_support
+ /*.led_compensation = */57,
+ /*.adv_thermal_throttle =*/ true,
+ /*.support_ct_kill_exit = */true,
+ /*.plcp_delta_threshold =*/ 50, /*IWL_MAX_PLCP_ERR_THRESHOLD_DEF,*/
+ /*.chain_noise_scale =*/ 1000,
+ /*.wd_timeout = */2000, /* IWL_LONG_WD_TIMEOUT,*/
+ /*.max_event_log_size =*/ 512,
+ false, //shadow_reg_enable
+ /*.hd_v2 = */true,
+ false, // advanced_bt_coexist
+ false, //bt_session_2
+ true, //bt_sco_disable
+ false, //additional_nic_config
+ iwn6000_regulatory_bands, //regulatory_bands
+ true, //enhanced_TX_power
+ (IWN_FLG_NEED_PHY_CALIB_DC | IWN_FLG_NEED_PHY_CALIB_LO | IWN_FLG_NEED_PHY_CALIB_TX_IQ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND|IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET ), //calib_need
+ false, //no_crystal_calibration
+ false, //support_hostap
+ true, //no_multi_vaps
+ 0, //additional_gp_drv_bit
+};
+static struct iwn_base_params iwn_6050_base_params = {
+ 0, //pll_cfg_val
+ IWN_OTP_MAX_LL_ITEMS_6x50, // max_ll_items
+ true, //shadow_ram_support
+ /*.led_compensation = */57,
+ /*.adv_thermal_throttle =*/ true,
+ /*.support_ct_kill_exit = */true,
+ /*.plcp_delta_threshold =*/ 50, /*IWL_MAX_PLCP_ERR_THRESHOLD_DEF,*/
+ /*.chain_noise_scale =*/ 1000,
+ /*.wd_timeout = */2000, /* IWL_LONG_WD_TIMEOUT,*/
+ /*.max_event_log_size =*/ 512,
+ false, //shadow_reg_enable
+ /*.hd_v2 = */true,
+ false, // advanced_bt_coexist
+ false, //bt_session_2
+ true, //bt_sco_disable
+ true, //additional_nic_config
+ iwn6000_regulatory_bands, //regulatory_bands
+ true, //enhanced_TX_power
+ (IWN_FLG_NEED_PHY_CALIB_DC | IWN_FLG_NEED_PHY_CALIB_LO | IWN_FLG_NEED_PHY_CALIB_TX_IQ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND|IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET ), //calib_need
+ false, //no_crystal_calibration
+ false, //support_hostap
+ true, //no_multi_vaps
+ 0, //additional_gp_drv_bit
+};
+static struct iwn_base_params iwn_6150_base_params = {
+ 0, //pll_cfg_val
+ IWN_OTP_MAX_LL_ITEMS_6x50, // max_ll_items
+ true, //shadow_ram_support
+ /*.led_compensation = */57,
+ /*.adv_thermal_throttle =*/ true,
+ /*.support_ct_kill_exit = */true,
+ /*.plcp_delta_threshold =*/ 50, /*IWL_MAX_PLCP_ERR_THRESHOLD_DEF,*/
+ /*.chain_noise_scale =*/ 1000,
+ /*.wd_timeout = */2000, /* IWL_LONG_WD_TIMEOUT,*/
+ /*.max_event_log_size =*/ 512,
+ false, //shadow_reg_enable
+ /*.hd_v2 = */true,
+ false, // advanced_bt_coexist
+ false, //bt_session_2
+ true, //bt_sco_disable
+ true, //additional_nic_config
+ iwn6000_regulatory_bands, //regulatory_bands
+ true, //enhanced_TX_power
+ (IWN_FLG_NEED_PHY_CALIB_DC | IWN_FLG_NEED_PHY_CALIB_LO | IWN_FLG_NEED_PHY_CALIB_TX_IQ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND|IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET ), //calib_need
+ false, //no_crystal_calibration
+ false, //support_hostap
+ true, //no_multi_vaps
+ IWN_GP_DRIVER_6050_1X2, //additional_gp_drv_bit
+};
+//IWL_DEVICE_6035 & IWL_DEVICE_6030
+static struct iwn_base_params iwn_6000g2b_base_params = {
+ 0, //pll_cfg_val
+ IWN_OTP_MAX_LL_ITEMS_6x00, // max_ll_items
+ true, //shadow_ram_support
+ /*.led_compensation = */57,
+ /*.adv_thermal_throttle =*/ true,
+ /*.support_ct_kill_exit = */true,
+ /*.plcp_delta_threshold =*/ 50, /*IWL_MAX_PLCP_ERR_THRESHOLD_DEF,*/
+ /*.chain_noise_scale =*/ 1000,
+ /*.wd_timeout = */2000, /* IWL_LONG_WD_TIMEOUT,*/
+ /*.max_event_log_size =*/ 512,
+ false, //shadow_reg_enable
+ /*.hd_v2 = */true,
+ true, // advanced_bt_coexist
+ false, //bt_session_2
+ true, //bt_sco_disable
+ false, //additional_nic_config
+ iwn6000_regulatory_bands, //regulatory_bands
+ true, //enhanced_TX_power
+ (IWN_FLG_NEED_PHY_CALIB_DC | IWN_FLG_NEED_PHY_CALIB_LO | IWN_FLG_NEED_PHY_CALIB_TX_IQ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND|IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET ), //calib_need
+ false, //no_crystal_calibration
+ false, //support_hostap
+ true, //no_multi_vaps
+ 0, //additional_gp_drv_bit
+};
+static struct iwn_base_params iwn_5x50_base_params = {
+ IWN_ANA_PLL_INIT, // pll_cfg_val
+ 4, //max_ll_items
+ true, // shadow_ram_support
+ /*.led_compensation = */57,
+ /*.adv_thermal_throttle =*/ true,
+ /*.support_ct_kill_exit = */true,
+ /*.plcp_delta_threshold =*/ 50, /*IWL_MAX_PLCP_ERR_THRESHOLD_DEF,*/
+ /*.chain_noise_scale =*/ 1000,
+ /*.wd_timeout = */2000, /* IWL_LONG_WD_TIMEOUT,*/
+ /*.max_event_log_size =*/ 512,
+ false, //shadow_reg_enable
+ /*.hd_v2 = */true,
+ false, // advanced_bt_coexist
+ false, // bt_session_2
+ true, // bt_sco_disable
+ false, //additional_nic_config
+ iwn5000_regulatory_bands, //regulatory_bands
+ false, //enhanced_TX_power
+ (IWN_FLG_NEED_PHY_CALIB_DC | IWN_FLG_NEED_PHY_CALIB_LO | IWN_FLG_NEED_PHY_CALIB_TX_IQ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND ), //calib_need
+ true, //no_crystal_calibration
+ false, //support_hostap
+ true, // no_multi_vaps
+ 0, //additional_gp_drv_bit
+};
+
Index: sys/dev/iwn/if_iwnvar.h
===================================================================
--- sys/dev/iwn/if_iwnvar.h (revision 253707)
+++ sys/dev/iwn/if_iwnvar.h (working copy)
@@ -2,6 +2,8 @@
/* $OpenBSD: if_iwnvar.h,v 1.18 2010/04/30 16:06:46 damien Exp $ */
/*-
+ * Copyright (c) 2013 Cedric GROSS <lenine@bsdfrance.fr>
+ * Copyright (c) 2011 Intel Corporation
* Copyright (c) 2007, 2008
* Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2008 Sam Leffler, Errno Consulting
@@ -18,7 +20,42 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+enum iwn_rxon_ctx_id {
+ IWN_RXON_BSS_CTX,
+ IWN_RXON_PAN_CTX,
+ IWN_NUM_RXON_CTX
+};
+
+struct iwn_pan_slot {
+ uint16_t time;
+ uint8_t type;
+ uint8_t reserved;
+} __packed;
+
+struct iwn_pan_params_cmd {
+ uint16_t flags;
+#define IWN_PAN_PARAMS_FLG_SLOTTED_MODE (1 << 3)
+
+ uint8_t reserved;
+ uint8_t num_slots;
+ struct iwn_pan_slot slots[10];
+} __packed;
+
+
+struct iwn_led_mode
+{
+ uint8_t led_cur_mode;
+ uint64_t led_cur_bt;
+ uint64_t led_last_bt;
+ uint64_t led_cur_tpt;
+ uint64_t led_last_tpt;
+ uint64_t led_bt_diff;
+ int led_cur_time;
+ int led_last_time;
+};
+
+
struct iwn_rx_radiotap_header {
struct ieee80211_radiotap_header wr_ihdr;
uint64_t wr_tsft;
@@ -140,6 +177,9 @@
uint32_t energy_samples[10];
u_int cur_energy_sample;
uint32_t energy_cck;
+
+ uint32_t corr_barker_mrc;
+ uint32_t energy_ofdm;
};
struct iwn_calib_info {
@@ -191,6 +231,10 @@
int (*iv_newstate)(struct ieee80211vap *,
enum ieee80211_state, int);
+ int ctx;
+ int beacon_int;
+ uint8_t macaddr[IEEE80211_ADDR_LEN];
+
};
#define IWN_VAP(_vap) ((struct iwn_vap *)(_vap))
@@ -203,15 +247,18 @@
struct mtx sc_mtx;
u_int sc_flags;
-#define IWN_FLAG_HAS_OTPROM (1 << 1)
-#define IWN_FLAG_CALIB_DONE (1 << 2)
-#define IWN_FLAG_USE_ICT (1 << 3)
+#define IWN_FLAG_HAS_OTPROM (1 << 1)
+#define IWN_FLAG_CALIB_DONE (1 << 2)
+#define IWN_FLAG_USE_ICT (1 << 3)
#define IWN_FLAG_INTERNAL_PA (1 << 4)
-#define IWN_FLAG_HAS_11N (1 << 6)
-#define IWN_FLAG_ENH_SENS (1 << 7)
-#define IWN_FLAG_ADV_BTCOEX (1 << 8)
+#define IWN_FLAG_HAS_11N (1 << 6)
+#define IWN_FLAG_ENH_SENS (1 << 7)
+#define IWN_FLAG_ADV_BTCOEX (1 << 8)
+#define IWN_FLAG_PAN_SUPPORT (1 << 9)
uint8_t hw_type;
+ /* subdevice_id used to adjust configuration */
+ uint16_t subdevice_id;
struct iwn_ops ops;
const char *fwname;
@@ -272,15 +319,20 @@
int calib_cnt;
struct iwn_calib_state calib;
struct callout watchdog_to;
-
+ struct callout ct_kill_exit_to;
struct iwn_fw_info fw;
- struct iwn_calib_info calibcmd[5];
+ struct iwn_calib_info calibcmd[IWN5000_PHY_CALIB_MAX_RESULT];
uint32_t errptr;
struct iwn_rx_stat last_rx_stat;
int last_rx_valid;
struct iwn_ucode_info ucode_info;
- struct iwn_rxon rxon;
+ struct iwn_rxon rx_on[IWN_NUM_RXON_CTX];
+ struct iwn_rxon *rxon;
+ int ctx;
+ struct ieee80211vap *ivap[IWN_NUM_RXON_CTX];
+ uint8_t uc_pan_support; /*CG: PAN support */
+ uint8_t uc_scan_progress;
uint32_t rawtemp;
int temp;
int noise;
@@ -295,11 +347,14 @@
char eeprom_domain[4];
uint32_t eeprom_crystal;
int16_t eeprom_temp;
+ int16_t eeprom_temp_high;
int16_t eeprom_voltage;
int8_t maxpwr2GHz;
int8_t maxpwr5GHz;
int8_t maxpwr[IEEE80211_CHAN_MAX];
+ uint32_t tlv_feature_flags;
+
int32_t temp_off;
uint32_t int_mask;
uint8_t ntxchains;
@@ -309,6 +364,7 @@
uint8_t chainmask;
int sc_tx_timer;
+ int sc_scan_timer;
struct ieee80211_tx_ampdu *qid2tap[IWN5000_NTXQUEUES];
@@ -323,9 +379,22 @@
void (*sc_addba_stop)(struct ieee80211_node *,
struct ieee80211_tx_ampdu *);
+ struct iwn_led_mode sc_led;
struct iwn_rx_radiotap_header sc_rxtap;
struct iwn_tx_radiotap_header sc_txtap;
+
+
+ /* The power save level originally configured by user */
+ int desired_pwrsave_level;
+
+ /* The current power save level, this may differ from the configured value due to
+ * thermal throttling etc.
+ * */
+ int current_pwrsave_level;
+
+ /* For specifique params */
+ struct iwn_base_params *base_params;
};
#define IWN_LOCK_INIT(_sc) \
@@ -335,3 +404,5 @@
#define IWN_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
#define IWN_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
#define IWN_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx)
+#define IWN_UC_PAN_PRESENT 1
+
Index: sys/modules/iwn/Makefile
===================================================================
--- sys/modules/iwn/Makefile (revision 253707)
+++ sys/modules/iwn/Makefile (working copy)
@@ -5,4 +5,12 @@
KMOD = if_iwn
SRCS = if_iwn.c device_if.h bus_if.h pci_if.h
+.if !defined(KERNBUILDDIR)
+opt_wlan.h:
+ echo "#define IEEE80211_DEBUG 1" > ${.TARGET}
+.endif
+.if IWN_DEBUG
+CFLAGS+=-DIWN_DEBUG
+.endif
+
.include <bsd.kmod.mk>
Index: sys/modules/iwnfw/Makefile
===================================================================
--- sys/modules/iwnfw/Makefile (revision 253707)
+++ sys/modules/iwnfw/Makefile (working copy)
@@ -1,5 +1,5 @@
# $FreeBSD$
-SUBDIR= iwn1000 iwn4965 iwn5000 iwn5150 iwn6000 iwn6000g2a iwn6000g2b iwn6050
+SUBDIR= iwn1000 iwn4965 iwn5000 iwn5150 iwn6000 iwn6000g2a iwn6000g2b iwn6050 iwn2030
.include <bsd.subdir.mk>
Index: sys/modules/iwnfw/iwn2030/Makefile
===================================================================
--- sys/modules/iwnfw/iwn2030/Makefile (revision 0)
+++ sys/modules/iwnfw/iwn2030/Makefile (working copy)
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+KMOD= iwn2030fw
+IMG= iwnwifi-2030-18.168.6.1
+
+.include <bsd.kmod.mk>
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?000301ce8b6e$cbca9dc0$635fd940$>
