124a8d46aSMatthew Dillon /* $OpenBSD: if_iwmvar.h,v 1.7 2015/03/02 13:51:10 jsg Exp $ */ 224a8d46aSMatthew Dillon /* $FreeBSD$ */ 324a8d46aSMatthew Dillon 424a8d46aSMatthew Dillon /* 524a8d46aSMatthew Dillon * Copyright (c) 2014 genua mbh <info@genua.de> 624a8d46aSMatthew Dillon * Copyright (c) 2014 Fixup Software Ltd. 724a8d46aSMatthew Dillon * 824a8d46aSMatthew Dillon * Permission to use, copy, modify, and distribute this software for any 924a8d46aSMatthew Dillon * purpose with or without fee is hereby granted, provided that the above 1024a8d46aSMatthew Dillon * copyright notice and this permission notice appear in all copies. 1124a8d46aSMatthew Dillon * 1224a8d46aSMatthew Dillon * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1324a8d46aSMatthew Dillon * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1424a8d46aSMatthew Dillon * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1524a8d46aSMatthew Dillon * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1624a8d46aSMatthew Dillon * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1724a8d46aSMatthew Dillon * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1824a8d46aSMatthew Dillon * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1924a8d46aSMatthew Dillon */ 2024a8d46aSMatthew Dillon 2124a8d46aSMatthew Dillon /*- 2224a8d46aSMatthew Dillon * Based on BSD-licensed source modules in the Linux iwlwifi driver, 2324a8d46aSMatthew Dillon * which were used as the reference documentation for this implementation. 2424a8d46aSMatthew Dillon * 2524a8d46aSMatthew Dillon * Driver version we are currently based off of is 2624a8d46aSMatthew Dillon * Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd) 2724a8d46aSMatthew Dillon * 2824a8d46aSMatthew Dillon *********************************************************************** 2924a8d46aSMatthew Dillon * 3024a8d46aSMatthew Dillon * This file is provided under a dual BSD/GPLv2 license. When using or 3124a8d46aSMatthew Dillon * redistributing this file, you may do so under either license. 3224a8d46aSMatthew Dillon * 3324a8d46aSMatthew Dillon * GPL LICENSE SUMMARY 3424a8d46aSMatthew Dillon * 3524a8d46aSMatthew Dillon * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved. 3624a8d46aSMatthew Dillon * 3724a8d46aSMatthew Dillon * This program is free software; you can redistribute it and/or modify 3824a8d46aSMatthew Dillon * it under the terms of version 2 of the GNU General Public License as 3924a8d46aSMatthew Dillon * published by the Free Software Foundation. 4024a8d46aSMatthew Dillon * 4124a8d46aSMatthew Dillon * This program is distributed in the hope that it will be useful, but 4224a8d46aSMatthew Dillon * WITHOUT ANY WARRANTY; without even the implied warranty of 4324a8d46aSMatthew Dillon * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 4424a8d46aSMatthew Dillon * General Public License for more details. 4524a8d46aSMatthew Dillon * 4624a8d46aSMatthew Dillon * You should have received a copy of the GNU General Public License 4724a8d46aSMatthew Dillon * along with this program; if not, write to the Free Software 4824a8d46aSMatthew Dillon * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, 4924a8d46aSMatthew Dillon * USA 5024a8d46aSMatthew Dillon * 5124a8d46aSMatthew Dillon * The full GNU General Public License is included in this distribution 5224a8d46aSMatthew Dillon * in the file called COPYING. 5324a8d46aSMatthew Dillon * 5424a8d46aSMatthew Dillon * Contact Information: 5524a8d46aSMatthew Dillon * Intel Linux Wireless <ilw@linux.intel.com> 5624a8d46aSMatthew Dillon * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 5724a8d46aSMatthew Dillon * 5824a8d46aSMatthew Dillon * 5924a8d46aSMatthew Dillon * BSD LICENSE 6024a8d46aSMatthew Dillon * 6124a8d46aSMatthew Dillon * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. 6224a8d46aSMatthew Dillon * All rights reserved. 6324a8d46aSMatthew Dillon * 6424a8d46aSMatthew Dillon * Redistribution and use in source and binary forms, with or without 6524a8d46aSMatthew Dillon * modification, are permitted provided that the following conditions 6624a8d46aSMatthew Dillon * are met: 6724a8d46aSMatthew Dillon * 6824a8d46aSMatthew Dillon * * Redistributions of source code must retain the above copyright 6924a8d46aSMatthew Dillon * notice, this list of conditions and the following disclaimer. 7024a8d46aSMatthew Dillon * * Redistributions in binary form must reproduce the above copyright 7124a8d46aSMatthew Dillon * notice, this list of conditions and the following disclaimer in 7224a8d46aSMatthew Dillon * the documentation and/or other materials provided with the 7324a8d46aSMatthew Dillon * distribution. 7424a8d46aSMatthew Dillon * * Neither the name Intel Corporation nor the names of its 7524a8d46aSMatthew Dillon * contributors may be used to endorse or promote products derived 7624a8d46aSMatthew Dillon * from this software without specific prior written permission. 7724a8d46aSMatthew Dillon * 7824a8d46aSMatthew Dillon * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 7924a8d46aSMatthew Dillon * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 8024a8d46aSMatthew Dillon * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 8124a8d46aSMatthew Dillon * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 8224a8d46aSMatthew Dillon * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 8324a8d46aSMatthew Dillon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 8424a8d46aSMatthew Dillon * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 8524a8d46aSMatthew Dillon * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 8624a8d46aSMatthew Dillon * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 8724a8d46aSMatthew Dillon * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 8824a8d46aSMatthew Dillon * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 8924a8d46aSMatthew Dillon */ 9024a8d46aSMatthew Dillon 9124a8d46aSMatthew Dillon /*- 9224a8d46aSMatthew Dillon * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr> 9324a8d46aSMatthew Dillon * 9424a8d46aSMatthew Dillon * Permission to use, copy, modify, and distribute this software for any 9524a8d46aSMatthew Dillon * purpose with or without fee is hereby granted, provided that the above 9624a8d46aSMatthew Dillon * copyright notice and this permission notice appear in all copies. 9724a8d46aSMatthew Dillon * 9824a8d46aSMatthew Dillon * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9924a8d46aSMatthew Dillon * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10024a8d46aSMatthew Dillon * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10124a8d46aSMatthew Dillon * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 10224a8d46aSMatthew Dillon * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 10324a8d46aSMatthew Dillon * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 10424a8d46aSMatthew Dillon * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 10524a8d46aSMatthew Dillon */ 10624a8d46aSMatthew Dillon 10724a8d46aSMatthew Dillon struct iwm_rx_radiotap_header { 10824a8d46aSMatthew Dillon struct ieee80211_radiotap_header wr_ihdr; 10924a8d46aSMatthew Dillon uint64_t wr_tsft; 11024a8d46aSMatthew Dillon uint8_t wr_flags; 11124a8d46aSMatthew Dillon uint8_t wr_rate; 11224a8d46aSMatthew Dillon uint16_t wr_chan_freq; 11324a8d46aSMatthew Dillon uint16_t wr_chan_flags; 11424a8d46aSMatthew Dillon int8_t wr_dbm_antsignal; 11524a8d46aSMatthew Dillon int8_t wr_dbm_antnoise; 11624a8d46aSMatthew Dillon } __packed; 11724a8d46aSMatthew Dillon 11824a8d46aSMatthew Dillon #define IWM_RX_RADIOTAP_PRESENT \ 11924a8d46aSMatthew Dillon ((1 << IEEE80211_RADIOTAP_TSFT) | \ 12024a8d46aSMatthew Dillon (1 << IEEE80211_RADIOTAP_FLAGS) | \ 12124a8d46aSMatthew Dillon (1 << IEEE80211_RADIOTAP_RATE) | \ 12224a8d46aSMatthew Dillon (1 << IEEE80211_RADIOTAP_CHANNEL) | \ 12324a8d46aSMatthew Dillon (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \ 12424a8d46aSMatthew Dillon (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE)) 12524a8d46aSMatthew Dillon 12624a8d46aSMatthew Dillon struct iwm_tx_radiotap_header { 12724a8d46aSMatthew Dillon struct ieee80211_radiotap_header wt_ihdr; 12824a8d46aSMatthew Dillon uint8_t wt_flags; 12924a8d46aSMatthew Dillon uint8_t wt_rate; 13024a8d46aSMatthew Dillon uint16_t wt_chan_freq; 13124a8d46aSMatthew Dillon uint16_t wt_chan_flags; 13224a8d46aSMatthew Dillon uint8_t wt_hwqueue; 13324a8d46aSMatthew Dillon } __packed; 13424a8d46aSMatthew Dillon 13524a8d46aSMatthew Dillon #define IWM_TX_RADIOTAP_PRESENT \ 13624a8d46aSMatthew Dillon ((1 << IEEE80211_RADIOTAP_FLAGS) | \ 13724a8d46aSMatthew Dillon (1 << IEEE80211_RADIOTAP_RATE) | \ 13824a8d46aSMatthew Dillon (1 << IEEE80211_RADIOTAP_CHANNEL)) 13924a8d46aSMatthew Dillon 14024a8d46aSMatthew Dillon 14124a8d46aSMatthew Dillon #define IWM_UCODE_SECT_MAX 6 14224a8d46aSMatthew Dillon #define IWM_FWDMASEGSZ (192*1024) 14324a8d46aSMatthew Dillon /* sanity check value */ 14424a8d46aSMatthew Dillon #define IWM_FWMAXSIZE (2*1024*1024) 14524a8d46aSMatthew Dillon 14624a8d46aSMatthew Dillon /* 14724a8d46aSMatthew Dillon * fw_status is used to determine if we've already parsed the firmware file 14824a8d46aSMatthew Dillon * 14924a8d46aSMatthew Dillon * In addition to the following, status < 0 ==> -error 15024a8d46aSMatthew Dillon */ 15124a8d46aSMatthew Dillon #define IWM_FW_STATUS_NONE 0 15224a8d46aSMatthew Dillon #define IWM_FW_STATUS_INPROGRESS 1 15324a8d46aSMatthew Dillon #define IWM_FW_STATUS_DONE 2 15424a8d46aSMatthew Dillon 155*45bc40b1SMatthew Dillon #define IWM_LOCK(_sc) lockmgr(&sc->sc_lk, LK_EXCLUSIVE) 156*45bc40b1SMatthew Dillon #define IWM_UNLOCK(_sc) lockmgr(&sc->sc_lk, LK_RELEASE) 15724a8d46aSMatthew Dillon 15824a8d46aSMatthew Dillon enum iwm_ucode_type { 15924a8d46aSMatthew Dillon IWM_UCODE_TYPE_INIT, 16024a8d46aSMatthew Dillon IWM_UCODE_TYPE_REGULAR, 16124a8d46aSMatthew Dillon IWM_UCODE_TYPE_WOW, 16224a8d46aSMatthew Dillon IWM_UCODE_TYPE_MAX 16324a8d46aSMatthew Dillon }; 16424a8d46aSMatthew Dillon 16524a8d46aSMatthew Dillon struct iwm_fw_info { 16624a8d46aSMatthew Dillon const void *fw_rawdata; 16724a8d46aSMatthew Dillon size_t fw_rawsize; 16824a8d46aSMatthew Dillon int fw_status; 16924a8d46aSMatthew Dillon 17024a8d46aSMatthew Dillon struct iwm_fw_sects { 17124a8d46aSMatthew Dillon struct iwm_fw_onesect { 17224a8d46aSMatthew Dillon const void *fws_data; 17324a8d46aSMatthew Dillon uint32_t fws_len; 17424a8d46aSMatthew Dillon uint32_t fws_devoff; 17524a8d46aSMatthew Dillon } fw_sect[IWM_UCODE_SECT_MAX]; 17624a8d46aSMatthew Dillon size_t fw_totlen; 17724a8d46aSMatthew Dillon int fw_count; 17824a8d46aSMatthew Dillon } fw_sects[IWM_UCODE_TYPE_MAX]; 17924a8d46aSMatthew Dillon }; 18024a8d46aSMatthew Dillon 18124a8d46aSMatthew Dillon struct iwm_nvm_data { 18224a8d46aSMatthew Dillon int n_hw_addrs; 18324a8d46aSMatthew Dillon uint8_t hw_addr[IEEE80211_ADDR_LEN]; 18424a8d46aSMatthew Dillon 18524a8d46aSMatthew Dillon uint8_t calib_version; 18624a8d46aSMatthew Dillon uint16_t calib_voltage; 18724a8d46aSMatthew Dillon 18824a8d46aSMatthew Dillon uint16_t raw_temperature; 18924a8d46aSMatthew Dillon uint16_t kelvin_temperature; 19024a8d46aSMatthew Dillon uint16_t kelvin_voltage; 19124a8d46aSMatthew Dillon uint16_t xtal_calib[2]; 19224a8d46aSMatthew Dillon 19324a8d46aSMatthew Dillon int sku_cap_band_24GHz_enable; 19424a8d46aSMatthew Dillon int sku_cap_band_52GHz_enable; 19524a8d46aSMatthew Dillon int sku_cap_11n_enable; 19624a8d46aSMatthew Dillon int sku_cap_amt_enable; 19724a8d46aSMatthew Dillon int sku_cap_ipan_enable; 19824a8d46aSMatthew Dillon 19924a8d46aSMatthew Dillon uint8_t radio_cfg_type; 20024a8d46aSMatthew Dillon uint8_t radio_cfg_step; 20124a8d46aSMatthew Dillon uint8_t radio_cfg_dash; 20224a8d46aSMatthew Dillon uint8_t radio_cfg_pnum; 20324a8d46aSMatthew Dillon uint8_t valid_tx_ant, valid_rx_ant; 20424a8d46aSMatthew Dillon 20524a8d46aSMatthew Dillon uint16_t nvm_version; 20624a8d46aSMatthew Dillon uint8_t max_tx_pwr_half_dbm; 20724a8d46aSMatthew Dillon }; 20824a8d46aSMatthew Dillon 20924a8d46aSMatthew Dillon /* max bufs per tfd the driver will use */ 21024a8d46aSMatthew Dillon #define IWM_MAX_CMD_TBS_PER_TFD 2 21124a8d46aSMatthew Dillon 21224a8d46aSMatthew Dillon struct iwm_rx_packet; 21324a8d46aSMatthew Dillon struct iwm_host_cmd { 21424a8d46aSMatthew Dillon const void *data[IWM_MAX_CMD_TBS_PER_TFD]; 21524a8d46aSMatthew Dillon struct iwm_rx_packet *resp_pkt; 21624a8d46aSMatthew Dillon unsigned long _rx_page_addr; 21724a8d46aSMatthew Dillon uint32_t _rx_page_order; 21824a8d46aSMatthew Dillon int handler_status; 21924a8d46aSMatthew Dillon 22024a8d46aSMatthew Dillon uint32_t flags; 22124a8d46aSMatthew Dillon uint16_t len[IWM_MAX_CMD_TBS_PER_TFD]; 22224a8d46aSMatthew Dillon uint8_t dataflags[IWM_MAX_CMD_TBS_PER_TFD]; 22324a8d46aSMatthew Dillon uint8_t id; 22424a8d46aSMatthew Dillon }; 22524a8d46aSMatthew Dillon 22624a8d46aSMatthew Dillon /* 22724a8d46aSMatthew Dillon * DMA glue is from iwn 22824a8d46aSMatthew Dillon */ 22924a8d46aSMatthew Dillon 23024a8d46aSMatthew Dillon typedef caddr_t iwm_caddr_t; 23124a8d46aSMatthew Dillon typedef void *iwm_hookarg_t; 23224a8d46aSMatthew Dillon 23324a8d46aSMatthew Dillon struct iwm_dma_info { 23424a8d46aSMatthew Dillon bus_dma_tag_t tag; 23524a8d46aSMatthew Dillon bus_dmamap_t map; 23624a8d46aSMatthew Dillon bus_dma_segment_t seg; 23724a8d46aSMatthew Dillon bus_addr_t paddr; 23824a8d46aSMatthew Dillon void *vaddr; 23924a8d46aSMatthew Dillon bus_size_t size; 24024a8d46aSMatthew Dillon }; 24124a8d46aSMatthew Dillon 24224a8d46aSMatthew Dillon #define IWM_TX_RING_COUNT 256 24324a8d46aSMatthew Dillon #define IWM_TX_RING_LOMARK 192 24424a8d46aSMatthew Dillon #define IWM_TX_RING_HIMARK 224 24524a8d46aSMatthew Dillon 24624a8d46aSMatthew Dillon struct iwm_tx_data { 24724a8d46aSMatthew Dillon bus_dmamap_t map; 24824a8d46aSMatthew Dillon bus_addr_t cmd_paddr; 24924a8d46aSMatthew Dillon bus_addr_t scratch_paddr; 25024a8d46aSMatthew Dillon struct mbuf *m; 25124a8d46aSMatthew Dillon struct iwm_node *in; 25224a8d46aSMatthew Dillon int done; 25324a8d46aSMatthew Dillon }; 25424a8d46aSMatthew Dillon 25524a8d46aSMatthew Dillon struct iwm_tx_ring { 25624a8d46aSMatthew Dillon struct iwm_dma_info desc_dma; 25724a8d46aSMatthew Dillon struct iwm_dma_info cmd_dma; 25824a8d46aSMatthew Dillon struct iwm_tfd *desc; 25924a8d46aSMatthew Dillon struct iwm_device_cmd *cmd; 26024a8d46aSMatthew Dillon bus_dma_tag_t data_dmat; 26124a8d46aSMatthew Dillon struct iwm_tx_data data[IWM_TX_RING_COUNT]; 26224a8d46aSMatthew Dillon int qid; 26324a8d46aSMatthew Dillon int queued; 26424a8d46aSMatthew Dillon int cur; 26524a8d46aSMatthew Dillon }; 26624a8d46aSMatthew Dillon 26724a8d46aSMatthew Dillon #define IWM_RX_RING_COUNT 256 26824a8d46aSMatthew Dillon #define IWM_RBUF_COUNT (IWM_RX_RING_COUNT + 32) 26924a8d46aSMatthew Dillon /* Linux driver optionally uses 8k buffer */ 27024a8d46aSMatthew Dillon #define IWM_RBUF_SIZE 4096 27124a8d46aSMatthew Dillon 27224a8d46aSMatthew Dillon #define IWM_MAX_SCATTER 20 27324a8d46aSMatthew Dillon 27424a8d46aSMatthew Dillon struct iwm_softc; 27524a8d46aSMatthew Dillon struct iwm_rbuf { 27624a8d46aSMatthew Dillon struct iwm_softc *sc; 27724a8d46aSMatthew Dillon void *vaddr; 27824a8d46aSMatthew Dillon bus_addr_t paddr; 27924a8d46aSMatthew Dillon }; 28024a8d46aSMatthew Dillon 28124a8d46aSMatthew Dillon struct iwm_rx_data { 28224a8d46aSMatthew Dillon struct mbuf *m; 28324a8d46aSMatthew Dillon bus_dmamap_t map; 28424a8d46aSMatthew Dillon int wantresp; 28524a8d46aSMatthew Dillon }; 28624a8d46aSMatthew Dillon 28724a8d46aSMatthew Dillon struct iwm_rx_ring { 28824a8d46aSMatthew Dillon struct iwm_dma_info desc_dma; 28924a8d46aSMatthew Dillon struct iwm_dma_info stat_dma; 29024a8d46aSMatthew Dillon struct iwm_dma_info buf_dma; 29124a8d46aSMatthew Dillon uint32_t *desc; 29224a8d46aSMatthew Dillon struct iwm_rb_status *stat; 29324a8d46aSMatthew Dillon struct iwm_rx_data data[IWM_RX_RING_COUNT]; 29424a8d46aSMatthew Dillon bus_dma_tag_t data_dmat; 29524a8d46aSMatthew Dillon int cur; 29624a8d46aSMatthew Dillon }; 29724a8d46aSMatthew Dillon 29824a8d46aSMatthew Dillon #define IWM_FLAG_USE_ICT 0x01 29924a8d46aSMatthew Dillon #define IWM_FLAG_HW_INITED 0x02 30024a8d46aSMatthew Dillon #define IWM_FLAG_STOPPED 0x04 30124a8d46aSMatthew Dillon #define IWM_FLAG_RFKILL 0x08 30224a8d46aSMatthew Dillon #define IWM_FLAG_BUSY 0x10 30324a8d46aSMatthew Dillon 30424a8d46aSMatthew Dillon struct iwm_ucode_status { 30524a8d46aSMatthew Dillon uint32_t uc_error_event_table; 30624a8d46aSMatthew Dillon uint32_t uc_log_event_table; 30724a8d46aSMatthew Dillon 30824a8d46aSMatthew Dillon int uc_ok; 30924a8d46aSMatthew Dillon int uc_intr; 31024a8d46aSMatthew Dillon }; 31124a8d46aSMatthew Dillon 31224a8d46aSMatthew Dillon #define IWM_CMD_RESP_MAX PAGE_SIZE 31324a8d46aSMatthew Dillon 31424a8d46aSMatthew Dillon #define IWM_OTP_LOW_IMAGE_SIZE 2048 31524a8d46aSMatthew Dillon 31624a8d46aSMatthew Dillon #define IWM_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS 500 31724a8d46aSMatthew Dillon #define IWM_MVM_TE_SESSION_PROTECTION_MIN_TIME_MS 400 31824a8d46aSMatthew Dillon 31924a8d46aSMatthew Dillon /* 32024a8d46aSMatthew Dillon * Command headers are in iwl-trans.h, which is full of all 32124a8d46aSMatthew Dillon * kinds of other junk, so we just replicate the structures here. 32224a8d46aSMatthew Dillon * First the software bits: 32324a8d46aSMatthew Dillon */ 32424a8d46aSMatthew Dillon enum IWM_CMD_MODE { 32524a8d46aSMatthew Dillon IWM_CMD_SYNC = 0, 32624a8d46aSMatthew Dillon IWM_CMD_ASYNC = (1 << 0), 32724a8d46aSMatthew Dillon IWM_CMD_WANT_SKB = (1 << 1), 32824a8d46aSMatthew Dillon IWM_CMD_SEND_IN_RFKILL = (1 << 2), 32924a8d46aSMatthew Dillon }; 33024a8d46aSMatthew Dillon enum iwm_hcmd_dataflag { 33124a8d46aSMatthew Dillon IWM_HCMD_DFL_NOCOPY = (1 << 0), 33224a8d46aSMatthew Dillon IWM_HCMD_DFL_DUP = (1 << 1), 33324a8d46aSMatthew Dillon }; 33424a8d46aSMatthew Dillon 33524a8d46aSMatthew Dillon /* 33624a8d46aSMatthew Dillon * iwlwifi/iwl-phy-db 33724a8d46aSMatthew Dillon */ 33824a8d46aSMatthew Dillon 33924a8d46aSMatthew Dillon #define IWM_NUM_PAPD_CH_GROUPS 4 34024a8d46aSMatthew Dillon #define IWM_NUM_TXP_CH_GROUPS 9 34124a8d46aSMatthew Dillon 34224a8d46aSMatthew Dillon struct iwm_phy_db_entry { 34324a8d46aSMatthew Dillon uint16_t size; 34424a8d46aSMatthew Dillon uint8_t *data; 34524a8d46aSMatthew Dillon }; 34624a8d46aSMatthew Dillon 34724a8d46aSMatthew Dillon struct iwm_phy_db { 34824a8d46aSMatthew Dillon struct iwm_phy_db_entry cfg; 34924a8d46aSMatthew Dillon struct iwm_phy_db_entry calib_nch; 35024a8d46aSMatthew Dillon struct iwm_phy_db_entry calib_ch_group_papd[IWM_NUM_PAPD_CH_GROUPS]; 35124a8d46aSMatthew Dillon struct iwm_phy_db_entry calib_ch_group_txp[IWM_NUM_TXP_CH_GROUPS]; 35224a8d46aSMatthew Dillon }; 35324a8d46aSMatthew Dillon 35424a8d46aSMatthew Dillon struct iwm_int_sta { 35524a8d46aSMatthew Dillon uint32_t sta_id; 35624a8d46aSMatthew Dillon uint32_t tfd_queue_msk; 35724a8d46aSMatthew Dillon }; 35824a8d46aSMatthew Dillon 35924a8d46aSMatthew Dillon struct iwm_mvm_phy_ctxt { 36024a8d46aSMatthew Dillon uint16_t id; 36124a8d46aSMatthew Dillon uint16_t color; 36224a8d46aSMatthew Dillon uint32_t ref; 36324a8d46aSMatthew Dillon struct ieee80211_channel *channel; 36424a8d46aSMatthew Dillon }; 36524a8d46aSMatthew Dillon 36624a8d46aSMatthew Dillon struct iwm_bf_data { 36724a8d46aSMatthew Dillon int bf_enabled; /* filtering */ 36824a8d46aSMatthew Dillon int ba_enabled; /* abort */ 36924a8d46aSMatthew Dillon int ave_beacon_signal; 37024a8d46aSMatthew Dillon int last_cqm_event; 37124a8d46aSMatthew Dillon }; 37224a8d46aSMatthew Dillon 37324a8d46aSMatthew Dillon struct iwm_vap { 37424a8d46aSMatthew Dillon struct ieee80211vap iv_vap; 37524a8d46aSMatthew Dillon uint8_t macaddr[IEEE80211_ADDR_LEN]; 37624a8d46aSMatthew Dillon int is_uploaded; 37724a8d46aSMatthew Dillon 37824a8d46aSMatthew Dillon int (*iv_newstate)(struct ieee80211vap *, enum ieee80211_state, int); 37924a8d46aSMatthew Dillon }; 38024a8d46aSMatthew Dillon 38124a8d46aSMatthew Dillon #define IWM_VAP(_vap) ((struct iwm_vap *)(_vap)) 38224a8d46aSMatthew Dillon 38324a8d46aSMatthew Dillon struct iwm_softc { 384*45bc40b1SMatthew Dillon struct lock sc_lk; 385*45bc40b1SMatthew Dillon struct ifnet *sc_ifp; 38624a8d46aSMatthew Dillon device_t sc_dev; 387*45bc40b1SMatthew Dillon struct ieee80211com *sc_ic; 388*45bc40b1SMatthew Dillon 389*45bc40b1SMatthew Dillon int sc_newstate_pending; 390*45bc40b1SMatthew Dillon 391*45bc40b1SMatthew Dillon uint8_t sc_bssid[IEEE80211_ADDR_LEN]; 39224a8d46aSMatthew Dillon 39324a8d46aSMatthew Dillon struct intr_config_hook sc_preinit_hook; 39424a8d46aSMatthew Dillon struct callout sc_watchdog_to; 39524a8d46aSMatthew Dillon 39624a8d46aSMatthew Dillon struct task init_task; 397*45bc40b1SMatthew Dillon uint8_t sc_macaddr[IEEE80211_ADDR_LEN]; 39824a8d46aSMatthew Dillon 39924a8d46aSMatthew Dillon struct resource *sc_irq; 40024a8d46aSMatthew Dillon struct resource *sc_mem; 40124a8d46aSMatthew Dillon bus_space_tag_t sc_st; 40224a8d46aSMatthew Dillon bus_space_handle_t sc_sh; 40324a8d46aSMatthew Dillon bus_size_t sc_sz; 40424a8d46aSMatthew Dillon bus_dma_tag_t sc_dmat; 40524a8d46aSMatthew Dillon void *sc_ih; 40624a8d46aSMatthew Dillon 40724a8d46aSMatthew Dillon /* TX scheduler rings. */ 40824a8d46aSMatthew Dillon struct iwm_dma_info sched_dma; 40924a8d46aSMatthew Dillon uint32_t sched_base; 41024a8d46aSMatthew Dillon 41124a8d46aSMatthew Dillon /* TX/RX rings. */ 41224a8d46aSMatthew Dillon struct iwm_tx_ring txq[IWM_MVM_MAX_QUEUES]; 41324a8d46aSMatthew Dillon struct iwm_rx_ring rxq; 41424a8d46aSMatthew Dillon int qfullmsk; 41524a8d46aSMatthew Dillon 41624a8d46aSMatthew Dillon int sc_sf_state; 41724a8d46aSMatthew Dillon 41824a8d46aSMatthew Dillon /* ICT table. */ 41924a8d46aSMatthew Dillon struct iwm_dma_info ict_dma; 42024a8d46aSMatthew Dillon int ict_cur; 42124a8d46aSMatthew Dillon 42224a8d46aSMatthew Dillon int sc_hw_rev; 42324a8d46aSMatthew Dillon int sc_hw_id; 42424a8d46aSMatthew Dillon 42524a8d46aSMatthew Dillon struct iwm_dma_info kw_dma; 42624a8d46aSMatthew Dillon struct iwm_dma_info fw_dma; 42724a8d46aSMatthew Dillon 42824a8d46aSMatthew Dillon int sc_fw_chunk_done; 42924a8d46aSMatthew Dillon int sc_init_complete; 43024a8d46aSMatthew Dillon 43124a8d46aSMatthew Dillon struct iwm_ucode_status sc_uc; 43224a8d46aSMatthew Dillon enum iwm_ucode_type sc_uc_current; 43324a8d46aSMatthew Dillon int sc_fwver; 43424a8d46aSMatthew Dillon 43524a8d46aSMatthew Dillon int sc_capaflags; 43624a8d46aSMatthew Dillon int sc_capa_max_probe_len; 43724a8d46aSMatthew Dillon 43824a8d46aSMatthew Dillon int sc_intmask; 43924a8d46aSMatthew Dillon int sc_flags; 44024a8d46aSMatthew Dillon uint32_t sc_debug; 44124a8d46aSMatthew Dillon 44224a8d46aSMatthew Dillon /* 44324a8d46aSMatthew Dillon * So why do we need a separate stopped flag and a generation? 44424a8d46aSMatthew Dillon * the former protects the device from issueing commands when it's 44524a8d46aSMatthew Dillon * stopped (duh). The latter protects against race from a very 44624a8d46aSMatthew Dillon * fast stop/unstop cycle where threads waiting for responses do 44724a8d46aSMatthew Dillon * not have a chance to run in between. Notably: we want to stop 44824a8d46aSMatthew Dillon * the device from interrupt context when it craps out, so we 44924a8d46aSMatthew Dillon * don't have the luxury of waiting for quiescense. 45024a8d46aSMatthew Dillon */ 45124a8d46aSMatthew Dillon int sc_generation; 45224a8d46aSMatthew Dillon 45324a8d46aSMatthew Dillon const char *sc_fwname; 45424a8d46aSMatthew Dillon bus_size_t sc_fwdmasegsz; 45524a8d46aSMatthew Dillon struct iwm_fw_info sc_fw; 45624a8d46aSMatthew Dillon int sc_fw_phy_config; 45724a8d46aSMatthew Dillon struct iwm_tlv_calib_ctrl sc_default_calib[IWM_UCODE_TYPE_MAX]; 45824a8d46aSMatthew Dillon 45924a8d46aSMatthew Dillon struct iwm_nvm_data sc_nvm; 46024a8d46aSMatthew Dillon struct iwm_phy_db sc_phy_db; 46124a8d46aSMatthew Dillon 46224a8d46aSMatthew Dillon struct iwm_bf_data sc_bf; 46324a8d46aSMatthew Dillon 46424a8d46aSMatthew Dillon int sc_tx_timer; 46524a8d46aSMatthew Dillon 46624a8d46aSMatthew Dillon struct iwm_scan_cmd *sc_scan_cmd; 46724a8d46aSMatthew Dillon size_t sc_scan_cmd_len; 46824a8d46aSMatthew Dillon int sc_scan_last_antenna; 46924a8d46aSMatthew Dillon int sc_scanband; 47024a8d46aSMatthew Dillon 47124a8d46aSMatthew Dillon int sc_auth_prot; 47224a8d46aSMatthew Dillon 47324a8d46aSMatthew Dillon int sc_fixed_ridx; 47424a8d46aSMatthew Dillon 47524a8d46aSMatthew Dillon int sc_staid; 47624a8d46aSMatthew Dillon int sc_nodecolor; 47724a8d46aSMatthew Dillon 47824a8d46aSMatthew Dillon uint8_t sc_cmd_resp[IWM_CMD_RESP_MAX]; 47924a8d46aSMatthew Dillon int sc_wantresp; 48024a8d46aSMatthew Dillon 48124a8d46aSMatthew Dillon struct taskqueue *sc_tq; 48224a8d46aSMatthew Dillon struct task sc_es_task; 48324a8d46aSMatthew Dillon 48424a8d46aSMatthew Dillon struct iwm_rx_phy_info sc_last_phy_info; 48524a8d46aSMatthew Dillon int sc_ampdu_ref; 48624a8d46aSMatthew Dillon 48724a8d46aSMatthew Dillon struct iwm_int_sta sc_aux_sta; 48824a8d46aSMatthew Dillon 48924a8d46aSMatthew Dillon /* phy contexts. we only use the first one */ 49024a8d46aSMatthew Dillon struct iwm_mvm_phy_ctxt sc_phyctxt[IWM_NUM_PHY_CTX]; 49124a8d46aSMatthew Dillon 49224a8d46aSMatthew Dillon struct iwm_notif_statistics sc_stats; 49324a8d46aSMatthew Dillon int sc_noise; 49424a8d46aSMatthew Dillon 49524a8d46aSMatthew Dillon int host_interrupt_operation_mode; 49624a8d46aSMatthew Dillon 49724a8d46aSMatthew Dillon caddr_t sc_drvbpf; 49824a8d46aSMatthew Dillon 49924a8d46aSMatthew Dillon union { 50024a8d46aSMatthew Dillon struct iwm_rx_radiotap_header th; 50124a8d46aSMatthew Dillon uint8_t pad[IEEE80211_RADIOTAP_HDRLEN]; 50224a8d46aSMatthew Dillon } sc_rxtapu; 50324a8d46aSMatthew Dillon #define sc_rxtap sc_rxtapu.th 50424a8d46aSMatthew Dillon int sc_rxtap_len; 50524a8d46aSMatthew Dillon 50624a8d46aSMatthew Dillon union { 50724a8d46aSMatthew Dillon struct iwm_tx_radiotap_header th; 50824a8d46aSMatthew Dillon uint8_t pad[IEEE80211_RADIOTAP_HDRLEN]; 50924a8d46aSMatthew Dillon } sc_txtapu; 51024a8d46aSMatthew Dillon #define sc_txtap sc_txtapu.th 51124a8d46aSMatthew Dillon int sc_txtap_len; 51224a8d46aSMatthew Dillon 51324a8d46aSMatthew Dillon int sc_max_rssi; 51424a8d46aSMatthew Dillon }; 51524a8d46aSMatthew Dillon 51624a8d46aSMatthew Dillon #define IWM_DEFAULT_MACID 0 51724a8d46aSMatthew Dillon #define IWM_DEFAULT_COLOR 0 51824a8d46aSMatthew Dillon #define IWM_DEFAULT_TSFID 0 51924a8d46aSMatthew Dillon 52024a8d46aSMatthew Dillon struct iwm_node { 52124a8d46aSMatthew Dillon struct ieee80211_node in_ni; 52224a8d46aSMatthew Dillon struct iwm_mvm_phy_ctxt *in_phyctxt; 52324a8d46aSMatthew Dillon 52424a8d46aSMatthew Dillon /* status "bits" */ 52524a8d46aSMatthew Dillon int in_assoc; 52624a8d46aSMatthew Dillon 52724a8d46aSMatthew Dillon struct iwm_lq_cmd in_lq; 52824a8d46aSMatthew Dillon 52924a8d46aSMatthew Dillon uint8_t in_ridx[IEEE80211_RATE_MAXSIZE]; 53024a8d46aSMatthew Dillon }; 53124a8d46aSMatthew Dillon #define IWM_STATION_ID 0 53224a8d46aSMatthew Dillon 53324a8d46aSMatthew Dillon #define IWM_ICT_SIZE 4096 53424a8d46aSMatthew Dillon #define IWM_ICT_COUNT (IWM_ICT_SIZE / sizeof (uint32_t)) 53524a8d46aSMatthew Dillon #define IWM_ICT_PADDR_SHIFT 12 536