diff options
author | Sylvestre Gallon <syl@cvs.openbsd.org> | 2013-08-29 19:06:41 +0000 |
---|---|---|
committer | Sylvestre Gallon <syl@cvs.openbsd.org> | 2013-08-29 19:06:41 +0000 |
commit | 514acfbf4d29506078ac09ba5d85f12a80634c1f (patch) | |
tree | aad1def131955851ccb64127bb9c8347fc89edcf /sys/dev/pci | |
parent | 9f8d6b3c56bc4e768652e8f24c3dc7d10c9222d6 (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.c | 77 | ||||
-rw-r--r-- | sys/dev/pci/if_iwnreg.h | 55 |
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; |