Add support for Intel Centrino Wireless-N 2230.

Fixes #12006.

Signed-off-by: Adrien Destugues <[email protected]>
This commit is contained in:
Dan MacDonald
2015-04-28 20:49:46 +02:00
committed by Adrien Destugues
parent 5de22b9bf6
commit 1894a24358
5 changed files with 155 additions and 30 deletions
@@ -25,12 +25,14 @@ KernelAddon iprowifi4965 :
; ;
HAIKU_WIFI_FIRMWARE_PACKAGES on iprowifi4965 = HAIKU_WIFI_FIRMWARE_PACKAGES on iprowifi4965 =
iwlwifi-1000-ucode-39.31.5.1 iwlwifi-4965-ucode-228.61.2.24 iwlwifi-1000-ucode-39.31.5.1
iwlwifi-2030-ucode-18.168.6.1 iwlwifi-4965-ucode-228.61.2.24
iwlwifi-5000-ucode-8.83.5.1 iwlwifi-5150-ucode-8.24.2.2 iwlwifi-5000-ucode-8.83.5.1 iwlwifi-5150-ucode-8.24.2.2
iwlwifi-6000-ucode-9.221.4.1 iwlwifi-6000g2a-ucode-18.168.6.1 iwlwifi-6000-ucode-9.221.4.1 iwlwifi-6000g2a-ucode-18.168.6.1
iwlwifi-6000g2b-ucode-18.168.6.1 iwlwifi-6050-ucode-41.28.5.1 ; iwlwifi-6000g2b-ucode-18.168.6.1 iwlwifi-6050-ucode-41.28.5.1 ;
HAIKU_WIFI_FIRMWARE_ARCHIVES on iprowifi4965 = HAIKU_WIFI_FIRMWARE_ARCHIVES on iprowifi4965 =
iwlwifi-1000-ucode-39.31.5.1.tgz iwlwifi-4965-ucode-228.61.2.24.tgz iwlwifi-1000-ucode-39.31.5.1.tgz
iwlwifi-2030-ucode-18.168.6.1.tgz iwlwifi-4965-ucode-228.61.2.24.tgz
iwlwifi-5000-ucode-8.83.5.1.tgz iwlwifi-5150-ucode-8.24.2.2.tgz iwlwifi-5000-ucode-8.83.5.1.tgz iwlwifi-5150-ucode-8.24.2.2.tgz
iwlwifi-6000-ucode-9.221.4.1.tgz iwlwifi-6000g2a-ucode-18.168.6.1.tgz iwlwifi-6000-ucode-9.221.4.1.tgz iwlwifi-6000g2a-ucode-18.168.6.1.tgz
iwlwifi-6000g2b-ucode-18.168.6.1.tgz iwlwifi-6050-ucode-41.28.5.1.tgz ; iwlwifi-6000g2b-ucode-18.168.6.1.tgz iwlwifi-6050-ucode-41.28.5.1.tgz ;
@@ -284,7 +284,8 @@ static int iwn5000_query_calibration(struct iwn_softc *);
static int iwn5000_send_calibration(struct iwn_softc *); static int iwn5000_send_calibration(struct iwn_softc *);
static int iwn5000_send_wimax_coex(struct iwn_softc *); static int iwn5000_send_wimax_coex(struct iwn_softc *);
static int iwn5000_crystal_calib(struct iwn_softc *); static int iwn5000_crystal_calib(struct iwn_softc *);
static int iwn5000_temp_offset_calib(struct iwn_softc *); static int iwn6000_temp_offset_calib(struct iwn_softc *);
static int iwn2000_temp_offset_calib(struct iwn_softc *);
static int iwn4965_post_alive(struct iwn_softc *); static int iwn4965_post_alive(struct iwn_softc *);
static int iwn5000_post_alive(struct iwn_softc *); static int iwn5000_post_alive(struct iwn_softc *);
static int iwn4965_load_bootcode(struct iwn_softc *, const uint8_t *, static int iwn4965_load_bootcode(struct iwn_softc *, const uint8_t *,
@@ -806,6 +807,11 @@ iwn5000_attach(struct iwn_softc *sc, uint16_t pid)
} else } else
sc->fwname = "iwn6000g2afw"; sc->fwname = "iwn6000g2afw";
break; break;
case IWN_HW_REV_TYPE_2030:
sc->limits = &iwn2000_sensitivity_limits;
sc->fwname = "iwn2030fw";
sc->sc_flags |= IWN_FLAG_ADV_BTCOEX;
break;
default: default:
device_printf(sc->sc_dev, "adapter type %d not supported\n", device_printf(sc->sc_dev, "adapter type %d not supported\n",
sc->hw_type); sc->hw_type);
@@ -1774,6 +1780,14 @@ iwn5000_read_eeprom(struct iwn_softc *sc)
hdr.version, hdr.pa_type, le16toh(hdr.volt)); hdr.version, hdr.pa_type, le16toh(hdr.volt));
sc->calib_ver = hdr.version; sc->calib_ver = hdr.version;
if (sc->hw_type == IWN_HW_REV_TYPE_2030) {
sc->eeprom_voltage = htole16(hdr.volt);
iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP, &val, 2);
sc->eeprom_temp = htole16(val);
iwn_read_prom_data(sc, base + IWN2000_EEPROM_RAWTEMP, &val, 2);
sc->eeprom_rawtemp = htole16(val);
}
if (sc->hw_type == IWN_HW_REV_TYPE_5150) { if (sc->hw_type == IWN_HW_REV_TYPE_5150) {
/* Compute temperature offset. */ /* Compute temperature offset. */
iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP, &val, 2); iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP, &val, 2);
@@ -5002,28 +5016,55 @@ iwn_send_advanced_btcoex(struct iwn_softc *sc)
0xcc00ff28, 0x0000aaaa, 0xcc00aaaa, 0x0000aaaa, 0xcc00ff28, 0x0000aaaa, 0xcc00aaaa, 0x0000aaaa,
0xc0004000, 0x00004000, 0xf0005000, 0xf0005000, 0xc0004000, 0x00004000, 0xf0005000, 0xf0005000,
}; };
struct iwn6000_btcoex_config btconfig;
struct iwn_btcoex_priotable btprio; struct iwn_btcoex_priotable btprio;
struct iwn_btcoex_prot btprot; struct iwn_btcoex_prot btprot;
int error, i; int error, i;
memset(&btconfig, 0, sizeof btconfig); if (sc->hw_type == IWN_HW_REV_TYPE_2030) {
btconfig.flags = 145; struct iwn2000_btcoex_config btconfig;
btconfig.max_kill = 5;
btconfig.bt3_t7_timer = 1; memset(&btconfig, 0, sizeof btconfig);
btconfig.kill_ack = htole32(0xffff0000); btconfig.flags = 145;
btconfig.kill_cts = htole32(0xffff0000); btconfig.max_kill = 5;
btconfig.sample_time = 2; btconfig.bt3_t7_timer = 1;
btconfig.bt3_t2_timer = 0xc; btconfig.kill_ack = htole32(0xffff0000);
for (i = 0; i < 12; i++) btconfig.kill_cts = htole32(0xffff0000);
btconfig.lookup_table[i] = htole32(btcoex_3wire[i]); btconfig.sample_time = 2;
btconfig.valid = htole16(0xff); btconfig.bt3_t2_timer = 0xc;
btconfig.prio_boost = 0xf0; for (i = 0; i < 12; i++)
DPRINTF(sc, IWN_DEBUG_RESET, btconfig.lookup_table[i] = htole32(btcoex_3wire[i]);
"%s: configuring advanced bluetooth coexistence\n", __func__); btconfig.valid = htole16(0xff);
error = iwn_cmd(sc, IWN_CMD_BT_COEX, &btconfig, sizeof(btconfig), 1); btconfig.prio_boost = htole32(0xf0);
if (error != 0) DPRINTF(sc, IWN_DEBUG_RESET,
return error; "%s: configuring advanced bluetooth coexistence\n",
__func__);
error = iwn_cmd(sc, IWN_CMD_BT_COEX, &btconfig,
sizeof(btconfig), 1);
if (error != 0)
return (error);
} else {
struct iwn6000_btcoex_config btconfig;
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);
if (error != 0)
return (error);
}
memset(&btprio, 0, sizeof btprio); memset(&btprio, 0, sizeof btprio);
btprio.calib_init1 = 0x6; btprio.calib_init1 = 0x6;
@@ -5074,9 +5115,16 @@ iwn_config(struct iwn_softc *sc)
uint16_t rxchain; uint16_t rxchain;
int error; int error;
/* Set radio temperature sensor offset. */
if (sc->hw_type == IWN_HW_REV_TYPE_6005) { if (sc->hw_type == IWN_HW_REV_TYPE_6005) {
/* Set radio temperature sensor offset. */ error = iwn6000_temp_offset_calib(sc);
error = iwn5000_temp_offset_calib(sc); if (error != 0) {
device_printf(sc->sc_dev,
"%s: could not set temperature offset\n", __func__);
return error;
}
} else if (sc->hw_type == IWN_HW_REV_TYPE_2030) {
error = iwn2000_temp_offset_calib(sc);
if (error != 0) { if (error != 0) {
device_printf(sc->sc_dev, device_printf(sc->sc_dev,
"%s: could not set temperature offset\n", __func__); "%s: could not set temperature offset\n", __func__);
@@ -5943,12 +5991,12 @@ iwn5000_crystal_calib(struct iwn_softc *sc)
} }
static int static int
iwn5000_temp_offset_calib(struct iwn_softc *sc) iwn6000_temp_offset_calib(struct iwn_softc *sc)
{ {
struct iwn5000_phy_calib_temp_offset cmd; struct iwn6000_phy_calib_temp_offset cmd;
memset(&cmd, 0, sizeof cmd); memset(&cmd, 0, sizeof cmd);
cmd.code = IWN5000_PHY_CALIB_TEMP_OFFSET; cmd.code = IWN6000_PHY_CALIB_TEMP_OFFSET;
cmd.ngroups = 1; cmd.ngroups = 1;
cmd.isvalid = 1; cmd.isvalid = 1;
if (sc->eeprom_temp != 0) if (sc->eeprom_temp != 0)
@@ -5960,6 +6008,31 @@ iwn5000_temp_offset_calib(struct iwn_softc *sc)
return iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 0); return iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 0);
} }
static int
iwn2000_temp_offset_calib(struct iwn_softc *sc)
{
struct iwn2000_phy_calib_temp_offset cmd;
memset(&cmd, 0, sizeof cmd);
cmd.code = IWN2000_PHY_CALIB_TEMP_OFFSET;
cmd.ngroups = 1;
cmd.isvalid = 1;
if (sc->eeprom_rawtemp != 0) {
cmd.offset_low = htole16(sc->eeprom_rawtemp);
cmd.offset_high = htole16(sc->eeprom_temp);
} else {
cmd.offset_low = htole16(IWN_DEFAULT_TEMP_OFFSET);
cmd.offset_high = htole16(IWN_DEFAULT_TEMP_OFFSET);
}
cmd.burnt_voltage_ref = htole16(sc->eeprom_voltage);
DPRINTF(sc, IWN_DEBUG_CALIBRATE,
"setting radio sensor offset to %d:%d, voltage to %d\n",
htole16(cmd.offset_low), htole16(cmd.offset_high),
htole16(cmd.burnt_voltage_ref));
return iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 0);
}
/* /*
* This function is called after the runtime firmware notifies us of its * This function is called after the runtime firmware notifies us of its
* readiness (called in a process context). * readiness (called in a process context).
@@ -6663,6 +6736,8 @@ iwn5000_nic_config(struct iwn_softc *sc)
} }
if (sc->hw_type == IWN_HW_REV_TYPE_6005) if (sc->hw_type == IWN_HW_REV_TYPE_6005)
IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_6050_1X2); IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_6050_1X2);
if (sc->hw_type == IWN_HW_REV_TYPE_2030)
IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_RADIO_IQ_INVERT);
return 0; return 0;
} }
@@ -206,6 +206,7 @@
#define IWN_HW_REV_TYPE_6000 7 #define IWN_HW_REV_TYPE_6000 7
#define IWN_HW_REV_TYPE_6050 8 #define IWN_HW_REV_TYPE_6050 8
#define IWN_HW_REV_TYPE_6005 11 #define IWN_HW_REV_TYPE_6005 11
#define IWN_HW_REV_TYPE_2030 12
/* Possible flags for register IWN_GIO_CHICKEN. */ /* Possible flags for register IWN_GIO_CHICKEN. */
#define IWN_GIO_CHICKEN_L1A_NO_L0S_RX (1 << 23) #define IWN_GIO_CHICKEN_L1A_NO_L0S_RX (1 << 23)
@@ -220,6 +221,7 @@
#define IWN_GP_DRIVER_RADIO_2X2_IPA (2 << 0) #define IWN_GP_DRIVER_RADIO_2X2_IPA (2 << 0)
#define IWN_GP_DRIVER_CALIB_VER6 (1 << 2) #define IWN_GP_DRIVER_CALIB_VER6 (1 << 2)
#define IWN_GP_DRIVER_6050_1X2 (1 << 3) #define IWN_GP_DRIVER_6050_1X2 (1 << 3)
#define IWN_GP_DRIVER_RADIO_IQ_INVERT (1 << 7)
/* Possible flags for register IWN_UCODE_GP1_CLR. */ /* Possible flags for register IWN_UCODE_GP1_CLR. */
#define IWN_UCODE_GP1_RFKILL (1 << 1) #define IWN_UCODE_GP1_RFKILL (1 << 1)
@@ -878,6 +880,25 @@ struct iwn6000_btcoex_config {
uint16_t rx_prio_boost; uint16_t rx_prio_boost;
} __packed; } __packed;
struct iwn2000_btcoex_config {
uint8_t flags; /* same as 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;
uint8_t reserved;
uint8_t tx_prio_boost;
uint16_t rx_prio_boost;
} __packed;
struct iwn_btcoex_priotable { struct iwn_btcoex_priotable {
uint8_t calib_init1; uint8_t calib_init1;
uint8_t calib_init2; uint8_t calib_init2;
@@ -965,11 +986,12 @@ struct iwn_phy_calib {
#define IWN5000_PHY_CALIB_CRYSTAL 15 #define IWN5000_PHY_CALIB_CRYSTAL 15
#define IWN5000_PHY_CALIB_BASE_BAND 16 #define IWN5000_PHY_CALIB_BASE_BAND 16
#define IWN5000_PHY_CALIB_TX_IQ_PERIODIC 17 #define IWN5000_PHY_CALIB_TX_IQ_PERIODIC 17
#define IWN5000_PHY_CALIB_TEMP_OFFSET 18
#define IWN5000_PHY_CALIB_RESET_NOISE_GAIN 18 #define IWN5000_PHY_CALIB_RESET_NOISE_GAIN 18
#define IWN5000_PHY_CALIB_NOISE_GAIN 19 #define IWN5000_PHY_CALIB_NOISE_GAIN 19
#define IWN6000_PHY_CALIB_TEMP_OFFSET 18
#define IWN2000_PHY_CALIB_TEMP_OFFSET 18
uint8_t group; uint8_t group;
uint8_t ngroups; uint8_t ngroups;
uint8_t isvalid; uint8_t isvalid;
@@ -985,7 +1007,7 @@ struct iwn5000_phy_calib_crystal {
uint8_t reserved[2]; uint8_t reserved[2];
} __packed; } __packed;
struct iwn5000_phy_calib_temp_offset { struct iwn6000_phy_calib_temp_offset {
uint8_t code; uint8_t code;
uint8_t group; uint8_t group;
uint8_t ngroups; uint8_t ngroups;
@@ -996,6 +1018,17 @@ struct iwn5000_phy_calib_temp_offset {
uint16_t reserved; uint16_t reserved;
} __packed; } __packed;
struct iwn2000_phy_calib_temp_offset {
uint8_t code;
uint8_t group;
uint8_t ngroups;
uint8_t isvalid;
int16_t offset_high;
int16_t offset_low;
int16_t burnt_voltage_ref;
int16_t reserved;
} __packed;
struct iwn_phy_calib_gain { struct iwn_phy_calib_gain {
uint8_t code; uint8_t code;
uint8_t group; uint8_t group;
@@ -1414,6 +1447,7 @@ struct iwn_fw_tlv {
#define IWN5000_EEPROM_CRYSTAL 0x128 #define IWN5000_EEPROM_CRYSTAL 0x128
#define IWN5000_EEPROM_TEMP 0x12a #define IWN5000_EEPROM_TEMP 0x12a
#define IWN5000_EEPROM_VOLT 0x12b #define IWN5000_EEPROM_VOLT 0x12b
#define IWN2000_EEPROM_RAWTEMP 0x12b
/* Possible flags for IWN_EEPROM_SKU_CAP. */ /* Possible flags for IWN_EEPROM_SKU_CAP. */
#define IWN_EEPROM_SKU_CAP_11N (1 << 6) #define IWN_EEPROM_SKU_CAP_11N (1 << 6)
@@ -1722,6 +1756,18 @@ static const struct iwn_sensitivity_limits iwn6000_sensitivity_limits = {
100 100
}; };
static const struct iwn_sensitivity_limits iwn2000_sensitivity_limits = {
105, 110,
192, 232,
80, 145,
128, 232,
125, 175,
160, 310,
97,
97,
100
};
/* Map TID to TX scheduler's FIFO. */ /* Map TID to TX scheduler's FIFO. */
static const uint8_t iwn_tid2fifo[] = { static const uint8_t iwn_tid2fifo[] = {
1, 0, 0, 1, 2, 2, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 3 1, 0, 0, 1, 2, 2, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 3
@@ -295,6 +295,7 @@ struct iwn_softc {
uint32_t eeprom_crystal; uint32_t eeprom_crystal;
int16_t eeprom_temp; int16_t eeprom_temp;
int16_t eeprom_voltage; int16_t eeprom_voltage;
int16_t eeprom_rawtemp;
int8_t maxpwr2GHz; int8_t maxpwr2GHz;
int8_t maxpwr5GHz; int8_t maxpwr5GHz;
int8_t maxpwr[IEEE80211_CHAN_MAX]; int8_t maxpwr[IEEE80211_CHAN_MAX];
@@ -24,8 +24,9 @@ NO_HAIKU_FBSD_MII_DRIVER();
NO_HAIKU_REENABLE_INTERRUPTS(); NO_HAIKU_REENABLE_INTERRUPTS();
HAIKU_DRIVER_REQUIREMENTS(FBSD_TASKQUEUES | FBSD_WLAN); HAIKU_DRIVER_REQUIREMENTS(FBSD_TASKQUEUES | FBSD_WLAN);
HAIKU_FIRMWARE_VERSION(44417); HAIKU_FIRMWARE_VERSION(44417);
HAIKU_FIRMWARE_NAME_MAP(8) = { HAIKU_FIRMWARE_NAME_MAP(9) = {
{"iwn1000fw", "iwlwifi-1000-5.ucode"}, {"iwn1000fw", "iwlwifi-1000-5.ucode"},
{"iwn2030fw", "iwlwifi-2030-6.ucode"},
{"iwn4965fw", "iwlwifi-4965-2.ucode"}, {"iwn4965fw", "iwlwifi-4965-2.ucode"},
{"iwn5000fw", "iwlwifi-5000-5.ucode"}, {"iwn5000fw", "iwlwifi-5000-5.ucode"},
{"iwn5150fw", "iwlwifi-5150-2.ucode"}, {"iwn5150fw", "iwlwifi-5150-2.ucode"},