summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorSylvestre Gallon <syl@cvs.openbsd.org>2013-08-29 19:06:41 +0000
committerSylvestre Gallon <syl@cvs.openbsd.org>2013-08-29 19:06:41 +0000
commit514acfbf4d29506078ac09ba5d85f12a80634c1f (patch)
treeaad1def131955851ccb64127bb9c8347fc89edcf /sys/dev/pci
parent9f8d6b3c56bc4e768652e8f24c3dc7d10c9222d6 (diff)
Add support for advanced btcoex. This commit is not really needed
but it reduces the diff against the FreeBSD version. Tested on: My Wifi Link 130. jca@ Wifi Link 5300. Jan Stary Wifi Link 4965 (thanks). Adapted from FreeBSD r220894. ok mpi@.
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/if_iwn.c77
-rw-r--r--sys/dev/pci/if_iwnreg.h55
2 files changed, 121 insertions, 11 deletions
diff --git a/sys/dev/pci/if_iwn.c b/sys/dev/pci/if_iwn.c
index 729ff223cbc..8b33eb3e2f5 100644
--- a/sys/dev/pci/if_iwn.c
+++ b/sys/dev/pci/if_iwn.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_iwn.c,v 1.122 2013/08/08 23:32:50 syl Exp $ */
+/* $OpenBSD: if_iwn.c,v 1.123 2013/08/29 19:06:39 syl Exp $ */
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
@@ -210,6 +210,7 @@ int iwn_send_sensitivity(struct iwn_softc *);
int iwn_set_pslevel(struct iwn_softc *, int, int, int);
int iwn_send_temperature_offset(struct iwn_softc *);
int iwn_send_btcoex(struct iwn_softc *);
+int iwn_send_advanced_btcoex(struct iwn_softc *);
int iwn5000_runtime_calib(struct iwn_softc *);
int iwn_config(struct iwn_softc *);
int iwn_scan(struct iwn_softc *, uint16_t);
@@ -4144,6 +4145,65 @@ iwn_send_btcoex(struct iwn_softc *sc)
}
int
+iwn_send_advanced_btcoex(struct iwn_softc *sc)
+{
+ static const uint32_t btcoex_3wire[12] = {
+ 0xaaaaaaaa, 0xaaaaaaaa, 0xaeaaaaaa, 0xaaaaaaaa,
+ 0xcc00ff28, 0x0000aaaa, 0xcc00aaaa, 0x0000aaaa,
+ 0xc0004000, 0x00004000, 0xf0005000, 0xf0005000,
+ };
+ struct iwn6000_btcoex_config btconfig;
+ struct iwn_btcoex_priotable btprio;
+ struct iwn_btcoex_prot btprot;
+ int error, i;
+
+ memset(&btconfig, 0, sizeof btconfig);
+ btconfig.flags = IWN_BT_FLAG_COEX6000_CHAN_INHIBITION |
+ (IWN_BT_FLAG_COEX6000_MODE_3W << IWN_BT_FLAG_COEX6000_MODE_SHIFT) |
+ IWN_BT_FLAG_SYNC_2_BT_DISABLE;
+ 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(("configuring advanced bluetooth coexistence\n"));
+ error = iwn_cmd(sc, IWN_CMD_BT_COEX, &btconfig, sizeof(btconfig), 1);
+ if (error != 0)
+ return (error);
+
+ memset(&btprio, 0, sizeof btprio);
+ btprio.calib_init1 = 0x6;
+ btprio.calib_init2 = 0x7;
+ btprio.calib_periodic_low1 = 0x2;
+ btprio.calib_periodic_low2 = 0x3;
+ btprio.calib_periodic_high1 = 0x4;
+ btprio.calib_periodic_high2 = 0x5;
+ btprio.dtim = 0x6;
+ btprio.scan52 = 0x8;
+ btprio.scan24 = 0xa;
+ error = iwn_cmd(sc, IWN_CMD_BT_COEX_PRIOTABLE, &btprio, sizeof(btprio),
+ 1);
+ if (error != 0)
+ return (error);
+
+ /* Force BT state machine change */
+ memset(&btprot, 0, sizeof btprot);
+ btprot.open = 1;
+ btprot.type = 1;
+ error = iwn_cmd(sc, IWN_CMD_BT_COEX_PROT, &btprot, sizeof(btprot), 1);
+ if (error != 0)
+ return (error);
+
+ btprot.open = 0;
+ return (iwn_cmd(sc, IWN_CMD_BT_COEX_PROT, &btprot, sizeof(btprot), 1));
+}
+
+int
iwn5000_runtime_calib(struct iwn_softc *sc)
{
struct iwn5000_calib_config cmd;
@@ -4200,15 +4260,14 @@ iwn_config(struct iwn_softc *sc)
}
/* Configure bluetooth coexistence. */
- if (sc->sc_flags & IWN_FLAG_ADV_BT_COEX) {
- /* XXX Advanced bluetooth coexistence isn't implemented yet. */
- } else {
+ if (sc->sc_flags & IWN_FLAG_ADV_BT_COEX)
+ error = iwn_send_advanced_btcoex(sc);
+ else
error = iwn_send_btcoex(sc);
- if (error != 0) {
- printf("%s: could not configure bluetooth coexistence\n",
- sc->sc_dev.dv_xname);
- return error;
- }
+ if (error != 0) {
+ printf("%s: could not configure bluetooth coexistence\n",
+ sc->sc_dev.dv_xname);
+ return error;
}
/* Set mode, channel, RX filter and enable RX. */
diff --git a/sys/dev/pci/if_iwnreg.h b/sys/dev/pci/if_iwnreg.h
index 3303750d709..12a345bcd1f 100644
--- a/sys/dev/pci/if_iwnreg.h
+++ b/sys/dev/pci/if_iwnreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_iwnreg.h,v 1.43 2011/09/01 18:49:56 kettenis Exp $ */
+/* $OpenBSD: if_iwnreg.h,v 1.44 2013/08/29 19:06:40 syl Exp $ */
/*-
* Copyright (c) 2007, 2008
@@ -433,6 +433,8 @@ struct iwn_tx_cmd {
#define IWN_CMD_SET_CRITICAL_TEMP 164
#define IWN_CMD_SET_SENSITIVITY 168
#define IWN_CMD_PHY_CALIB 176
+#define IWN_CMD_BT_COEX_PRIOTABLE 204
+#define IWN_CMD_BT_COEX_PROT 205
uint8_t flags;
uint8_t idx;
@@ -830,7 +832,7 @@ struct iwn5000_cmd_txpower {
uint8_t reserved;
} __packed;
-/* Structure for command IWN_CMD_BLUETOOTH. */
+/* Structures for command IWN_CMD_BLUETOOTH. */
struct iwn_bluetooth {
uint8_t flags;
#define IWN_BT_COEX_CHAN_ANN (1 << 0)
@@ -848,6 +850,55 @@ struct iwn_bluetooth {
uint32_t kill_cts;
} __packed;
+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)
+#define IWN_BT_FLAG_SYNC_2_BT_DISABLE (1<<7)
+
+ 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;
+ uint8_t prio_boost;
+ uint8_t tx_prio_boost;
+ uint16_t rx_prio_boost;
+} __packed;
+
+/* Structure for command IWN_CMD_BT_COEX_PRIOTABLE */
+struct iwn_btcoex_priotable {
+ uint8_t calib_init1;
+ uint8_t calib_init2;
+ uint8_t calib_periodic_low1;
+ uint8_t calib_periodic_low2;
+ uint8_t calib_periodic_high1;
+ uint8_t calib_periodic_high2;
+ uint8_t dtim;
+ uint8_t scan52;
+ uint8_t scan24;
+ uint8_t reserved[7];
+} __packed;
+
+/* Structure for command IWN_CMD_BT_COEX_PROT */
+struct iwn_btcoex_prot {
+ uint8_t open;
+ uint8_t type;
+ uint8_t reserved[2];
+} __packed;
+
/* Structure for command IWN_CMD_SET_CRITICAL_TEMP. */
struct iwn_critical_temp {
uint32_t reserved;