svn commit: r258035 - head/sys/dev/iwn
Adrian Chadd
adrian at FreeBSD.org
Tue Nov 12 05:58:24 UTC 2013
Author: adrian
Date: Tue Nov 12 05:58:23 2013
New Revision: 258035
URL: http://svnweb.freebsd.org/changeset/base/258035
Log:
Commit over some work to prepare the iwn(4) driver for further chipset
support.
* Extend the hardware base_params structure to include a bunch of hardware
flags indicating what is and isn't supported.
* Convert a bunch of the initial hardware configuration conditionals to
consult the base_params structure.
* Add new calibration code for temperature calibration for the Centrino 2xxx
series NICs.
* Add new bluetooth coexistence code for Centrino 2xxx series NICs.
* For NICs that support PAN (personal area networking), use a different
transmit queue and command queue setup, in preparation for said
PAN support.
* Extend the calibration array in iwn_softc to include enough space for
the new calibration types.
Tested (by myself, if not mentioned):
* Intel 4965
* Intel 5100
* Intel 6150
* Intel 2230
* Intel 2200 (eadler)
* Intel 1030
* Intel 6200
* Intel 6230
* Intel 6250
* Intel 6150
* Intel 100
What doesn't work:
* Intel 6235 - fails in calibration at startup
TODO:
* Testing on Intel 53xx series hardware
Submitted by: Cedric Gross <cg at cgross.info>
Added:
head/sys/dev/iwn/if_iwn_chip_cfg.h (contents, props changed)
Modified:
head/sys/dev/iwn/if_iwn.c
head/sys/dev/iwn/if_iwnvar.h
Modified: head/sys/dev/iwn/if_iwn.c
==============================================================================
--- head/sys/dev/iwn/if_iwn.c Tue Nov 12 05:49:01 2013 (r258034)
+++ head/sys/dev/iwn/if_iwn.c Tue Nov 12 05:58:23 2013 (r258035)
@@ -78,6 +78,7 @@ __FBSDID("$FreeBSD$");
#include <dev/iwn/if_iwnreg.h>
#include <dev/iwn/if_iwnvar.h>
#include <dev/iwn/if_iwn_devid.h>
+#include <dev/iwn/if_iwn_chip_cfg.h>
#include <dev/iwn/if_iwn_debug.h>
struct iwn_ident {
@@ -99,6 +100,9 @@ static const struct iwn_ident iwn_ident_
{ 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_2x00_1, "Intel(R) Centrino(R) Wireless-N 2200 BGN" },
+ { 0x8086, IWN_DID_2x00_2, "Intel(R) Centrino(R) Wireless-N 2200 BGN" },
+ /* XXX 2200D is IWN_SDID_2x00_4; there's no way to express this here! */
{ 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" },
@@ -121,6 +125,15 @@ static const struct iwn_ident iwn_ident_
{ 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" },
+ /*
+ * These currently don't function; the firmware crashes during
+ * the startup calibration request.
+ */
+#if 0
+ { 0x8086, IWN_DID_6035_1, "Intel Centrino Advanced 6235" },
+ /* XXX TODO: figure out which ID this one is? */
+ { 0x8086, IWN_DID_6035_2, "Intel Centrino Advanced 6235" },
+#endif
{ 0, 0, NULL }
};
@@ -128,6 +141,7 @@ static int iwn_probe(device_t);
static int iwn_attach(device_t);
static int iwn4965_attach(struct iwn_softc *, uint16_t);
static int iwn5000_attach(struct iwn_softc *, uint16_t);
+static int iwn_config_specific(struct iwn_softc *, uint16_t);
static void iwn_radiotap_attach(struct iwn_softc *);
static void iwn_sysctlattach(struct iwn_softc *);
static struct ieee80211vap *iwn_vap_create(struct ieee80211com *,
@@ -294,6 +308,7 @@ static int iwn5000_send_calibration(stru
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 *,
@@ -452,6 +467,11 @@ iwn_attach(device_t dev)
sc->hw_type = (IWN_READ(sc, IWN_HW_REV) >> IWN_HW_REV_TYPE_SHIFT)
& IWN_HW_REV_TYPE_MASK;
sc->subdevice_id = pci_get_subdevice(dev);
+
+ /*
+ * 4965 versus 5000 and later have different methods.
+ * Let's set those up first.
+ */
if (sc->hw_type == IWN_HW_REV_TYPE_4965)
error = iwn4965_attach(sc, pci_get_device(dev));
else
@@ -462,6 +482,16 @@ iwn_attach(device_t dev)
goto fail;
}
+ /*
+ * Next, let's setup the various parameters of each NIC.
+ */
+ error = iwn_config_specific(sc, pci_get_device(dev));
+ if (error != 0) {
+ device_printf(dev, "could not attach device, error %d\n",
+ error);
+ goto fail;
+ }
+
if ((error = iwn_hw_prepare(sc)) != 0) {
device_printf(dev, "hardware not ready, error %d\n", error);
goto fail;
@@ -671,6 +701,441 @@ fail:
return error;
}
+/*
+ * 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) {
+/* 4965 series */
+ case IWN_DID_4965_1:
+ case IWN_DID_4965_2:
+ case IWN_DID_4965_3:
+ case IWN_DID_4965_4:
+ sc->base_params = &iwn4965_base_params;
+ sc->limits = &iwn4965_sensitivity_limits;
+ sc->fwname = "iwn4965fw";
+ /* Override chains masks, ROM is known to be broken. */
+ sc->txchainmask = IWN_ANT_AB;
+ sc->rxchainmask = IWN_ANT_ABC;
+ /* Enable normal btcoex */
+ sc->sc_flags |= IWN_FLAG_BTCOEX;
+ break;
+/* 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 = &iwn1000_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 adjustment 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 = &iwn1000_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;
+
+/* 2x00 Series */
+ case IWN_DID_2x00_1:
+ case IWN_DID_2x00_2:
+ switch(sc->subdevice_id) {
+ case IWN_SDID_2x00_1:
+ case IWN_SDID_2x00_2:
+ case IWN_SDID_2x00_3:
+ //iwl2000_2bgn_cfg
+ case IWN_SDID_2x00_4:
+ //iwl2000_2bgn_d_cfg
+ sc->limits = &iwn2030_sensitivity_limits;
+ sc->base_params = &iwn2000_base_params;
+ sc->fwname = "iwn2000fw";
+ 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 = &iwn5000_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 = &iwn5000_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 = &iwn5000_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;
+}
+
static int
iwn4965_attach(struct iwn_softc *sc, uint16_t pid)
{
@@ -748,90 +1213,6 @@ iwn5000_attach(struct iwn_softc *sc, uin
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;
- /* Enable normal btcoex */
- sc->sc_flags |= IWN_FLAG_BTCOEX;
- break;
- case IWN_HW_REV_TYPE_5150:
- sc->limits = &iwn5150_sensitivity_limits;
- sc->fwname = "iwn5150fw";
- /* Enable normal btcoex */
- sc->sc_flags |= IWN_FLAG_BTCOEX;
- break;
- case IWN_HW_REV_TYPE_5300:
- case IWN_HW_REV_TYPE_5350:
- sc->limits = &iwn5000_sensitivity_limits;
- sc->fwname = "iwn5000fw";
- /* Enable normal btcoex */
- sc->sc_flags |= IWN_FLAG_BTCOEX;
- break;
- case IWN_HW_REV_TYPE_1000:
- sc->limits = &iwn1000_sensitivity_limits;
- sc->fwname = "iwn1000fw";
- /* Enable normal btcoex */
- sc->sc_flags |= IWN_FLAG_BTCOEX;
- break;
- case IWN_HW_REV_TYPE_6000:
- sc->limits = &iwn6000_sensitivity_limits;
- sc->fwname = "iwn6000fw";
- /*
- * Disable btcoex for 6200.
- * XXX TODO: disable for 6205; no btcoex as well
- * (6230/6235 - enable bluetooth)
- */
- if (pid != 0x422c) {
- /* Enable normal btcoex */
- sc->sc_flags |= IWN_FLAG_BTCOEX;
- }
- 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;
- /* Enable normal btcoex */
- sc->sc_flags |= IWN_FLAG_BTCOEX;
- 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";
- /*
- * 6250 - disable bluetooth coexistence.
- */
- }
- 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;
- }
- if (sc->sc_flags & IWN_FLAG_BTCOEX)
- device_printf(sc->sc_dev,
- "enable basic bluetooth coexistence\n");
- else if (sc->sc_flags & IWN_FLAG_ADV_BTCOEX)
- device_printf(sc->sc_dev,
- "enable advanced bluetooth coexistence\n");
- else
- device_printf(sc->sc_dev,
- "disable bluetooth coexistence\n");
return 0;
}
@@ -1154,7 +1535,7 @@ iwn_init_otprom(struct iwn_softc *sc)
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);
}
@@ -1167,11 +1548,12 @@ iwn_init_otprom(struct iwn_softc *sc)
* 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;
@@ -1180,7 +1562,7 @@ iwn_init_otprom(struct iwn_softc *sc)
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;
@@ -1830,15 +2212,12 @@ iwn5000_read_eeprom(struct iwn_softc *sc
/* Read the list of authorized channels (20MHz ones only). */
for (i = 0; i < IWN_NBANDS - 1; i++) {
- if (sc->hw_type >= IWN_HW_REV_TYPE_6000)
- addr = base + iwn6000_regulatory_bands[i];
- else
- addr = base + iwn5000_regulatory_bands[i];
+ addr = base + sc->base_params->regulatory_bands[i];
iwn_read_eeprom_channels(sc, i, addr);
}
/* 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);
@@ -1849,6 +2228,14 @@ iwn5000_read_eeprom(struct iwn_softc *sc
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. */
iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP, &val, 2);
@@ -2698,25 +3085,24 @@ iwn5000_rx_calib_results(struct iwn_soft
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. */
@@ -2733,7 +3119,7 @@ iwn5000_rx_calib_results(struct iwn_soft
return;
}
DPRINTF(sc, IWN_DEBUG_CALIBRATE,
- "saving calibration result code=%d len=%d\n", calib->code, len);
+ "saving calibration result idx=%d, code=%d len=%d\n", idx, calib->code, len);
sc->calibcmd[idx].len = len;
memcpy(sc->calibcmd[idx].buf, calib, len);
}
@@ -2947,12 +3333,19 @@ iwn_tx_done(struct iwn_softc *sc, struct
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;
+
+ if ((desc->qid & IWN_RX_DESC_QID_MSK) != 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. */
@@ -3862,8 +4255,15 @@ iwn_tx_data(struct iwn_softc *sc, struct
data->m = m;
data->ni = ni;
- DPRINTF(sc, IWN_DEBUG_XMIT, "%s: qid %d idx %d len %d nsegs %d\n",
- __func__, ring->qid, ring->cur, m->m_pkthdr.len, nsegs);
+ DPRINTF(sc, IWN_DEBUG_XMIT,
+ "%s: qid %d idx %d len %d nsegs %d rate %04x plcp 0x%08x\n",
+ __func__,
+ ring->qid,
+ ring->cur,
+ m->m_pkthdr.len,
+ nsegs,
+ rate,
+ tx->rate);
/* Fill TX descriptor. */
desc->nsegs = 1;
@@ -4261,19 +4661,26 @@ iwn_ioctl(struct ifnet *ifp, u_long cmd,
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;
struct mbuf *m;
bus_addr_t paddr;
int totlen, error;
+ int cmd_queue_num;
DPRINTF(sc, IWN_DEBUG_TRACE, "->%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;
@@ -4382,7 +4789,7 @@ iwn_set_link_quality(struct iwn_softc *s
linkq.id = wn->id;
linkq.antmsk_1stream = txant;
linkq.antmsk_2stream = IWN_ANT_AB;
- linkq.ampdu_max = 64;
+ linkq.ampdu_max = 32; /* XXX negotiated? */
linkq.ampdu_threshold = 3;
linkq.ampdu_limit = htole16(4000); /* 4ms */
@@ -4400,6 +4807,9 @@ iwn_set_link_quality(struct iwn_softc *s
}
/* Start at highest available bit-rate. */
+ /*
+ * XXX this is all very dirty!
+ */
if (is_11n)
txrate = ni->ni_htrates.rs_nrates - 1;
else
@@ -4412,6 +4822,13 @@ iwn_set_link_quality(struct iwn_softc *s
else
rate = RV(rs->rs_rates[txrate]);
+ DPRINTF(sc, IWN_DEBUG_XMIT,
+ "%s: i=%d, txrate=%d, rate=0x%02x\n",
+ __func__,
+ i,
+ txrate,
+ rate);
+
/* Do rate -> PLCP config mapping */
plcp = iwn_rate_to_plcp(sc, ni, rate);
linkq.retry[i] = plcp;
@@ -5412,25 +5829,74 @@ iwn_send_advanced_btcoex(struct iwn_soft
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;
@@ -5485,13 +5951,32 @@ iwn_config(struct iwn_softc *sc)
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__);
- return error;
+ return (error);
+ }
+ } 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 compute temperature offset v2\n",
+ __func__);
+ return (error);
}
}
@@ -5523,10 +6008,13 @@ iwn_config(struct iwn_softc *sc)
/* Configure bluetooth coexistence. */
error = 0;
- if (sc->sc_flags & IWN_FLAG_ADV_BTCOEX)
+
+ /* Configure bluetooth coexistence if needed. */
+ if (sc->base_params->bt_mode == IWN_BT_ADVANCED)
error = iwn_send_advanced_btcoex(sc);
- else if (sc->sc_flags & IWN_FLAG_BTCOEX)
+ if (sc->base_params->bt_mode == IWN_BT_SIMPLE)
error = iwn_send_btcoex(sc);
+
if (error != 0) {
device_printf(sc->sc_dev,
"%s: could not configure bluetooth coexistence, error %d\n",
@@ -6335,9 +6823,20 @@ iwn5000_send_calibration(struct iwn_soft
{
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);
@@ -6414,6 +6913,33 @@ iwn5000_temp_offset_calib(struct iwn_sof
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;
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-all
mailing list