From owner-svn-src-all@FreeBSD.ORG Tue Nov 12 05:58:24 2013 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 789E2BD3; Tue, 12 Nov 2013 05:58:24 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 672122158; Tue, 12 Nov 2013 05:58:24 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id rAC5wOEf096276; Tue, 12 Nov 2013 05:58:24 GMT (envelope-from adrian@svn.freebsd.org) Received: (from adrian@localhost) by svn.freebsd.org (8.14.7/8.14.5/Submit) id rAC5wO2Y096274; Tue, 12 Nov 2013 05:58:24 GMT (envelope-from adrian@svn.freebsd.org) Message-Id: <201311120558.rAC5wO2Y096274@svn.freebsd.org> From: Adrian Chadd Date: Tue, 12 Nov 2013 05:58:24 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r258035 - head/sys/dev/iwn X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 12 Nov 2013 05:58:24 -0000 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 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 #include #include +#include #include 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<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 ***