Import OpenBSD's iwm WiFi driver for Intel 3160/7260/7265.

There are still several bugs, but I've been using it for a while now.
Thanks to all the testers and to Adrian for his help with this
driver.

This driver isn't connected to the build yet, but it will be soon.

There's no MFC planned because the driver isn't very stable yet.

Reviewed by:	adrian
Obtained from:	https://github.com/rpaulo/iwm
Tested by:	adrian, gjb, dumbbell (others that I forgot).
Relnotes:	yes
This commit is contained in:
Rui Paulo 2015-08-08 06:06:48 +00:00
parent aaa8b90caf
commit d4886179cb
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=286441
34 changed files with 61527 additions and 0 deletions

153
share/man/man4/iwm.4 Normal file
View File

@ -0,0 +1,153 @@
.\" Copyright (c) 2004-2006
.\" Damien Bergamini <damien.bergamini@free.fr>. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice unmodified, this list of conditions, and the following
.\" disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd July 1, 2015
.Dt IWM 4
.Os
.Sh NAME
.Nm iwm
.Nd Intel IEEE 802.11ac wireless network driver
.Sh SYNOPSIS
To compile this driver into the kernel,
include the following lines in your
kernel configuration file:
.Bd -ragged -offset indent
.Cd "device iwm"
.Cd "device pci"
.Cd "device wlan"
.Cd "device firmware"
.Ed
.Pp
You also need to select a firmware for your device.
Choose one from:
.Bd -ragged -offset indent
.Cd "device iwm3160fw"
.Cd "device iwm7260fw"
.Cd "device iwm7265fw"
.Ed
.Pp
Or you can use
.Bd -ragged -offset indent
.Cd "device iwmfw"
.Ed
.Pp
to include them all.
.Pp
Alternatively, to load the driver as a
module at boot time, place the following lines in
.Xr loader.conf 5 :
.Bd -literal -offset indent
if_iwm_load="YES"
iwm3160fw_load="YES"
iwm7260fw_load="YES"
iwm7265fw_load="YES"
.Ed
.Sh DESCRIPTION
The
.Nm
driver provides support for:
.Pp
.Bl -tag -width Ds -offset indent -compact
.It Intel Dual Band Wireless AC 3160
.It Intel Dual Band Wireless AC 7260
.It Intel Dual Band Wireless AC 7265
.El
.Pp
.Nm
supports
.Cm station
mode operation.
Only one virtual interface may be configured at any time.
For more information on configuring this device, see
.Xr ifconfig 8 .
.Pp
This driver requires the firmware built with the
.Nm iwmfw
module to work.
.Sh EXAMPLES
Join an existing BSS network (i.e., connect to an access point):
.Bd -literal -offset indent
ifconfig wlan create wlandev iwm0 inet 192.168.0.20 \e
netmask 0xffffff00
.Ed
.Pp
Join a specific BSS network with network name
.Dq Li my_net :
.Pp
.Dl "ifconfig wlan create wlandev iwm0 ssid my_net up"
.Pp
Join a specific BSS network with 64-bit WEP encryption:
.Bd -literal -offset indent
ifconfig wlan create wlandev iwm0 ssid my_net \e
wepmode on wepkey 0x1234567890 weptxkey 1 up
.Ed
.Pp
Join a specific BSS network with 128-bit WEP encryption:
.Bd -literal -offset indent
ifconfig wlan create wlandev iwm0 wlanmode adhoc ssid my_net \e
wepmode on wepkey 0x01020304050607080910111213 weptxkey 1
.Ed
.Sh DIAGNOSTICS
.Bl -diag
.It "iwm%d: device timeout"
The driver will reset the hardware.
This should not happen.
.It "iwm%d: firmware error"
The onboard microcontroller crashed for some reason.
The driver will reset the hardware.
This should not happen.
.It "iwm%d: timeout waiting for firmware initialization to complete"
The onboard microcontroller failed to initialize in time.
This should not happen.
.It "iwm%d: could not load firmware image '%s'"
The driver failed to load the firmware image using the
.Xr firmware 9
subsystem.
Verify the
.Xr iwmfw 4
firmware module is present.
.It "iwm%d: could not load boot firmware"
An attempt to upload the boot firmware image to the onboard microcontroller
failed.
This should not happen.
.It "iwm%d: could not load microcode"
An attempt to upload the microcode image to the onboard microcontroller failed.
This should not happen.
.It "iwm%d: could not load main firmware"
An attempt to upload the main firmware image to the onboard microcontroller
failed.
This should not happen.
.El
.Sh SEE ALSO
.Xr iwmfw 4 ,
.Xr pci 4 ,
.Xr wlan 4 ,
.Xr wlan_ccmp 4 ,
.Xr wlan_tkip 4 ,
.Xr wlan_wep 4 ,
.Xr ifconfig 8 ,
.Xr wpa_supplicant 8

66
share/man/man4/iwmfw.4 Normal file
View File

@ -0,0 +1,66 @@
.\" Copyright (c) 2009 Sam Leffler, Errno Consulting
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. The name of the author may not be used to endorse or promote products
.\" derived from this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd May 28, 2015
.Dt IWMFW 4
.Os
.Sh NAME
.Nm iwmfw
.Nd "Firmware Module for Intel Wireless driver"
.Sh SYNOPSIS
To compile this module into the kernel,
place the following line in your
kernel configuration file:
.Bd -ragged -offset indent
.Cd "device iwmfw"
.Ed
.Pp
This will include firmware images for all
.Xr iwm 4
devices inside the kernel.
If you want to pick only the firmware image for your network adapter choose one
of the following:
.Bd -ragged -offset indent
.Cd "device iwm3160fw"
.Cd "device iwm7260fw"
.Cd "device iwm7265fw"
.Ed
.Pp
Alternatively, to load the driver as a
module at boot time, place the following line in
.Xr loader.conf 5 :
.Bd -literal -offset indent
iwm3160fw_load="YES"
iwm7260fw_load="YES"
iwm7265fw_load="YES"
.Ed
.Sh DESCRIPTION
This module provides access to firmware sets for the
Intel Dual Band Wireless WiFi 3160, 7260 and 7265 series of
IEEE 802.11n/11ac adapters.
It may be
statically linked into the kernel, or loaded as a module.
.Sh SEE ALSO
.Xr iwm 4 ,
.Xr firmware 9

View File

@ -0,0 +1,39 @@
Copyright (c) 2014, Intel Corporation.
All rights reserved.
Redistribution. Redistribution and use in binary form, without
modification, are permitted provided that the following conditions are
met:
* Redistributions must reproduce the above copyright notice and the
following disclaimer in the documentation and/or other materials
provided with the distribution.
* Neither the name of Intel Corporation nor the names of its suppliers
may be used to endorse or promote products derived from this software
without specific prior written permission.
* No reverse engineering, decompilation, or disassembly of this software
is permitted.
Limited patent license. Intel Corporation grants a world-wide,
royalty-free, non-exclusive license under patents it now or hereafter
owns or controls to make, have made, use, import, offer to sell and
sell ("Utilize") this software, but solely to the extent that any
such patent is necessary to Utilize the software alone, or in
combination with an operating system licensed under an approved Open
Source license as listed by the Open Source Initiative at
http://opensource.org/licenses. The patent license shall not apply to
any other combinations which include this software. No hardware per
se is licensed hereunder.
DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

5125
sys/dev/iwm/if_iwm.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,213 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/endian.h>
#include <sys/firmware.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/rman.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/endian.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_ratectl.h>
#include <net80211/ieee80211_radiotap.h>
#include <if_iwmreg.h>
#include <if_iwmvar.h>
#include <if_iwm_debug.h>
#include <if_iwm_util.h>
#include <if_iwm_binding.h>
/*
* BEGIN iwlwifi/mvm/binding.c
*/
int
iwm_mvm_binding_cmd(struct iwm_softc *sc, struct iwm_node *in, uint32_t action)
{
struct iwm_binding_cmd cmd;
struct iwm_mvm_phy_ctxt *phyctxt = in->in_phyctxt;
int i, ret;
uint32_t status;
memset(&cmd, 0, sizeof(cmd));
cmd.id_and_color
= htole32(IWM_FW_CMD_ID_AND_COLOR(phyctxt->id, phyctxt->color));
cmd.action = htole32(action);
cmd.phy = htole32(IWM_FW_CMD_ID_AND_COLOR(phyctxt->id, phyctxt->color));
cmd.macs[0] = htole32(IWM_FW_CMD_ID_AND_COLOR(IWM_DEFAULT_MACID,
IWM_DEFAULT_COLOR));
/* We use MACID 0 here.. */
for (i = 1; i < IWM_MAX_MACS_IN_BINDING; i++)
cmd.macs[i] = htole32(IWM_FW_CTXT_INVALID);
status = 0;
ret = iwm_mvm_send_cmd_pdu_status(sc, IWM_BINDING_CONTEXT_CMD,
sizeof(cmd), &cmd, &status);
if (ret) {
IWM_DPRINTF(sc, IWM_DEBUG_CMD | IWM_DEBUG_RESET,
"%s: Failed to send binding (action:%d): %d\n",
__func__, action, ret);
return ret;
}
if (status) {
IWM_DPRINTF(sc, IWM_DEBUG_CMD | IWM_DEBUG_RESET,
"%s: Binding command failed: %u\n",
__func__,
status);
ret = EIO;
}
return ret;
}
int
iwm_mvm_binding_update(struct iwm_softc *sc, struct iwm_node *in, int add)
{
return iwm_mvm_binding_cmd(sc, in, IWM_FW_CTXT_ACTION_ADD);
}
int
iwm_mvm_binding_add_vif(struct iwm_softc *sc, struct iwm_node *in)
{
return iwm_mvm_binding_update(sc, in, IWM_FW_CTXT_ACTION_ADD);
}

View File

@ -0,0 +1,114 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/* $FreeBSD$ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __IF_IWM_BINDING_H__
#define __IF_IWM_BINDING_H__
extern int iwm_mvm_binding_cmd(struct iwm_softc *sc, struct iwm_node *in,
uint32_t action);
extern int iwm_mvm_binding_update(struct iwm_softc *sc, struct iwm_node *in,
int add);
extern int iwm_mvm_binding_add_vif(struct iwm_softc *sc, struct iwm_node *in);
#endif /* __IF_IWM_BINDING_H__ */

View File

@ -0,0 +1,58 @@
/*-
* Copyright (c) 2015 Adrian Chadd <adrian@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD$
*/
#ifndef __IF_IWM_DEBUG_H__
#define __IF_IWM_DEBUG_H__
#ifdef IWM_DEBUG
enum {
IWM_DEBUG_XMIT = 0x00000001, /* basic xmit operation */
IWM_DEBUG_RECV = 0x00000002, /* basic recv operation */
IWM_DEBUG_STATE = 0x00000004, /* 802.11 state transitions */
IWM_DEBUG_TXPOW = 0x00000008, /* tx power processing */
IWM_DEBUG_RESET = 0x00000010, /* reset processing */
IWM_DEBUG_OPS = 0x00000020, /* iwm_ops processing */
IWM_DEBUG_BEACON = 0x00000040, /* beacon handling */
IWM_DEBUG_WATCHDOG = 0x00000080, /* watchdog timeout */
IWM_DEBUG_INTR = 0x00000100, /* ISR */
IWM_DEBUG_CALIBRATE = 0x00000200, /* periodic calibration */
IWM_DEBUG_NODE = 0x00000400, /* node management */
IWM_DEBUG_LED = 0x00000800, /* led management */
IWM_DEBUG_CMD = 0x00001000, /* cmd submission */
IWM_DEBUG_TXRATE = 0x00002000, /* TX rate debugging */
IWM_DEBUG_PWRSAVE = 0x00004000, /* Power save operations */
IWM_DEBUG_SCAN = 0x00008000, /* Scan related operations */
IWM_DEBUG_STATS = 0x00010000, /* Statistics updates */
IWM_DEBUG_FIRMWARE_TLV = 0x00020000, /* Firmware TLV parsing */
IWM_DEBUG_TRANS = 0x00040000, /* Transport layer (eg PCIe) */
IWM_DEBUG_EEPROM = 0x00080000, /* EEPROM/channel information */
IWM_DEBUG_REGISTER = 0x20000000, /* print chipset register */
IWM_DEBUG_TRACE = 0x40000000, /* Print begin and start driver function */
IWM_DEBUG_FATAL = 0x80000000, /* fatal errors */
IWM_DEBUG_ANY = 0xffffffff
};
#define IWM_DPRINTF(sc, m, fmt, ...) do { \
if (sc->sc_debug & (m)) \
device_printf(sc->sc_dev, fmt, ##__VA_ARGS__); \
} while (0)
#else
#define IWM_DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
#endif
#endif /* __IF_IWM_DEBUG_H__ */

View File

@ -0,0 +1,533 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/endian.h>
#include <sys/firmware.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/rman.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/endian.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_ratectl.h>
#include <net80211/ieee80211_radiotap.h>
#include <if_iwmreg.h>
#include <if_iwmvar.h>
#include <if_iwm_debug.h>
#include <if_iwm_util.h>
#include <if_iwm_mac_ctxt.h>
/*
* BEGIN mvm/mac-ctxt.c
*/
static void
iwm_mvm_ack_rates(struct iwm_softc *sc, int is2ghz,
int *cck_rates, int *ofdm_rates)
{
int lowest_present_ofdm = 100;
int lowest_present_cck = 100;
uint8_t cck = 0;
uint8_t ofdm = 0;
int i;
if (is2ghz) {
for (i = 0; i <= IWM_LAST_CCK_RATE; i++) {
cck |= (1 << i);
if (lowest_present_cck > i)
lowest_present_cck = i;
}
}
for (i = IWM_FIRST_OFDM_RATE; i <= IWM_LAST_NON_HT_RATE; i++) {
int adj = i - IWM_FIRST_OFDM_RATE;
ofdm |= (1 << adj);
if (lowest_present_ofdm > i)
lowest_present_ofdm = i;
}
/*
* Now we've got the basic rates as bitmaps in the ofdm and cck
* variables. This isn't sufficient though, as there might not
* be all the right rates in the bitmap. E.g. if the only basic
* rates are 5.5 Mbps and 11 Mbps, we still need to add 1 Mbps
* and 6 Mbps because the 802.11-2007 standard says in 9.6:
*
* [...] a STA responding to a received frame shall transmit
* its Control Response frame [...] at the highest rate in the
* BSSBasicRateSet parameter that is less than or equal to the
* rate of the immediately previous frame in the frame exchange
* sequence ([...]) and that is of the same modulation class
* ([...]) as the received frame. If no rate contained in the
* BSSBasicRateSet parameter meets these conditions, then the
* control frame sent in response to a received frame shall be
* transmitted at the highest mandatory rate of the PHY that is
* less than or equal to the rate of the received frame, and
* that is of the same modulation class as the received frame.
*
* As a consequence, we need to add all mandatory rates that are
* lower than all of the basic rates to these bitmaps.
*/
if (IWM_RATE_24M_INDEX < lowest_present_ofdm)
ofdm |= IWM_RATE_BIT_MSK(24) >> IWM_FIRST_OFDM_RATE;
if (IWM_RATE_12M_INDEX < lowest_present_ofdm)
ofdm |= IWM_RATE_BIT_MSK(12) >> IWM_FIRST_OFDM_RATE;
/* 6M already there or needed so always add */
ofdm |= IWM_RATE_BIT_MSK(6) >> IWM_FIRST_OFDM_RATE;
/*
* CCK is a bit more complex with DSSS vs. HR/DSSS vs. ERP.
* Note, however:
* - if no CCK rates are basic, it must be ERP since there must
* be some basic rates at all, so they're OFDM => ERP PHY
* (or we're in 5 GHz, and the cck bitmap will never be used)
* - if 11M is a basic rate, it must be ERP as well, so add 5.5M
* - if 5.5M is basic, 1M and 2M are mandatory
* - if 2M is basic, 1M is mandatory
* - if 1M is basic, that's the only valid ACK rate.
* As a consequence, it's not as complicated as it sounds, just add
* any lower rates to the ACK rate bitmap.
*/
if (IWM_RATE_11M_INDEX < lowest_present_cck)
cck |= IWM_RATE_BIT_MSK(11) >> IWM_FIRST_CCK_RATE;
if (IWM_RATE_5M_INDEX < lowest_present_cck)
cck |= IWM_RATE_BIT_MSK(5) >> IWM_FIRST_CCK_RATE;
if (IWM_RATE_2M_INDEX < lowest_present_cck)
cck |= IWM_RATE_BIT_MSK(2) >> IWM_FIRST_CCK_RATE;
/* 1M already there or needed so always add */
cck |= IWM_RATE_BIT_MSK(1) >> IWM_FIRST_CCK_RATE;
*cck_rates = cck;
*ofdm_rates = ofdm;
}
static void
iwm_mvm_mac_ctxt_cmd_common(struct iwm_softc *sc, struct iwm_node *in,
struct iwm_mac_ctx_cmd *cmd, uint32_t action)
{
struct ieee80211com *ic = sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_node *ni = vap->iv_bss;
int cck_ack_rates, ofdm_ack_rates;
int i;
int is2ghz;
/*
* id is the MAC address ID - something to do with MAC filtering.
* color - not sure.
*
* These are both functions of the vap, not of the node.
* So, for now, hard-code both to 0 (default).
*/
cmd->id_and_color = htole32(IWM_FW_CMD_ID_AND_COLOR(IWM_DEFAULT_MACID,
IWM_DEFAULT_COLOR));
cmd->action = htole32(action);
cmd->mac_type = htole32(IWM_FW_MAC_TYPE_BSS_STA);
/*
* The TSF ID is one of four TSF tracking resources in the firmware.
* Read the iwlwifi/mvm code for more details.
*
* For now, just hard-code it to TSF tracking ID 0; we only support
* a single STA mode VAP.
*
* It's per-vap, not per-node.
*/
cmd->tsf_id = htole32(IWM_DEFAULT_TSFID);
IEEE80211_ADDR_COPY(cmd->node_addr, sc->sc_bssid);
/*
* XXX should we error out if in_assoc is 1 and ni == NULL?
*/
if (in->in_assoc) {
IEEE80211_ADDR_COPY(cmd->bssid_addr, ni->ni_bssid);
} else {
/* eth broadcast address */
memset(cmd->bssid_addr, 0xff, sizeof(cmd->bssid_addr));
}
/*
* Default to 2ghz if no node information is given.
*/
if (in) {
is2ghz = !! IEEE80211_IS_CHAN_2GHZ(in->in_ni.ni_chan);
} else {
is2ghz = 1;
}
iwm_mvm_ack_rates(sc, is2ghz, &cck_ack_rates, &ofdm_ack_rates);
cmd->cck_rates = htole32(cck_ack_rates);
cmd->ofdm_rates = htole32(ofdm_ack_rates);
cmd->cck_short_preamble
= htole32((ic->ic_flags & IEEE80211_F_SHPREAMBLE)
? IWM_MAC_FLG_SHORT_PREAMBLE : 0);
cmd->short_slot
= htole32((ic->ic_flags & IEEE80211_F_SHSLOT)
? IWM_MAC_FLG_SHORT_SLOT : 0);
/* XXX TODO: set wme parameters; also handle getting updated wme parameters */
for (i = 0; i < IWM_AC_NUM+1; i++) {
int txf = i;
cmd->ac[txf].cw_min = htole16(0x0f);
cmd->ac[txf].cw_max = htole16(0x3f);
cmd->ac[txf].aifsn = 1;
cmd->ac[txf].fifos_mask = (1 << txf);
cmd->ac[txf].edca_txop = 0;
}
if (ic->ic_flags & IEEE80211_F_USEPROT)
cmd->protection_flags |= htole32(IWM_MAC_PROT_FLG_TGG_PROTECT);
cmd->filter_flags = htole32(IWM_MAC_FILTER_ACCEPT_GRP);
}
static int
iwm_mvm_mac_ctxt_send_cmd(struct iwm_softc *sc, struct iwm_mac_ctx_cmd *cmd)
{
int ret = iwm_mvm_send_cmd_pdu(sc, IWM_MAC_CONTEXT_CMD, IWM_CMD_SYNC,
sizeof(*cmd), cmd);
if (ret)
device_printf(sc->sc_dev,
"%s: Failed to send MAC context (action:%d): %d\n",
__func__, le32toh(cmd->action), ret);
return ret;
}
/*
* Fill the specific data for mac context of type station or p2p client
*/
static void
iwm_mvm_mac_ctxt_cmd_fill_sta(struct iwm_softc *sc, struct iwm_node *in,
struct iwm_mac_data_sta *ctxt_sta, int force_assoc_off)
{
struct ieee80211_node *ni = &in->in_ni;
unsigned dtim_period, dtim_count;
struct ieee80211com *ic = sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
/* will this work? */
dtim_period = vap->iv_dtim_period;
dtim_count = vap->iv_dtim_count;
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_BEACON | IWM_DEBUG_CMD,
"%s: force_assoc_off=%d\n", __func__, force_assoc_off);
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_BEACON | IWM_DEBUG_CMD,
"DTIM: period=%d count=%d\n", dtim_period, dtim_count);
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_BEACON | IWM_DEBUG_CMD,
"BEACON: tsf: %llu, ni_intval=%d\n",
(unsigned long long) le64toh(ni->ni_tstamp.tsf),
ni->ni_intval);
/* We need the dtim_period to set the MAC as associated */
if (in->in_assoc && dtim_period && !force_assoc_off) {
uint64_t tsf;
uint32_t dtim_offs;
/*
* The DTIM count counts down, so when it is N that means N
* more beacon intervals happen until the DTIM TBTT. Therefore
* add this to the current time. If that ends up being in the
* future, the firmware will handle it.
*
* Also note that the system_timestamp (which we get here as
* "sync_device_ts") and TSF timestamp aren't at exactly the
* same offset in the frame -- the TSF is at the first symbol
* of the TSF, the system timestamp is at signal acquisition
* time. This means there's an offset between them of at most
* a few hundred microseconds (24 * 8 bits + PLCP time gives
* 384us in the longest case), this is currently not relevant
* as the firmware wakes up around 2ms before the TBTT.
*/
dtim_offs = dtim_count * ni->ni_intval;
/* convert TU to usecs */
dtim_offs *= 1024;
/*
* net80211: TSF is in 802.11 order, so convert up to local
* ordering before we manipulate things.
*/
tsf = le64toh(ni->ni_tstamp.tsf);
ctxt_sta->dtim_tsf = htole64(tsf + dtim_offs);
ctxt_sta->dtim_time = htole32(tsf + dtim_offs);
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_BEACON | IWM_DEBUG_CMD,
"DTIM TBTT is 0x%llx/0x%x, offset %d\n",
(long long)le64toh(ctxt_sta->dtim_tsf),
le32toh(ctxt_sta->dtim_time), dtim_offs);
ctxt_sta->is_assoc = htole32(1);
} else {
ctxt_sta->is_assoc = htole32(0);
}
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_CMD | IWM_DEBUG_BEACON,
"%s: ni_intval: %d, bi_reciprocal: %d, dtim_interval: %d, dtim_reciprocal: %d\n",
__func__,
ni->ni_intval,
iwm_mvm_reciprocal(ni->ni_intval),
ni->ni_intval * dtim_period,
iwm_mvm_reciprocal(ni->ni_intval * dtim_period));
ctxt_sta->bi = htole32(ni->ni_intval);
ctxt_sta->bi_reciprocal = htole32(iwm_mvm_reciprocal(ni->ni_intval));
ctxt_sta->dtim_interval = htole32(ni->ni_intval * dtim_period);
ctxt_sta->dtim_reciprocal =
htole32(iwm_mvm_reciprocal(ni->ni_intval * dtim_period));
/* 10 = CONN_MAX_LISTEN_INTERVAL */
ctxt_sta->listen_interval = htole32(10);
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_CMD | IWM_DEBUG_BEACON,
"%s: associd=%d\n", __func__, IEEE80211_AID(ni->ni_associd));
ctxt_sta->assoc_id = htole32(IEEE80211_AID(ni->ni_associd));
}
static int
iwm_mvm_mac_ctxt_cmd_station(struct iwm_softc *sc, struct ieee80211vap *vap,
uint32_t action)
{
struct ieee80211_node *ni = vap->iv_bss;
struct iwm_node *in = (struct iwm_node *) ni;
struct iwm_mac_ctx_cmd cmd;
IWM_DPRINTF(sc, IWM_DEBUG_RESET,
"%s: called; action=%d\n", __func__, action);
memset(&cmd, 0, sizeof(cmd));
/* Fill the common data for all mac context types */
iwm_mvm_mac_ctxt_cmd_common(sc, in, &cmd, action);
/* Allow beacons to pass through as long as we are not associated,or we
* do not have dtim period information */
if (!in->in_assoc || !vap->iv_dtim_period)
cmd.filter_flags |= htole32(IWM_MAC_FILTER_IN_BEACON);
else
cmd.filter_flags &= ~htole32(IWM_MAC_FILTER_IN_BEACON);
/* Fill the data specific for station mode */
iwm_mvm_mac_ctxt_cmd_fill_sta(sc, in,
&cmd.sta, action == IWM_FW_CTXT_ACTION_ADD);
return iwm_mvm_mac_ctxt_send_cmd(sc, &cmd);
}
static int
iwm_mvm_mac_ctx_send(struct iwm_softc *sc, struct ieee80211vap *vap,
uint32_t action)
{
int ret;
ret = iwm_mvm_mac_ctxt_cmd_station(sc, vap, action);
if (ret)
return (ret);
return (0);
}
int
iwm_mvm_mac_ctxt_add(struct iwm_softc *sc, struct ieee80211vap *vap)
{
struct iwm_vap *iv = IWM_VAP(vap);
int ret;
if (iv->is_uploaded != 0) {
device_printf(sc->sc_dev, "%s: called; uploaded != 0\n",
__func__);
return (EIO);
}
ret = iwm_mvm_mac_ctx_send(sc, vap, IWM_FW_CTXT_ACTION_ADD);
if (ret)
return (ret);
iv->is_uploaded = 1;
return (0);
}
int
iwm_mvm_mac_ctxt_changed(struct iwm_softc *sc, struct ieee80211vap *vap)
{
struct iwm_vap *iv = IWM_VAP(vap);
int ret;
if (iv->is_uploaded == 0) {
device_printf(sc->sc_dev, "%s: called; uploaded = 0\n",
__func__);
return (EIO);
}
ret = iwm_mvm_mac_ctx_send(sc, vap, IWM_FW_CTXT_ACTION_MODIFY);
if (ret)
return (ret);
return (0);
}
#if 0
static int
iwm_mvm_mac_ctxt_remove(struct iwm_softc *sc, struct iwm_node *in)
{
struct iwm_mac_ctx_cmd cmd;
int ret;
if (!in->in_uploaded) {
device_printf(sc->sc_dev,
"attempt to remove !uploaded node %p", in);
return EIO;
}
memset(&cmd, 0, sizeof(cmd));
cmd.id_and_color = htole32(IWM_FW_CMD_ID_AND_COLOR(IWM_DEFAULT_MACID,
IWM_DEFAULT_COLOR));
cmd.action = htole32(IWM_FW_CTXT_ACTION_REMOVE);
ret = iwm_mvm_send_cmd_pdu(sc,
IWM_MAC_CONTEXT_CMD, IWM_CMD_SYNC, sizeof(cmd), &cmd);
if (ret) {
device_printf(sc->sc_dev,
"Failed to remove MAC context: %d\n", ret);
return ret;
}
in->in_uploaded = 0;
return 0;
}
#endif

View File

@ -0,0 +1,113 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/* $FreeBSD$ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __IF_IWM_MAC_CTXT_H__
#define __IF_IWM_MAC_CTXT_H__
extern int iwm_mvm_mac_ctxt_add(struct iwm_softc *sc, struct ieee80211vap *vap);
extern int iwm_mvm_mac_ctxt_changed(struct iwm_softc *sc, struct ieee80211vap *vap);
extern int iwm_mvm_mac_ctxt_remove(struct iwm_softc *sc, struct ieee80211vap *vap);
#endif /* __IF_IWM_MAC_CTXT_H__ */

View File

@ -0,0 +1,565 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/endian.h>
#include <sys/firmware.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/rman.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/endian.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_ratectl.h>
#include <net80211/ieee80211_radiotap.h>
#include <if_iwmreg.h>
#include <if_iwmvar.h>
#include <if_iwm_debug.h>
#include <if_iwm_pcie_trans.h>
/*
* This is a subset of what's in linux iwlwifi/pcie/trans.c.
* The rest can be migrated out into here once they're no longer in
* if_iwm.c.
*/
/*
* basic device access
*/
uint32_t
iwm_read_prph(struct iwm_softc *sc, uint32_t addr)
{
IWM_WRITE(sc,
IWM_HBUS_TARG_PRPH_RADDR, ((addr & 0x000fffff) | (3 << 24)));
IWM_BARRIER_READ_WRITE(sc);
return IWM_READ(sc, IWM_HBUS_TARG_PRPH_RDAT);
}
void
iwm_write_prph(struct iwm_softc *sc, uint32_t addr, uint32_t val)
{
IWM_WRITE(sc,
IWM_HBUS_TARG_PRPH_WADDR, ((addr & 0x000fffff) | (3 << 24)));
IWM_BARRIER_WRITE(sc);
IWM_WRITE(sc, IWM_HBUS_TARG_PRPH_WDAT, val);
}
#ifdef IWM_DEBUG
/* iwlwifi: pcie/trans.c */
int
iwm_read_mem(struct iwm_softc *sc, uint32_t addr, void *buf, int dwords)
{
int offs, ret = 0;
uint32_t *vals = buf;
if (iwm_nic_lock(sc)) {
IWM_WRITE(sc, IWM_HBUS_TARG_MEM_RADDR, addr);
for (offs = 0; offs < dwords; offs++)
vals[offs] = IWM_READ(sc, IWM_HBUS_TARG_MEM_RDAT);
iwm_nic_unlock(sc);
} else {
ret = EBUSY;
}
return ret;
}
#endif
/* iwlwifi: pcie/trans.c */
int
iwm_write_mem(struct iwm_softc *sc, uint32_t addr, const void *buf, int dwords)
{
int offs;
const uint32_t *vals = buf;
if (iwm_nic_lock(sc)) {
IWM_WRITE(sc, IWM_HBUS_TARG_MEM_WADDR, addr);
/* WADDR auto-increments */
for (offs = 0; offs < dwords; offs++) {
uint32_t val = vals ? vals[offs] : 0;
IWM_WRITE(sc, IWM_HBUS_TARG_MEM_WDAT, val);
}
iwm_nic_unlock(sc);
} else {
IWM_DPRINTF(sc, IWM_DEBUG_TRANS,
"%s: write_mem failed\n", __func__);
return EBUSY;
}
return 0;
}
int
iwm_write_mem32(struct iwm_softc *sc, uint32_t addr, uint32_t val)
{
return iwm_write_mem(sc, addr, &val, 1);
}
int
iwm_poll_bit(struct iwm_softc *sc, int reg,
uint32_t bits, uint32_t mask, int timo)
{
for (;;) {
if ((IWM_READ(sc, reg) & mask) == (bits & mask)) {
return 1;
}
if (timo < 10) {
return 0;
}
timo -= 10;
DELAY(10);
}
}
int
iwm_nic_lock(struct iwm_softc *sc)
{
int rv = 0;
IWM_SETBITS(sc, IWM_CSR_GP_CNTRL,
IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
if (iwm_poll_bit(sc, IWM_CSR_GP_CNTRL,
IWM_CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY
| IWM_CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP, 15000)) {
rv = 1;
} else {
/* jolt */
IWM_WRITE(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_FORCE_NMI);
}
return rv;
}
void
iwm_nic_unlock(struct iwm_softc *sc)
{
IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL,
IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
}
void
iwm_set_bits_mask_prph(struct iwm_softc *sc,
uint32_t reg, uint32_t bits, uint32_t mask)
{
uint32_t val;
/* XXX: no error path? */
if (iwm_nic_lock(sc)) {
val = iwm_read_prph(sc, reg) & mask;
val |= bits;
iwm_write_prph(sc, reg, val);
iwm_nic_unlock(sc);
}
}
void
iwm_set_bits_prph(struct iwm_softc *sc, uint32_t reg, uint32_t bits)
{
iwm_set_bits_mask_prph(sc, reg, bits, ~0);
}
void
iwm_clear_bits_prph(struct iwm_softc *sc, uint32_t reg, uint32_t bits)
{
iwm_set_bits_mask_prph(sc, reg, 0, ~bits);
}
/*
* High-level hardware frobbing routines
*/
void
iwm_enable_rfkill_int(struct iwm_softc *sc)
{
sc->sc_intmask = IWM_CSR_INT_BIT_RF_KILL;
IWM_WRITE(sc, IWM_CSR_INT_MASK, sc->sc_intmask);
}
int
iwm_check_rfkill(struct iwm_softc *sc)
{
uint32_t v;
int rv;
/*
* "documentation" is not really helpful here:
* 27: HW_RF_KILL_SW
* Indicates state of (platform's) hardware RF-Kill switch
*
* But apparently when it's off, it's on ...
*/
v = IWM_READ(sc, IWM_CSR_GP_CNTRL);
rv = (v & IWM_CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) == 0;
if (rv) {
sc->sc_flags |= IWM_FLAG_RFKILL;
} else {
sc->sc_flags &= ~IWM_FLAG_RFKILL;
}
return rv;
}
#define IWM_HW_READY_TIMEOUT 50
int
iwm_set_hw_ready(struct iwm_softc *sc)
{
IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG,
IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY);
return iwm_poll_bit(sc, IWM_CSR_HW_IF_CONFIG_REG,
IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
IWM_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
IWM_HW_READY_TIMEOUT);
}
#undef IWM_HW_READY_TIMEOUT
int
iwm_prepare_card_hw(struct iwm_softc *sc)
{
int rv = 0;
int t = 0;
IWM_DPRINTF(sc, IWM_DEBUG_RESET, "->%s\n", __func__);
if (iwm_set_hw_ready(sc))
goto out;
/* If HW is not ready, prepare the conditions to check again */
IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG,
IWM_CSR_HW_IF_CONFIG_REG_PREPARE);
do {
if (iwm_set_hw_ready(sc))
goto out;
DELAY(200);
t += 200;
} while (t < 150000);
rv = ETIMEDOUT;
out:
IWM_DPRINTF(sc, IWM_DEBUG_RESET, "<-%s\n", __func__);
return rv;
}
void
iwm_apm_config(struct iwm_softc *sc)
{
uint16_t reg;
reg = pci_read_config(sc->sc_dev, PCIER_LINK_CTL, sizeof(reg));
if (reg & PCIEM_LINK_CTL_ASPMC_L1) {
/* Um the Linux driver prints "Disabling L0S for this one ... */
IWM_SETBITS(sc, IWM_CSR_GIO_REG,
IWM_CSR_GIO_REG_VAL_L0S_ENABLED);
} else {
/* ... and "Enabling" here */
IWM_CLRBITS(sc, IWM_CSR_GIO_REG,
IWM_CSR_GIO_REG_VAL_L0S_ENABLED);
}
}
/*
* Start up NIC's basic functionality after it has been reset
* (e.g. after platform boot, or shutdown via iwm_pcie_apm_stop())
* NOTE: This does not load uCode nor start the embedded processor
*/
int
iwm_apm_init(struct iwm_softc *sc)
{
int error = 0;
IWM_DPRINTF(sc, IWM_DEBUG_RESET, "iwm apm start\n");
/* Disable L0S exit timer (platform NMI Work/Around) */
IWM_SETBITS(sc, IWM_CSR_GIO_CHICKEN_BITS,
IWM_CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
/*
* Disable L0s without affecting L1;
* don't wait for ICH L0s (ICH bug W/A)
*/
IWM_SETBITS(sc, IWM_CSR_GIO_CHICKEN_BITS,
IWM_CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
/* Set FH wait threshold to maximum (HW error during stress W/A) */
IWM_SETBITS(sc, IWM_CSR_DBG_HPET_MEM_REG, IWM_CSR_DBG_HPET_MEM_REG_VAL);
/*
* Enable HAP INTA (interrupt from management bus) to
* wake device's PCI Express link L1a -> L0s
*/
IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG,
IWM_CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
iwm_apm_config(sc);
#if 0 /* not for 7k */
/* Configure analog phase-lock-loop before activating to D0A */
if (trans->cfg->base_params->pll_cfg_val)
IWM_SETBITS(trans, IWM_CSR_ANA_PLL_CFG,
trans->cfg->base_params->pll_cfg_val);
#endif
/*
* Set "initialization complete" bit to move adapter from
* D0U* --> D0A* (powered-up active) state.
*/
IWM_SETBITS(sc, IWM_CSR_GP_CNTRL, IWM_CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
/*
* Wait for clock stabilization; once stabilized, access to
* device-internal resources is supported, e.g. iwm_write_prph()
* and accesses to uCode SRAM.
*/
if (!iwm_poll_bit(sc, IWM_CSR_GP_CNTRL,
IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000)) {
device_printf(sc->sc_dev,
"timeout waiting for clock stabilization\n");
goto out;
}
if (sc->host_interrupt_operation_mode) {
/*
* This is a bit of an abuse - This is needed for 7260 / 3160
* only check host_interrupt_operation_mode even if this is
* not related to host_interrupt_operation_mode.
*
* Enable the oscillator to count wake up time for L1 exit. This
* consumes slightly more power (100uA) - but allows to be sure
* that we wake up from L1 on time.
*
* This looks weird: read twice the same register, discard the
* value, set a bit, and yet again, read that same register
* just to discard the value. But that's the way the hardware
* seems to like it.
*/
iwm_read_prph(sc, IWM_OSC_CLK);
iwm_read_prph(sc, IWM_OSC_CLK);
iwm_set_bits_prph(sc, IWM_OSC_CLK, IWM_OSC_CLK_FORCE_CONTROL);
iwm_read_prph(sc, IWM_OSC_CLK);
iwm_read_prph(sc, IWM_OSC_CLK);
}
/*
* Enable DMA clock and wait for it to stabilize.
*
* Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits
* do not disable clocks. This preserves any hardware bits already
* set by default in "CLK_CTRL_REG" after reset.
*/
iwm_write_prph(sc, IWM_APMG_CLK_EN_REG, IWM_APMG_CLK_VAL_DMA_CLK_RQT);
//kpause("iwmapm", 0, mstohz(20), NULL);
DELAY(20);
/* Disable L1-Active */
iwm_set_bits_prph(sc, IWM_APMG_PCIDEV_STT_REG,
IWM_APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
/* Clear the interrupt in APMG if the NIC is in RFKILL */
iwm_write_prph(sc, IWM_APMG_RTC_INT_STT_REG,
IWM_APMG_RTC_INT_STT_RFKILL);
out:
if (error)
device_printf(sc->sc_dev, "apm init error %d\n", error);
return error;
}
/* iwlwifi/pcie/trans.c */
void
iwm_apm_stop(struct iwm_softc *sc)
{
/* stop device's busmaster DMA activity */
IWM_SETBITS(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_STOP_MASTER);
if (!iwm_poll_bit(sc, IWM_CSR_RESET,
IWM_CSR_RESET_REG_FLAG_MASTER_DISABLED,
IWM_CSR_RESET_REG_FLAG_MASTER_DISABLED, 100))
device_printf(sc->sc_dev, "timeout waiting for master\n");
IWM_DPRINTF(sc, IWM_DEBUG_TRANS, "%s: iwm apm stop\n", __func__);
}
/* iwlwifi pcie/trans.c */
int
iwm_start_hw(struct iwm_softc *sc)
{
int error;
if ((error = iwm_prepare_card_hw(sc)) != 0)
return error;
/* Reset the entire device */
IWM_WRITE(sc, IWM_CSR_RESET,
IWM_CSR_RESET_REG_FLAG_SW_RESET |
IWM_CSR_RESET_REG_FLAG_NEVO_RESET);
DELAY(10);
if ((error = iwm_apm_init(sc)) != 0)
return error;
iwm_enable_rfkill_int(sc);
iwm_check_rfkill(sc);
return 0;
}
/* iwlwifi pcie/trans.c (always main power) */
void
iwm_set_pwr(struct iwm_softc *sc)
{
iwm_set_bits_mask_prph(sc, IWM_APMG_PS_CTRL_REG,
IWM_APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, ~IWM_APMG_PS_CTRL_MSK_PWR_SRC);
}
/* iwlwifi pcie/rx.c */
int
iwm_pcie_rx_stop(struct iwm_softc *sc)
{
IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
return (iwm_poll_bit(sc, IWM_FH_MEM_RSSR_RX_STATUS_REG,
IWM_FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE,
IWM_FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE,
1000));
}

View File

@ -0,0 +1,132 @@
/* $FreeBSD$ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __IWM_PCIE_TRANS_H__
#define __IWM_PCIE_TRANS_H__
extern uint32_t iwm_read_prph(struct iwm_softc *sc, uint32_t addr);
extern void iwm_write_prph(struct iwm_softc *sc, uint32_t addr, uint32_t val);
extern int iwm_read_mem(struct iwm_softc *sc, uint32_t addr, void *buf, int dwords);
extern int iwm_write_mem(struct iwm_softc *sc, uint32_t addr, const void *buf,
int dwords);
extern int iwm_write_mem32(struct iwm_softc *sc, uint32_t addr, uint32_t val);
extern int iwm_poll_bit(struct iwm_softc *sc, int reg,
uint32_t bits, uint32_t mask, int timo);
extern int iwm_nic_lock(struct iwm_softc *sc);
extern void iwm_nic_unlock(struct iwm_softc *sc);
extern void iwm_set_bits_mask_prph(struct iwm_softc *sc,
uint32_t reg, uint32_t bits, uint32_t mask);
extern void iwm_set_bits_prph(struct iwm_softc *sc, uint32_t reg, uint32_t bits);
extern void iwm_clear_bits_prph(struct iwm_softc *sc, uint32_t reg, uint32_t bits);
extern void iwm_enable_rfkill_int(struct iwm_softc *sc);
extern int iwm_check_rfkill(struct iwm_softc *sc);
extern int iwm_set_hw_ready(struct iwm_softc *sc);
extern int iwm_prepare_card_hw(struct iwm_softc *sc);
extern void iwm_apm_config(struct iwm_softc *sc);
extern int iwm_apm_init(struct iwm_softc *sc);
extern void iwm_apm_stop(struct iwm_softc *sc);
extern int iwm_start_hw(struct iwm_softc *sc);
extern void iwm_set_pwr(struct iwm_softc *sc);
extern int iwm_pcie_rx_stop(struct iwm_softc *sc);
#endif

View File

@ -0,0 +1,312 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/endian.h>
#include <sys/firmware.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/rman.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/endian.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_ratectl.h>
#include <net80211/ieee80211_radiotap.h>
#include <if_iwmreg.h>
#include <if_iwmvar.h>
#include <if_iwm_debug.h>
#include <if_iwm_util.h>
#if 0
#include <if_iwm_binding.h>
#include <if_iwm_phy_db.h>
#include <if_iwm_mac_ctxt.h>
#include <if_iwm_pcie_trans.h>
#endif
#include <if_iwm_phy_ctxt.h>
/*
* BEGIN iwlwifi/mvm/phy-ctxt.c
*/
/*
* Construct the generic fields of the PHY context command
*/
static void
iwm_mvm_phy_ctxt_cmd_hdr(struct iwm_softc *sc, struct iwm_mvm_phy_ctxt *ctxt,
struct iwm_phy_context_cmd *cmd, uint32_t action, uint32_t apply_time)
{
memset(cmd, 0, sizeof(struct iwm_phy_context_cmd));
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_CMD,
"%s: id=%d, colour=%d, action=%d, apply_time=%d\n",
__func__,
ctxt->id,
ctxt->color,
action,
apply_time);
cmd->id_and_color = htole32(IWM_FW_CMD_ID_AND_COLOR(ctxt->id,
ctxt->color));
cmd->action = htole32(action);
cmd->apply_time = htole32(apply_time);
}
/*
* Add the phy configuration to the PHY context command
*/
static void
iwm_mvm_phy_ctxt_cmd_data(struct iwm_softc *sc,
struct iwm_phy_context_cmd *cmd, struct ieee80211_channel *chan,
uint8_t chains_static, uint8_t chains_dynamic)
{
struct ieee80211com *ic = sc->sc_ic;
uint8_t active_cnt, idle_cnt;
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_CMD,
"%s: 2ghz=%d, channel=%d, chains static=0x%x, dynamic=0x%x, "
"rx_ant=0x%x, tx_ant=0x%x\n",
__func__,
!! IEEE80211_IS_CHAN_2GHZ(chan),
ieee80211_chan2ieee(ic, chan),
chains_static,
chains_dynamic,
IWM_FW_VALID_RX_ANT(sc),
IWM_FW_VALID_TX_ANT(sc));
cmd->ci.band = IEEE80211_IS_CHAN_2GHZ(chan) ?
IWM_PHY_BAND_24 : IWM_PHY_BAND_5;
cmd->ci.channel = ieee80211_chan2ieee(ic, chan);
cmd->ci.width = IWM_PHY_VHT_CHANNEL_MODE20;
cmd->ci.ctrl_pos = IWM_PHY_VHT_CTRL_POS_1_BELOW;
/* Set rx the chains */
idle_cnt = chains_static;
active_cnt = chains_dynamic;
cmd->rxchain_info = htole32(IWM_FW_VALID_RX_ANT(sc) <<
IWM_PHY_RX_CHAIN_VALID_POS);
cmd->rxchain_info |= htole32(idle_cnt << IWM_PHY_RX_CHAIN_CNT_POS);
cmd->rxchain_info |= htole32(active_cnt <<
IWM_PHY_RX_CHAIN_MIMO_CNT_POS);
cmd->txchain_info = htole32(IWM_FW_VALID_TX_ANT(sc));
}
/*
* Send a command
* only if something in the configuration changed: in case that this is the
* first time that the phy configuration is applied or in case that the phy
* configuration changed from the previous apply.
*/
static int
iwm_mvm_phy_ctxt_apply(struct iwm_softc *sc,
struct iwm_mvm_phy_ctxt *ctxt,
uint8_t chains_static, uint8_t chains_dynamic,
uint32_t action, uint32_t apply_time)
{
struct iwm_phy_context_cmd cmd;
int ret;
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_CMD,
"%s: called; channel=%p\n",
__func__,
ctxt->channel);
/* Set the command header fields */
iwm_mvm_phy_ctxt_cmd_hdr(sc, ctxt, &cmd, action, apply_time);
/* Set the command data */
iwm_mvm_phy_ctxt_cmd_data(sc, &cmd, ctxt->channel,
chains_static, chains_dynamic);
ret = iwm_mvm_send_cmd_pdu(sc, IWM_PHY_CONTEXT_CMD, IWM_CMD_SYNC,
sizeof(struct iwm_phy_context_cmd), &cmd);
if (ret) {
device_printf(sc->sc_dev,
"PHY ctxt cmd error. ret=%d\n", ret);
}
return ret;
}
/*
* Send a command to add a PHY context based on the current HW configuration.
*/
int
iwm_mvm_phy_ctxt_add(struct iwm_softc *sc, struct iwm_mvm_phy_ctxt *ctxt,
struct ieee80211_channel *chan,
uint8_t chains_static, uint8_t chains_dynamic)
{
ctxt->channel = chan;
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_CMD,
"%s: called; channel=%d\n",
__func__,
ieee80211_chan2ieee(sc->sc_ic, chan));
return iwm_mvm_phy_ctxt_apply(sc, ctxt,
chains_static, chains_dynamic, IWM_FW_CTXT_ACTION_ADD, 0);
}
/*
* Send a command to modify the PHY context based on the current HW
* configuration. Note that the function does not check that the configuration
* changed.
*/
int
iwm_mvm_phy_ctxt_changed(struct iwm_softc *sc,
struct iwm_mvm_phy_ctxt *ctxt, struct ieee80211_channel *chan,
uint8_t chains_static, uint8_t chains_dynamic)
{
ctxt->channel = chan;
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_CMD,
"%s: called; channel=%d\n",
__func__,
ieee80211_chan2ieee(sc->sc_ic, chan));
return iwm_mvm_phy_ctxt_apply(sc, ctxt,
chains_static, chains_dynamic, IWM_FW_CTXT_ACTION_MODIFY, 0);
}
/*
* END iwlwifi/mvm/phy-ctxt.c
*/

View File

@ -0,0 +1,117 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/* $FreeBSD$ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __IF_IWM_PHY_CTXT_H__
#define __IF_IWM_PHY_CTXT_H__
extern int iwm_mvm_phy_ctxt_add(struct iwm_softc *sc,
struct iwm_mvm_phy_ctxt *ctxt,
struct ieee80211_channel *chan,
uint8_t chains_static, uint8_t chains_dynamic);
extern int iwm_mvm_phy_ctxt_changed(struct iwm_softc *sc,
struct iwm_mvm_phy_ctxt *ctxt, struct ieee80211_channel *chan,
uint8_t chains_static, uint8_t chains_dynamic);
#endif /* __IF_IWM_PHY_CTXT_H__ */

451
sys/dev/iwm/if_iwm_phy_db.c Normal file
View File

@ -0,0 +1,451 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/endian.h>
#include <sys/firmware.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/rman.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/endian.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_ratectl.h>
#include <net80211/ieee80211_radiotap.h>
#include <if_iwmreg.h>
#include <if_iwmvar.h>
#include <if_iwm_debug.h>
#include <if_iwm_util.h>
#include <if_iwm_phy_db.h>
/*
* BEGIN iwl-phy-db.c
*/
/*
* get phy db section: returns a pointer to a phy db section specified by
* type and channel group id.
*/
static struct iwm_phy_db_entry *
iwm_phy_db_get_section(struct iwm_softc *sc,
enum iwm_phy_db_section_type type, uint16_t chg_id)
{
struct iwm_phy_db *phy_db = &sc->sc_phy_db;
if (type >= IWM_PHY_DB_MAX)
return NULL;
switch (type) {
case IWM_PHY_DB_CFG:
return &phy_db->cfg;
case IWM_PHY_DB_CALIB_NCH:
return &phy_db->calib_nch;
case IWM_PHY_DB_CALIB_CHG_PAPD:
if (chg_id >= IWM_NUM_PAPD_CH_GROUPS)
return NULL;
return &phy_db->calib_ch_group_papd[chg_id];
case IWM_PHY_DB_CALIB_CHG_TXP:
if (chg_id >= IWM_NUM_TXP_CH_GROUPS)
return NULL;
return &phy_db->calib_ch_group_txp[chg_id];
default:
return NULL;
}
return NULL;
}
int
iwm_phy_db_set_section(struct iwm_softc *sc,
struct iwm_calib_res_notif_phy_db *phy_db_notif)
{
enum iwm_phy_db_section_type type = le16toh(phy_db_notif->type);
uint16_t size = le16toh(phy_db_notif->length);
struct iwm_phy_db_entry *entry;
uint16_t chg_id = 0;
if (type == IWM_PHY_DB_CALIB_CHG_PAPD ||
type == IWM_PHY_DB_CALIB_CHG_TXP)
chg_id = le16toh(*(uint16_t *)phy_db_notif->data);
entry = iwm_phy_db_get_section(sc, type, chg_id);
if (!entry)
return EINVAL;
if (entry->data)
free(entry->data, M_DEVBUF);
entry->data = malloc(size, M_DEVBUF, M_NOWAIT);
if (!entry->data) {
entry->size = 0;
return ENOMEM;
}
memcpy(entry->data, phy_db_notif->data, size);
entry->size = size;
IWM_DPRINTF(sc, IWM_DEBUG_RESET,
"%s(%d): [PHYDB]SET: Type %d , Size: %d, data: %p\n",
__func__, __LINE__, type, size, entry->data);
return 0;
}
static int
iwm_is_valid_channel(uint16_t ch_id)
{
if (ch_id <= 14 ||
(36 <= ch_id && ch_id <= 64 && ch_id % 4 == 0) ||
(100 <= ch_id && ch_id <= 140 && ch_id % 4 == 0) ||
(145 <= ch_id && ch_id <= 165 && ch_id % 4 == 1))
return 1;
return 0;
}
static uint8_t
iwm_ch_id_to_ch_index(uint16_t ch_id)
{
if (!iwm_is_valid_channel(ch_id))
return 0xff;
if (ch_id <= 14)
return ch_id - 1;
if (ch_id <= 64)
return (ch_id + 20) / 4;
if (ch_id <= 140)
return (ch_id - 12) / 4;
return (ch_id - 13) / 4;
}
static uint16_t
iwm_channel_id_to_papd(uint16_t ch_id)
{
if (!iwm_is_valid_channel(ch_id))
return 0xff;
if (1 <= ch_id && ch_id <= 14)
return 0;
if (36 <= ch_id && ch_id <= 64)
return 1;
if (100 <= ch_id && ch_id <= 140)
return 2;
return 3;
}
static uint16_t
iwm_channel_id_to_txp(struct iwm_softc *sc, uint16_t ch_id)
{
struct iwm_phy_db *phy_db = &sc->sc_phy_db;
struct iwm_phy_db_chg_txp *txp_chg;
int i;
uint8_t ch_index = iwm_ch_id_to_ch_index(ch_id);
if (ch_index == 0xff)
return 0xff;
for (i = 0; i < IWM_NUM_TXP_CH_GROUPS; i++) {
txp_chg = (void *)phy_db->calib_ch_group_txp[i].data;
if (!txp_chg)
return 0xff;
/*
* Looking for the first channel group that its max channel is
* higher then wanted channel.
*/
if (le16toh(txp_chg->max_channel_idx) >= ch_index)
return i;
}
return 0xff;
}
static int
iwm_phy_db_get_section_data(struct iwm_softc *sc,
uint32_t type, uint8_t **data, uint16_t *size, uint16_t ch_id)
{
struct iwm_phy_db_entry *entry;
uint16_t ch_group_id = 0;
IWM_DPRINTF(sc, IWM_DEBUG_RESET, "->%s\n", __func__);
/* find wanted channel group */
if (type == IWM_PHY_DB_CALIB_CHG_PAPD)
ch_group_id = iwm_channel_id_to_papd(ch_id);
else if (type == IWM_PHY_DB_CALIB_CHG_TXP)
ch_group_id = iwm_channel_id_to_txp(sc, ch_id);
entry = iwm_phy_db_get_section(sc, type, ch_group_id);
if (!entry)
return EINVAL;
*data = entry->data;
*size = entry->size;
IWM_DPRINTF(sc, IWM_DEBUG_RESET,
"%s(%d): [PHYDB] GET: Type %d , Size: %d\n",
__func__, __LINE__, type, *size);
return 0;
}
static int
iwm_send_phy_db_cmd(struct iwm_softc *sc, uint16_t type,
uint16_t length, void *data)
{
struct iwm_phy_db_cmd phy_db_cmd;
struct iwm_host_cmd cmd = {
.id = IWM_PHY_DB_CMD,
.flags = IWM_CMD_SYNC,
};
IWM_DPRINTF(sc, IWM_DEBUG_CMD,
"Sending PHY-DB hcmd of type %d, of length %d\n",
type, length);
/* Set phy db cmd variables */
phy_db_cmd.type = le16toh(type);
phy_db_cmd.length = le16toh(length);
/* Set hcmd variables */
cmd.data[0] = &phy_db_cmd;
cmd.len[0] = sizeof(struct iwm_phy_db_cmd);
cmd.data[1] = data;
cmd.len[1] = length;
cmd.dataflags[1] = IWM_HCMD_DFL_NOCOPY;
return iwm_send_cmd(sc, &cmd);
}
static int
iwm_phy_db_send_all_channel_groups(struct iwm_softc *sc,
enum iwm_phy_db_section_type type, uint8_t max_ch_groups)
{
uint16_t i;
int err;
struct iwm_phy_db_entry *entry;
/* Send all the channel-specific groups to operational fw */
for (i = 0; i < max_ch_groups; i++) {
entry = iwm_phy_db_get_section(sc, type, i);
if (!entry)
return EINVAL;
if (!entry->size)
continue;
/* Send the requested PHY DB section */
err = iwm_send_phy_db_cmd(sc, type, entry->size, entry->data);
if (err) {
IWM_DPRINTF(sc, IWM_DEBUG_CMD,
"%s: Can't SEND phy_db section %d (%d), "
"err %d\n", __func__, type, i, err);
return err;
}
IWM_DPRINTF(sc, IWM_DEBUG_CMD,
"Sent PHY_DB HCMD, type = %d num = %d\n", type, i);
}
return 0;
}
int
iwm_send_phy_db_data(struct iwm_softc *sc)
{
uint8_t *data = NULL;
uint16_t size = 0;
int err;
IWM_DPRINTF(sc, IWM_DEBUG_CMD | IWM_DEBUG_RESET,
"%s: Sending phy db data and configuration to runtime image\n",
__func__);
/* Send PHY DB CFG section */
err = iwm_phy_db_get_section_data(sc, IWM_PHY_DB_CFG, &data, &size, 0);
if (err) {
IWM_DPRINTF(sc, IWM_DEBUG_CMD | IWM_DEBUG_RESET,
"%s: Cannot get Phy DB cfg section, %d\n",
__func__, err);
return err;
}
err = iwm_send_phy_db_cmd(sc, IWM_PHY_DB_CFG, size, data);
if (err) {
IWM_DPRINTF(sc, IWM_DEBUG_CMD | IWM_DEBUG_RESET,
"%s: Cannot send HCMD of Phy DB cfg section, %d\n",
__func__, err);
return err;
}
err = iwm_phy_db_get_section_data(sc, IWM_PHY_DB_CALIB_NCH,
&data, &size, 0);
if (err) {
IWM_DPRINTF(sc, IWM_DEBUG_CMD | IWM_DEBUG_RESET,
"%s: Cannot get Phy DB non specific channel section, "
"%d\n", __func__, err);
return err;
}
err = iwm_send_phy_db_cmd(sc, IWM_PHY_DB_CALIB_NCH, size, data);
if (err) {
IWM_DPRINTF(sc, IWM_DEBUG_CMD | IWM_DEBUG_RESET,
"%s: Cannot send HCMD of Phy DB non specific channel "
"sect, %d\n", __func__, err);
return err;
}
/* Send all the TXP channel specific data */
err = iwm_phy_db_send_all_channel_groups(sc,
IWM_PHY_DB_CALIB_CHG_PAPD, IWM_NUM_PAPD_CH_GROUPS);
if (err) {
IWM_DPRINTF(sc, IWM_DEBUG_CMD | IWM_DEBUG_RESET,
"%s: Cannot send channel specific PAPD groups, %d\n",
__func__, err);
return err;
}
/* Send all the TXP channel specific data */
err = iwm_phy_db_send_all_channel_groups(sc,
IWM_PHY_DB_CALIB_CHG_TXP, IWM_NUM_TXP_CH_GROUPS);
if (err) {
IWM_DPRINTF(sc, IWM_DEBUG_CMD | IWM_DEBUG_RESET,
"%s: Cannot send channel specific TX power groups, "
"%d\n", __func__, err);
return err;
}
IWM_DPRINTF(sc, IWM_DEBUG_CMD | IWM_DEBUG_RESET,
"%s: Finished sending phy db non channel data\n",
__func__);
return 0;
}

147
sys/dev/iwm/if_iwm_phy_db.h Normal file
View File

@ -0,0 +1,147 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/* $FreeBSD$ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __IF_IWM_PHY_DB_H__
#define __IF_IWM_PHY_DB_H__
enum iwm_phy_db_section_type {
IWM_PHY_DB_CFG = 1,
IWM_PHY_DB_CALIB_NCH,
IWM_PHY_DB_UNUSED,
IWM_PHY_DB_CALIB_CHG_PAPD,
IWM_PHY_DB_CALIB_CHG_TXP,
IWM_PHY_DB_MAX
};
#define IWM_PHY_DB_CMD 0x6c /* TEMP API - The actual is 0x8c */
/*
* phy db - configure operational ucode
*/
struct iwm_phy_db_cmd {
uint16_t type;
uint16_t length;
uint8_t data[];
} __packed;
/* for parsing of tx power channel group data that comes from the firmware*/
struct iwm_phy_db_chg_txp {
uint32_t space;
uint16_t max_channel_idx;
} __packed;
/*
* phy db - Receive phy db chunk after calibrations
*/
struct iwm_calib_res_notif_phy_db {
uint16_t type;
uint16_t length;
uint8_t data[];
} __packed;
extern int iwm_phy_db_set_section(struct iwm_softc *sc,
struct iwm_calib_res_notif_phy_db *phy_db_notif);
extern int iwm_send_phy_db_data(struct iwm_softc *sc);
#endif /* __IF_IWM_PHY_DB_H__ */

370
sys/dev/iwm/if_iwm_power.c Normal file
View File

@ -0,0 +1,370 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/endian.h>
#include <sys/firmware.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/rman.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/endian.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_ratectl.h>
#include <net80211/ieee80211_radiotap.h>
#include <if_iwmreg.h>
#include <if_iwmvar.h>
#include <if_iwm_debug.h>
#include <if_iwm_util.h>
#include <if_iwm_power.h>
/*
* BEGIN mvm/power.c
*/
#define IWM_POWER_KEEP_ALIVE_PERIOD_SEC 25
static int
iwm_mvm_beacon_filter_send_cmd(struct iwm_softc *sc,
struct iwm_beacon_filter_cmd *cmd)
{
int ret;
ret = iwm_mvm_send_cmd_pdu(sc, IWM_REPLY_BEACON_FILTERING_CMD,
IWM_CMD_SYNC, sizeof(struct iwm_beacon_filter_cmd), cmd);
if (!ret) {
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"ba_enable_beacon_abort is: %d\n",
le32toh(cmd->ba_enable_beacon_abort));
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"ba_escape_timer is: %d\n",
le32toh(cmd->ba_escape_timer));
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"bf_debug_flag is: %d\n",
le32toh(cmd->bf_debug_flag));
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"bf_enable_beacon_filter is: %d\n",
le32toh(cmd->bf_enable_beacon_filter));
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"bf_energy_delta is: %d\n",
le32toh(cmd->bf_energy_delta));
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"bf_escape_timer is: %d\n",
le32toh(cmd->bf_escape_timer));
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"bf_roaming_energy_delta is: %d\n",
le32toh(cmd->bf_roaming_energy_delta));
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"bf_roaming_state is: %d\n",
le32toh(cmd->bf_roaming_state));
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"bf_temp_threshold is: %d\n",
le32toh(cmd->bf_temp_threshold));
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"bf_temp_fast_filter is: %d\n",
le32toh(cmd->bf_temp_fast_filter));
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"bf_temp_slow_filter is: %d\n",
le32toh(cmd->bf_temp_slow_filter));
}
return ret;
}
static void
iwm_mvm_beacon_filter_set_cqm_params(struct iwm_softc *sc,
struct iwm_node *in, struct iwm_beacon_filter_cmd *cmd)
{
cmd->ba_enable_beacon_abort = htole32(sc->sc_bf.ba_enabled);
}
static int
iwm_mvm_update_beacon_abort(struct iwm_softc *sc, struct iwm_node *in,
int enable)
{
struct iwm_beacon_filter_cmd cmd = {
IWM_BF_CMD_CONFIG_DEFAULTS,
.bf_enable_beacon_filter = htole32(1),
.ba_enable_beacon_abort = htole32(enable),
};
if (!sc->sc_bf.bf_enabled)
return 0;
sc->sc_bf.ba_enabled = enable;
iwm_mvm_beacon_filter_set_cqm_params(sc, in, &cmd);
return iwm_mvm_beacon_filter_send_cmd(sc, &cmd);
}
static void
iwm_mvm_power_log(struct iwm_softc *sc, struct iwm_mac_power_cmd *cmd)
{
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"Sending power table command on mac id 0x%X for "
"power level %d, flags = 0x%X\n",
cmd->id_and_color, IWM_POWER_SCHEME_CAM, le16toh(cmd->flags));
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"Keep alive = %u sec\n", le16toh(cmd->keep_alive_seconds));
if (!(cmd->flags & htole16(IWM_POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK))) {
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"Disable power management\n");
return;
}
KASSERT(0, ("unhandled power management"));
#if 0
DPRINTF(mvm, "Rx timeout = %u usec\n",
le32_to_cpu(cmd->rx_data_timeout));
DPRINTF(mvm, "Tx timeout = %u usec\n",
le32_to_cpu(cmd->tx_data_timeout));
if (cmd->flags & cpu_to_le16(IWM_POWER_FLAGS_SKIP_OVER_DTIM_MSK))
DPRINTF(mvm, "DTIM periods to skip = %u\n",
cmd->skip_dtim_periods);
if (cmd->flags & cpu_to_le16(IWM_POWER_FLAGS_LPRX_ENA_MSK))
DPRINTF(mvm, "LP RX RSSI threshold = %u\n",
cmd->lprx_rssi_threshold);
if (cmd->flags & cpu_to_le16(IWM_POWER_FLAGS_ADVANCE_PM_ENA_MSK)) {
DPRINTF(mvm, "uAPSD enabled\n");
DPRINTF(mvm, "Rx timeout (uAPSD) = %u usec\n",
le32_to_cpu(cmd->rx_data_timeout_uapsd));
DPRINTF(mvm, "Tx timeout (uAPSD) = %u usec\n",
le32_to_cpu(cmd->tx_data_timeout_uapsd));
DPRINTF(mvm, "QNDP TID = %d\n", cmd->qndp_tid);
DPRINTF(mvm, "ACs flags = 0x%x\n", cmd->uapsd_ac_flags);
DPRINTF(mvm, "Max SP = %d\n", cmd->uapsd_max_sp);
}
#endif
}
static void
iwm_mvm_power_build_cmd(struct iwm_softc *sc, struct iwm_node *in,
struct iwm_mac_power_cmd *cmd)
{
struct ieee80211_node *ni = &in->in_ni;
int dtimper, dtimper_msec;
int keep_alive;
struct ieee80211com *ic = sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
cmd->id_and_color = htole32(IWM_FW_CMD_ID_AND_COLOR(IWM_DEFAULT_MACID,
IWM_DEFAULT_COLOR));
dtimper = vap->iv_dtim_period ?: 1;
/*
* Regardless of power management state the driver must set
* keep alive period. FW will use it for sending keep alive NDPs
* immediately after association. Check that keep alive period
* is at least 3 * DTIM
*/
dtimper_msec = dtimper * ni->ni_intval;
keep_alive
= MAX(3 * dtimper_msec, 1000 * IWM_POWER_KEEP_ALIVE_PERIOD_SEC);
keep_alive = roundup(keep_alive, 1000) / 1000;
cmd->keep_alive_seconds = htole16(keep_alive);
}
int
iwm_mvm_power_mac_update_mode(struct iwm_softc *sc, struct iwm_node *in)
{
int ret;
int ba_enable;
struct iwm_mac_power_cmd cmd;
memset(&cmd, 0, sizeof(cmd));
iwm_mvm_power_build_cmd(sc, in, &cmd);
iwm_mvm_power_log(sc, &cmd);
if ((ret = iwm_mvm_send_cmd_pdu(sc, IWM_MAC_PM_POWER_TABLE,
IWM_CMD_SYNC, sizeof(cmd), &cmd)) != 0)
return ret;
ba_enable = !!(cmd.flags &
htole16(IWM_POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK));
return iwm_mvm_update_beacon_abort(sc, in, ba_enable);
}
int
iwm_mvm_power_update_device(struct iwm_softc *sc)
{
struct iwm_device_power_cmd cmd = {
.flags = htole16(IWM_DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK),
};
if (!(sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_DEVICE_PS_CMD))
return 0;
cmd.flags |= htole16(IWM_DEVICE_POWER_FLAGS_CAM_MSK);
IWM_DPRINTF(sc, IWM_DEBUG_PWRSAVE | IWM_DEBUG_CMD,
"Sending device power command with flags = 0x%X\n", cmd.flags);
return iwm_mvm_send_cmd_pdu(sc,
IWM_POWER_TABLE_CMD, IWM_CMD_SYNC, sizeof(cmd), &cmd);
}
int
iwm_mvm_enable_beacon_filter(struct iwm_softc *sc, struct iwm_node *in)
{
struct iwm_beacon_filter_cmd cmd = {
IWM_BF_CMD_CONFIG_DEFAULTS,
.bf_enable_beacon_filter = htole32(1),
};
int ret;
iwm_mvm_beacon_filter_set_cqm_params(sc, in, &cmd);
ret = iwm_mvm_beacon_filter_send_cmd(sc, &cmd);
if (ret == 0)
sc->sc_bf.bf_enabled = 1;
return ret;
}
int
iwm_mvm_disable_beacon_filter(struct iwm_softc *sc)
{
struct iwm_beacon_filter_cmd cmd;
int ret;
memset(&cmd, 0, sizeof(cmd));
if ((sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_BF_UPDATED) == 0)
return 0;
ret = iwm_mvm_beacon_filter_send_cmd(sc, &cmd);
if (ret == 0)
sc->sc_bf.bf_enabled = 0;
return ret;
}
#if 0
static int
iwm_mvm_update_beacon_filter(struct iwm_softc *sc, struct iwm_node *in)
{
if (!sc->sc_bf.bf_enabled)
return 0;
return iwm_mvm_enable_beacon_filter(sc, in);
}
#endif

100
sys/dev/iwm/if_iwm_power.h Normal file
View File

@ -0,0 +1,100 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/* $FreeBSD$ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __IF_IWM_POWER_H__
#define __IF_IWM_POWER_H__
extern int iwm_mvm_power_mac_update_mode(struct iwm_softc *sc,
struct iwm_node *in);
extern int iwm_mvm_power_update_device(struct iwm_softc *sc);
extern int iwm_mvm_enable_beacon_filter(struct iwm_softc *sc,
struct iwm_node *in);
extern int iwm_mvm_disable_beacon_filter(struct iwm_softc *sc);
#endif /* __IF_IWM_POWER_H__ */

458
sys/dev/iwm/if_iwm_scan.c Normal file
View File

@ -0,0 +1,458 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/endian.h>
#include <sys/firmware.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/rman.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/endian.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_ratectl.h>
#include <net80211/ieee80211_radiotap.h>
#include <if_iwmreg.h>
#include <if_iwmvar.h>
#include <if_iwm_debug.h>
#include <if_iwm_util.h>
#if 0
#include <if_iwm_binding.h>
#include <if_iwm_phy_db.h>
#include <if_iwm_mac_ctxt.h>
#include <if_iwm_phy_ctxt.h>
#include <if_iwm_time_event.h>
#include <if_iwm_power.h>
#include <if_iwm_pcie_trans.h>
#endif
#include <if_iwm_scan.h>
/*
* BEGIN mvm/scan.c
*/
#define IWM_PLCP_QUIET_THRESH 1
#define IWM_ACTIVE_QUIET_TIME 10
#define LONG_OUT_TIME_PERIOD (600 * IEEE80211_DUR_TU)
#define SHORT_OUT_TIME_PERIOD (200 * IEEE80211_DUR_TU)
#define SUSPEND_TIME_PERIOD (100 * IEEE80211_DUR_TU)
static uint16_t
iwm_mvm_scan_rx_chain(struct iwm_softc *sc)
{
uint16_t rx_chain;
uint8_t rx_ant;
rx_ant = IWM_FW_VALID_RX_ANT(sc);
rx_chain = rx_ant << IWM_PHY_RX_CHAIN_VALID_POS;
rx_chain |= rx_ant << IWM_PHY_RX_CHAIN_FORCE_MIMO_SEL_POS;
rx_chain |= rx_ant << IWM_PHY_RX_CHAIN_FORCE_SEL_POS;
rx_chain |= 0x1 << IWM_PHY_RX_CHAIN_DRIVER_FORCE_POS;
return htole16(rx_chain);
}
static uint32_t
iwm_mvm_scan_max_out_time(struct iwm_softc *sc, uint32_t flags, int is_assoc)
{
if (!is_assoc)
return 0;
if (flags & 0x1)
return htole32(SHORT_OUT_TIME_PERIOD);
return htole32(LONG_OUT_TIME_PERIOD);
}
static uint32_t
iwm_mvm_scan_suspend_time(struct iwm_softc *sc, int is_assoc)
{
if (!is_assoc)
return 0;
return htole32(SUSPEND_TIME_PERIOD);
}
static uint32_t
iwm_mvm_scan_rxon_flags(struct iwm_softc *sc, int flags)
{
if (flags & IEEE80211_CHAN_2GHZ)
return htole32(IWM_PHY_BAND_24);
else
return htole32(IWM_PHY_BAND_5);
}
static uint32_t
iwm_mvm_scan_rate_n_flags(struct iwm_softc *sc, int flags, int no_cck)
{
uint32_t tx_ant;
int i, ind;
for (i = 0, ind = sc->sc_scan_last_antenna;
i < IWM_RATE_MCS_ANT_NUM; i++) {
ind = (ind + 1) % IWM_RATE_MCS_ANT_NUM;
if (IWM_FW_VALID_TX_ANT(sc) & (1 << ind)) {
sc->sc_scan_last_antenna = ind;
break;
}
}
tx_ant = (1 << sc->sc_scan_last_antenna) << IWM_RATE_MCS_ANT_POS;
if ((flags & IEEE80211_CHAN_2GHZ) && !no_cck)
return htole32(IWM_RATE_1M_PLCP | IWM_RATE_MCS_CCK_MSK |
tx_ant);
else
return htole32(IWM_RATE_6M_PLCP | tx_ant);
}
/*
* If req->n_ssids > 0, it means we should do an active scan.
* In case of active scan w/o directed scan, we receive a zero-length SSID
* just to notify that this scan is active and not passive.
* In order to notify the FW of the number of SSIDs we wish to scan (including
* the zero-length one), we need to set the corresponding bits in chan->type,
* one for each SSID, and set the active bit (first). If the first SSID is
* already included in the probe template, so we need to set only
* req->n_ssids - 1 bits in addition to the first bit.
*/
static uint16_t
iwm_mvm_get_active_dwell(struct iwm_softc *sc, int flags, int n_ssids)
{
if (flags & IEEE80211_CHAN_2GHZ)
return 30 + 3 * (n_ssids + 1);
return 20 + 2 * (n_ssids + 1);
}
static uint16_t
iwm_mvm_get_passive_dwell(struct iwm_softc *sc, int flags)
{
return (flags & IEEE80211_CHAN_2GHZ) ? 100 + 20 : 100 + 10;
}
static int
iwm_mvm_scan_fill_channels(struct iwm_softc *sc, struct iwm_scan_cmd *cmd,
int flags, int n_ssids, int basic_ssid)
{
struct ieee80211com *ic = sc->sc_ic;
uint16_t passive_dwell = iwm_mvm_get_passive_dwell(sc, flags);
uint16_t active_dwell = iwm_mvm_get_active_dwell(sc, flags, n_ssids);
struct iwm_scan_channel *chan = (struct iwm_scan_channel *)
(cmd->data + le16toh(cmd->tx_cmd.len));
int type = (1 << n_ssids) - 1;
struct ieee80211_channel *c;
int nchan, j;
if (!basic_ssid)
type |= (1 << n_ssids);
for (nchan = j = 0; j < ic->ic_nchans; j++) {
c = &ic->ic_channels[j];
/* For 2GHz, only populate 11b channels */
/* For 5GHz, only populate 11a channels */
/*
* Catch other channels, in case we have 900MHz channels or
* something in the chanlist.
*/
if ((flags & IEEE80211_CHAN_2GHZ) && (! IEEE80211_IS_CHAN_B(c))) {
continue;
} else if ((flags & IEEE80211_CHAN_5GHZ) && (! IEEE80211_IS_CHAN_A(c))) {
continue;
} else {
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_EEPROM,
"%s: skipping channel (freq=%d, ieee=%d, flags=0x%08x)\n",
__func__,
c->ic_freq,
c->ic_ieee,
c->ic_flags);
}
IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_EEPROM,
"Adding channel %d (%d Mhz) to the list\n",
nchan, c->ic_freq);
chan->channel = htole16(ieee80211_mhz2ieee(c->ic_freq, flags));
chan->type = htole32(type);
if (c->ic_flags & IEEE80211_CHAN_PASSIVE)
chan->type &= htole32(~IWM_SCAN_CHANNEL_TYPE_ACTIVE);
chan->active_dwell = htole16(active_dwell);
chan->passive_dwell = htole16(passive_dwell);
chan->iteration_count = htole16(1);
chan++;
nchan++;
}
if (nchan == 0)
device_printf(sc->sc_dev,
"%s: NO CHANNEL!\n", __func__);
return nchan;
}
/*
* Fill in probe request with the following parameters:
* TA is our vif HW address, which mac80211 ensures we have.
* Packet is broadcasted, so this is both SA and DA.
* The probe request IE is made out of two: first comes the most prioritized
* SSID if a directed scan is requested. Second comes whatever extra
* information was given to us as the scan request IE.
*/
static uint16_t
iwm_mvm_fill_probe_req(struct iwm_softc *sc, struct ieee80211_frame *frame,
const uint8_t *ta, int n_ssids, const uint8_t *ssid, int ssid_len,
const uint8_t *ie, int ie_len, int left)
{
uint8_t *pos = NULL;
/* Make sure there is enough space for the probe request,
* two mandatory IEs and the data */
left -= sizeof(*frame);
if (left < 0)
return 0;
frame->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
IEEE80211_FC0_SUBTYPE_PROBE_REQ;
frame->i_fc[1] = IEEE80211_FC1_DIR_NODS;
IEEE80211_ADDR_COPY(frame->i_addr1, ieee80211broadcastaddr);
IEEE80211_ADDR_COPY(frame->i_addr2, ta);
IEEE80211_ADDR_COPY(frame->i_addr3, ieee80211broadcastaddr);
/* for passive scans, no need to fill anything */
if (n_ssids == 0)
return sizeof(*frame);
/* points to the payload of the request */
pos = (uint8_t *)frame + sizeof(*frame);
/* fill in our SSID IE */
left -= ssid_len + 2;
if (left < 0)
return 0;
pos = ieee80211_add_ssid(pos, ssid, ssid_len);
if (ie && ie_len && left >= ie_len) {
memcpy(pos, ie, ie_len);
pos += ie_len;
}
return pos - (uint8_t *)frame;
}
int
iwm_mvm_scan_request(struct iwm_softc *sc, int flags,
int n_ssids, uint8_t *ssid, int ssid_len)
{
struct iwm_host_cmd hcmd = {
.id = IWM_SCAN_REQUEST_CMD,
.len = { 0, },
.data = { sc->sc_scan_cmd, },
.flags = IWM_CMD_SYNC,
.dataflags = { IWM_HCMD_DFL_NOCOPY, },
};
struct iwm_scan_cmd *cmd = sc->sc_scan_cmd;
int is_assoc = 0;
int ret;
uint32_t status;
int basic_ssid =
!(sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_NO_BASIC_SSID);
sc->sc_scanband = flags & (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ);
IWM_DPRINTF(sc, IWM_DEBUG_SCAN,
"Handling ieee80211 scan request\n");
memset(cmd, 0, sc->sc_scan_cmd_len);
cmd->quiet_time = htole16(IWM_ACTIVE_QUIET_TIME);
cmd->quiet_plcp_th = htole16(IWM_PLCP_QUIET_THRESH);
cmd->rxchain_sel_flags = iwm_mvm_scan_rx_chain(sc);
cmd->max_out_time = iwm_mvm_scan_max_out_time(sc, 0, is_assoc);
cmd->suspend_time = iwm_mvm_scan_suspend_time(sc, is_assoc);
cmd->rxon_flags = iwm_mvm_scan_rxon_flags(sc, flags);
cmd->filter_flags = htole32(IWM_MAC_FILTER_ACCEPT_GRP |
IWM_MAC_FILTER_IN_BEACON);
cmd->type = htole32(IWM_SCAN_TYPE_FORCED);
cmd->repeats = htole32(1);
/*
* If the user asked for passive scan, don't change to active scan if
* you see any activity on the channel - remain passive.
*/
if (n_ssids > 0) {
cmd->passive2active = htole16(1);
cmd->scan_flags |= IWM_SCAN_FLAGS_PASSIVE2ACTIVE;
#if 0
if (basic_ssid) {
ssid = req->ssids[0].ssid;
ssid_len = req->ssids[0].ssid_len;
}
#endif
} else {
cmd->passive2active = 0;
cmd->scan_flags &= ~IWM_SCAN_FLAGS_PASSIVE2ACTIVE;
}
cmd->tx_cmd.tx_flags = htole32(IWM_TX_CMD_FLG_SEQ_CTL |
IWM_TX_CMD_FLG_BT_DIS);
cmd->tx_cmd.sta_id = sc->sc_aux_sta.sta_id;
cmd->tx_cmd.life_time = htole32(IWM_TX_CMD_LIFE_TIME_INFINITE);
cmd->tx_cmd.rate_n_flags = iwm_mvm_scan_rate_n_flags(sc, flags, 1/*XXX*/);
cmd->tx_cmd.len = htole16(iwm_mvm_fill_probe_req(sc,
(struct ieee80211_frame *)cmd->data,
sc->sc_bssid, n_ssids, ssid, ssid_len,
NULL, 0, sc->sc_capa_max_probe_len));
cmd->channel_count
= iwm_mvm_scan_fill_channels(sc, cmd, flags, n_ssids, basic_ssid);
cmd->len = htole16(sizeof(struct iwm_scan_cmd) +
le16toh(cmd->tx_cmd.len) +
(cmd->channel_count * sizeof(struct iwm_scan_channel)));
hcmd.len[0] = le16toh(cmd->len);
status = IWM_SCAN_RESPONSE_OK;
ret = iwm_mvm_send_cmd_status(sc, &hcmd, &status);
if (!ret && status == IWM_SCAN_RESPONSE_OK) {
IWM_DPRINTF(sc, IWM_DEBUG_SCAN,
"Scan request was sent successfully\n");
} else {
/*
* If the scan failed, it usually means that the FW was unable
* to allocate the time events. Warn on it, but maybe we
* should try to send the command again with different params.
*/
sc->sc_scanband = 0;
ret = EIO;
}
return ret;
}

113
sys/dev/iwm/if_iwm_scan.h Normal file
View File

@ -0,0 +1,113 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/* $FreeBSD$ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __IF_IWN_SCAN_H__
#define __IF_IWN_SCAN_H__
extern int
iwm_mvm_scan_request(struct iwm_softc *sc, int flags,
int n_ssids, uint8_t *ssid, int ssid_len);
#endif /* __IF_IWN_SCAN_H__ */

View File

@ -0,0 +1,272 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/endian.h>
#include <sys/firmware.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/rman.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/endian.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_ratectl.h>
#include <net80211/ieee80211_radiotap.h>
#include <if_iwmreg.h>
#include <if_iwmvar.h>
#include <if_iwm_debug.h>
#include <if_iwm_util.h>
#include <if_iwm_pcie_trans.h>
#include <if_iwm_time_event.h>
/*
* For the high priority TE use a time event type that has similar priority to
* the FW's action scan priority.
*/
#define IWM_MVM_ROC_TE_TYPE_NORMAL IWM_TE_P2P_DEVICE_DISCOVERABLE
#define IWM_MVM_ROC_TE_TYPE_MGMT_TX IWM_TE_P2P_CLIENT_ASSOC
/* used to convert from time event API v2 to v1 */
#define IWM_TE_V2_DEP_POLICY_MSK (IWM_TE_V2_DEP_OTHER | IWM_TE_V2_DEP_TSF |\
IWM_TE_V2_EVENT_SOCIOPATHIC)
static inline uint16_t
iwm_te_v2_get_notify(uint16_t policy)
{
return le16toh(policy) & IWM_TE_V2_NOTIF_MSK;
}
static inline uint16_t
iwm_te_v2_get_dep_policy(uint16_t policy)
{
return (le16toh(policy) & IWM_TE_V2_DEP_POLICY_MSK) >>
IWM_TE_V2_PLACEMENT_POS;
}
static inline uint16_t
iwm_te_v2_get_absence(uint16_t policy)
{
return (le16toh(policy) & IWM_TE_V2_ABSENCE) >> IWM_TE_V2_ABSENCE_POS;
}
static void
iwm_mvm_te_v2_to_v1(const struct iwm_time_event_cmd_v2 *cmd_v2,
struct iwm_time_event_cmd_v1 *cmd_v1)
{
cmd_v1->id_and_color = cmd_v2->id_and_color;
cmd_v1->action = cmd_v2->action;
cmd_v1->id = cmd_v2->id;
cmd_v1->apply_time = cmd_v2->apply_time;
cmd_v1->max_delay = cmd_v2->max_delay;
cmd_v1->depends_on = cmd_v2->depends_on;
cmd_v1->interval = cmd_v2->interval;
cmd_v1->duration = cmd_v2->duration;
if (cmd_v2->repeat == IWM_TE_V2_REPEAT_ENDLESS)
cmd_v1->repeat = htole32(IWM_TE_V1_REPEAT_ENDLESS);
else
cmd_v1->repeat = htole32(cmd_v2->repeat);
cmd_v1->max_frags = htole32(cmd_v2->max_frags);
cmd_v1->interval_reciprocal = 0; /* unused */
cmd_v1->dep_policy = htole32(iwm_te_v2_get_dep_policy(cmd_v2->policy));
cmd_v1->is_present = htole32(!iwm_te_v2_get_absence(cmd_v2->policy));
cmd_v1->notify = htole32(iwm_te_v2_get_notify(cmd_v2->policy));
}
static int
iwm_mvm_send_time_event_cmd(struct iwm_softc *sc,
const struct iwm_time_event_cmd_v2 *cmd)
{
struct iwm_time_event_cmd_v1 cmd_v1;
if (sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_TIME_EVENT_API_V2)
return iwm_mvm_send_cmd_pdu(sc, IWM_TIME_EVENT_CMD,
IWM_CMD_SYNC, sizeof(*cmd), cmd);
iwm_mvm_te_v2_to_v1(cmd, &cmd_v1);
return iwm_mvm_send_cmd_pdu(sc, IWM_TIME_EVENT_CMD, IWM_CMD_SYNC,
sizeof(cmd_v1), &cmd_v1);
}
static int
iwm_mvm_time_event_send_add(struct iwm_softc *sc, struct iwm_node *in,
void *te_data, struct iwm_time_event_cmd_v2 *te_cmd)
{
int ret;
IWM_DPRINTF(sc, IWM_DEBUG_CMD | IWM_DEBUG_RESET,
"Add new TE, duration %d TU\n", le32toh(te_cmd->duration));
ret = iwm_mvm_send_time_event_cmd(sc, te_cmd);
if (ret) {
IWM_DPRINTF(sc, IWM_DEBUG_CMD | IWM_DEBUG_RESET,
"%s: Couldn't send IWM_TIME_EVENT_CMD: %d\n",
__func__, ret);
}
return ret;
}
void
iwm_mvm_protect_session(struct iwm_softc *sc, struct iwm_node *in,
uint32_t duration, uint32_t min_duration, uint32_t max_delay)
{
struct iwm_time_event_cmd_v2 time_cmd;
memset(&time_cmd, 0, sizeof(time_cmd));
time_cmd.action = htole32(IWM_FW_CTXT_ACTION_ADD);
time_cmd.id_and_color =
htole32(IWM_FW_CMD_ID_AND_COLOR(IWM_DEFAULT_MACID, IWM_DEFAULT_COLOR));
time_cmd.id = htole32(IWM_TE_BSS_STA_AGGRESSIVE_ASSOC);
time_cmd.apply_time = htole32(iwm_read_prph(sc,
IWM_DEVICE_SYSTEM_TIME_REG));
time_cmd.max_frags = IWM_TE_V2_FRAG_NONE;
time_cmd.max_delay = htole32(max_delay);
/* TODO: why do we need to interval = bi if it is not periodic? */
time_cmd.interval = htole32(1);
time_cmd.duration = htole32(duration);
time_cmd.repeat = 1;
time_cmd.policy
= htole32(IWM_TE_V2_NOTIF_HOST_EVENT_START |
IWM_TE_V2_NOTIF_HOST_EVENT_END);
iwm_mvm_time_event_send_add(sc, in, /*te_data*/NULL, &time_cmd);
}

View File

@ -0,0 +1,113 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/* $FreeBSD$ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __IF_IWM_TIME_EVENT_H__
#define __IF_IWM_TIME_EVENT_H__
extern void iwm_mvm_protect_session(struct iwm_softc *sc, struct iwm_node *in,
uint32_t duration, uint32_t min_duration, uint32_t max_delay);
#endif /* __IF_IWM_TIME_EVENT_H__ */

405
sys/dev/iwm/if_iwm_util.c Normal file
View File

@ -0,0 +1,405 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/endian.h>
#include <sys/firmware.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/rman.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/endian.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_ratectl.h>
#include <net80211/ieee80211_radiotap.h>
#include <if_iwmreg.h>
#include <if_iwmvar.h>
#include <if_iwm_debug.h>
#include <if_iwm_binding.h>
#include <if_iwm_util.h>
#include <if_iwm_pcie_trans.h>
static void
iwm_dma_map_mem(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
{
if (error != 0)
return;
KASSERT(nsegs <= 2, ("too many DMA segments, %d should be <= 2",
nsegs));
if (nsegs > 1)
KASSERT(segs[1].ds_addr == segs[0].ds_addr + segs[0].ds_size,
("fragmented DMA memory"));
*(bus_addr_t *)arg = segs[0].ds_addr;
}
/*
* Send a command to the firmware. We try to implement the Linux
* driver interface for the routine.
* mostly from if_iwn (iwn_cmd()).
*
* For now, we always copy the first part and map the second one (if it exists).
*/
int
iwm_send_cmd(struct iwm_softc *sc, struct iwm_host_cmd *hcmd)
{
struct iwm_tx_ring *ring = &sc->txq[IWM_MVM_CMD_QUEUE];
struct iwm_tfd *desc;
struct iwm_tx_data *data;
struct iwm_device_cmd *cmd = NULL;
bus_addr_t paddr;
uint32_t addr_lo;
int error = 0, i, paylen, off;
int code;
int async, wantresp;
code = hcmd->id;
async = hcmd->flags & IWM_CMD_ASYNC;
wantresp = hcmd->flags & IWM_CMD_WANT_SKB;
for (i = 0, paylen = 0; i < nitems(hcmd->len); i++) {
paylen += hcmd->len[i];
}
/* if the command wants an answer, busy sc_cmd_resp */
if (wantresp) {
KASSERT(!async, ("invalid async parameter"));
while (sc->sc_wantresp != -1)
msleep(&sc->sc_wantresp, &sc->sc_mtx, 0, "iwmcmdsl", 0);
sc->sc_wantresp = ring->qid << 16 | ring->cur;
IWM_DPRINTF(sc, IWM_DEBUG_CMD,
"wantresp is %x\n", sc->sc_wantresp);
}
/*
* Is the hardware still available? (after e.g. above wait).
*/
if (sc->sc_flags & IWM_FLAG_STOPPED) {
error = ENXIO;
goto out;
}
desc = &ring->desc[ring->cur];
data = &ring->data[ring->cur];
if (paylen > sizeof(cmd->data)) {
IWM_DPRINTF(sc, IWM_DEBUG_CMD,
"large command paylen=%u len0=%u\n",
paylen, hcmd->len[0]);
/* Command is too large */
if (sizeof(cmd->hdr) + paylen > IWM_RBUF_SIZE) {
error = EINVAL;
goto out;
}
error = bus_dmamem_alloc(ring->data_dmat, (void **)&cmd,
BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &data->map);
if (error != 0)
goto out;
error = bus_dmamap_load(ring->data_dmat, data->map,
cmd, paylen + sizeof(cmd->hdr), iwm_dma_map_mem,
&paddr, BUS_DMA_NOWAIT);
if (error != 0)
goto out;
} else {
cmd = &ring->cmd[ring->cur];
paddr = data->cmd_paddr;
}
cmd->hdr.code = code;
cmd->hdr.flags = 0;
cmd->hdr.qid = ring->qid;
cmd->hdr.idx = ring->cur;
for (i = 0, off = 0; i < nitems(hcmd->data); i++) {
if (hcmd->len[i] == 0)
continue;
memcpy(cmd->data + off, hcmd->data[i], hcmd->len[i]);
off += hcmd->len[i];
}
KASSERT(off == paylen, ("off %d != paylen %d", off, paylen));
/* lo field is not aligned */
addr_lo = htole32((uint32_t)paddr);
memcpy(&desc->tbs[0].lo, &addr_lo, sizeof(uint32_t));
desc->tbs[0].hi_n_len = htole16(iwm_get_dma_hi_addr(paddr)
| ((sizeof(cmd->hdr) + paylen) << 4));
desc->num_tbs = 1;
IWM_DPRINTF(sc, IWM_DEBUG_CMD,
"%s: iwm_send_cmd 0x%x size=%lu %s\n",
__func__,
code,
(unsigned long) (hcmd->len[0] + hcmd->len[1] + sizeof(cmd->hdr)),
async ? " (async)" : "");
if (hcmd->len[0] > sizeof(cmd->data)) {
bus_dmamap_sync(ring->data_dmat, data->map,
BUS_DMASYNC_PREWRITE);
} else {
bus_dmamap_sync(ring->cmd_dma.tag, ring->cmd_dma.map,
BUS_DMASYNC_PREWRITE);
}
bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map,
BUS_DMASYNC_PREWRITE);
IWM_SETBITS(sc, IWM_CSR_GP_CNTRL,
IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
if (!iwm_poll_bit(sc, IWM_CSR_GP_CNTRL,
IWM_CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
(IWM_CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
IWM_CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000)) {
device_printf(sc->sc_dev,
"%s: acquiring device failed\n", __func__);
error = EBUSY;
goto out;
}
#if 0
iwm_update_sched(sc, ring->qid, ring->cur, 0, 0);
#endif
IWM_DPRINTF(sc, IWM_DEBUG_CMD,
"sending command 0x%x qid %d, idx %d\n",
code, ring->qid, ring->cur);
/* Kick command ring. */
ring->cur = (ring->cur + 1) % IWM_TX_RING_COUNT;
IWM_WRITE(sc, IWM_HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur);
if (!async) {
/* m..m-mmyy-mmyyyy-mym-ym m-my generation */
int generation = sc->sc_generation;
error = msleep(desc, &sc->sc_mtx, PCATCH, "iwmcmd", hz);
if (error == 0) {
/* if hardware is no longer up, return error */
if (generation != sc->sc_generation) {
error = ENXIO;
} else {
hcmd->resp_pkt = (void *)sc->sc_cmd_resp;
}
}
}
out:
if (cmd && paylen > sizeof(cmd->data))
bus_dmamem_free(ring->data_dmat, cmd, data->map);
if (wantresp && error != 0) {
iwm_free_resp(sc, hcmd);
}
return error;
}
/* iwlwifi: mvm/utils.c */
int
iwm_mvm_send_cmd_pdu(struct iwm_softc *sc, uint8_t id,
uint32_t flags, uint16_t len, const void *data)
{
struct iwm_host_cmd cmd = {
.id = id,
.len = { len, },
.data = { data, },
.flags = flags,
};
return iwm_send_cmd(sc, &cmd);
}
/* iwlwifi: mvm/utils.c */
int
iwm_mvm_send_cmd_status(struct iwm_softc *sc,
struct iwm_host_cmd *cmd, uint32_t *status)
{
struct iwm_rx_packet *pkt;
struct iwm_cmd_response *resp;
int error, resp_len;
KASSERT((cmd->flags & IWM_CMD_WANT_SKB) == 0,
("invalid command"));
cmd->flags |= IWM_CMD_SYNC | IWM_CMD_WANT_SKB;
if ((error = iwm_send_cmd(sc, cmd)) != 0)
return error;
pkt = cmd->resp_pkt;
/* Can happen if RFKILL is asserted */
if (!pkt) {
error = 0;
goto out_free_resp;
}
if (pkt->hdr.flags & IWM_CMD_FAILED_MSK) {
error = EIO;
goto out_free_resp;
}
resp_len = iwm_rx_packet_payload_len(pkt);
if (resp_len != sizeof(*resp)) {
error = EIO;
goto out_free_resp;
}
resp = (void *)pkt->data;
*status = le32toh(resp->status);
out_free_resp:
iwm_free_resp(sc, cmd);
return error;
}
/* iwlwifi/mvm/utils.c */
int
iwm_mvm_send_cmd_pdu_status(struct iwm_softc *sc, uint8_t id,
uint16_t len, const void *data, uint32_t *status)
{
struct iwm_host_cmd cmd = {
.id = id,
.len = { len, },
.data = { data, },
};
return iwm_mvm_send_cmd_status(sc, &cmd, status);
}
void
iwm_free_resp(struct iwm_softc *sc, struct iwm_host_cmd *hcmd)
{
KASSERT(sc->sc_wantresp != -1, ("already freed"));
KASSERT((hcmd->flags & (IWM_CMD_WANT_SKB|IWM_CMD_SYNC))
== (IWM_CMD_WANT_SKB|IWM_CMD_SYNC), ("invalid flags"));
sc->sc_wantresp = -1;
wakeup(&sc->sc_wantresp);
}

119
sys/dev/iwm/if_iwm_util.h Normal file
View File

@ -0,0 +1,119 @@
/* $OpenBSD: if_iwm.c,v 1.39 2015/03/23 00:35:19 jsg Exp $ */
/* $FreeBSD$ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __IF_IWM_UTIL_H__
#define __IF_IWM_UTIL_H__
extern int iwm_send_cmd(struct iwm_softc *sc, struct iwm_host_cmd *hcmd);
extern int iwm_mvm_send_cmd_pdu(struct iwm_softc *sc, uint8_t id,
uint32_t flags, uint16_t len, const void *data);
extern int iwm_mvm_send_cmd_status(struct iwm_softc *sc,
struct iwm_host_cmd *cmd, uint32_t *status);
extern int iwm_mvm_send_cmd_pdu_status(struct iwm_softc *sc, uint8_t id,
uint16_t len, const void *data, uint32_t *status);
extern void iwm_free_resp(struct iwm_softc *sc, struct iwm_host_cmd *hcmd);
#endif /* __IF_IWM_UTIL_H__ */

5320
sys/dev/iwm/if_iwmreg.h Normal file

File diff suppressed because it is too large Load Diff

534
sys/dev/iwm/if_iwmvar.h Normal file
View File

@ -0,0 +1,534 @@
/* $OpenBSD: if_iwmvar.h,v 1.7 2015/03/02 13:51:10 jsg Exp $ */
/* $FreeBSD$ */
/*
* Copyright (c) 2014 genua mbh <info@genua.de>
* Copyright (c) 2014 Fixup Software Ltd.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*-
* Based on BSD-licensed source modules in the Linux iwlwifi driver,
* which were used as the reference documentation for this implementation.
*
* Driver version we are currently based off of is
* Linux 3.14.3 (tag id a2df521e42b1d9a23f620ac79dbfe8655a8391dd)
*
***********************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
struct iwm_rx_radiotap_header {
struct ieee80211_radiotap_header wr_ihdr;
uint64_t wr_tsft;
uint8_t wr_flags;
uint8_t wr_rate;
uint16_t wr_chan_freq;
uint16_t wr_chan_flags;
int8_t wr_dbm_antsignal;
int8_t wr_dbm_antnoise;
} __packed;
#define IWM_RX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_TSFT) | \
(1 << IEEE80211_RADIOTAP_FLAGS) | \
(1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_CHANNEL) | \
(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \
(1 << IEEE80211_RADIOTAP_DBM_ANTNOISE))
struct iwm_tx_radiotap_header {
struct ieee80211_radiotap_header wt_ihdr;
uint8_t wt_flags;
uint8_t wt_rate;
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
uint8_t wt_hwqueue;
} __packed;
#define IWM_TX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
(1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_CHANNEL))
#define IWM_UCODE_SECT_MAX 6
#define IWM_FWDMASEGSZ (192*1024)
/* sanity check value */
#define IWM_FWMAXSIZE (2*1024*1024)
/*
* fw_status is used to determine if we've already parsed the firmware file
*
* In addition to the following, status < 0 ==> -error
*/
#define IWM_FW_STATUS_NONE 0
#define IWM_FW_STATUS_INPROGRESS 1
#define IWM_FW_STATUS_DONE 2
#define IWM_LOCK(_sc) mtx_lock(&sc->sc_mtx)
#define IWM_UNLOCK(_sc) mtx_unlock(&sc->sc_mtx)
enum iwm_ucode_type {
IWM_UCODE_TYPE_INIT,
IWM_UCODE_TYPE_REGULAR,
IWM_UCODE_TYPE_WOW,
IWM_UCODE_TYPE_MAX
};
struct iwm_fw_info {
const void *fw_rawdata;
size_t fw_rawsize;
int fw_status;
struct iwm_fw_sects {
struct iwm_fw_onesect {
const void *fws_data;
uint32_t fws_len;
uint32_t fws_devoff;
} fw_sect[IWM_UCODE_SECT_MAX];
size_t fw_totlen;
int fw_count;
} fw_sects[IWM_UCODE_TYPE_MAX];
};
struct iwm_nvm_data {
int n_hw_addrs;
uint8_t hw_addr[IEEE80211_ADDR_LEN];
uint8_t calib_version;
uint16_t calib_voltage;
uint16_t raw_temperature;
uint16_t kelvin_temperature;
uint16_t kelvin_voltage;
uint16_t xtal_calib[2];
int sku_cap_band_24GHz_enable;
int sku_cap_band_52GHz_enable;
int sku_cap_11n_enable;
int sku_cap_amt_enable;
int sku_cap_ipan_enable;
uint8_t radio_cfg_type;
uint8_t radio_cfg_step;
uint8_t radio_cfg_dash;
uint8_t radio_cfg_pnum;
uint8_t valid_tx_ant, valid_rx_ant;
uint16_t nvm_version;
uint8_t max_tx_pwr_half_dbm;
};
/* max bufs per tfd the driver will use */
#define IWM_MAX_CMD_TBS_PER_TFD 2
struct iwm_rx_packet;
struct iwm_host_cmd {
const void *data[IWM_MAX_CMD_TBS_PER_TFD];
struct iwm_rx_packet *resp_pkt;
unsigned long _rx_page_addr;
uint32_t _rx_page_order;
int handler_status;
uint32_t flags;
uint16_t len[IWM_MAX_CMD_TBS_PER_TFD];
uint8_t dataflags[IWM_MAX_CMD_TBS_PER_TFD];
uint8_t id;
};
/*
* DMA glue is from iwn
*/
typedef caddr_t iwm_caddr_t;
typedef void *iwm_hookarg_t;
struct iwm_dma_info {
bus_dma_tag_t tag;
bus_dmamap_t map;
bus_dma_segment_t seg;
bus_addr_t paddr;
void *vaddr;
bus_size_t size;
};
#define IWM_TX_RING_COUNT 256
#define IWM_TX_RING_LOMARK 192
#define IWM_TX_RING_HIMARK 224
struct iwm_tx_data {
bus_dmamap_t map;
bus_addr_t cmd_paddr;
bus_addr_t scratch_paddr;
struct mbuf *m;
struct iwm_node *in;
int done;
};
struct iwm_tx_ring {
struct iwm_dma_info desc_dma;
struct iwm_dma_info cmd_dma;
struct iwm_tfd *desc;
struct iwm_device_cmd *cmd;
bus_dma_tag_t data_dmat;
struct iwm_tx_data data[IWM_TX_RING_COUNT];
int qid;
int queued;
int cur;
};
#define IWM_RX_RING_COUNT 256
#define IWM_RBUF_COUNT (IWM_RX_RING_COUNT + 32)
/* Linux driver optionally uses 8k buffer */
#define IWM_RBUF_SIZE 4096
#define IWM_MAX_SCATTER 20
struct iwm_softc;
struct iwm_rbuf {
struct iwm_softc *sc;
void *vaddr;
bus_addr_t paddr;
};
struct iwm_rx_data {
struct mbuf *m;
bus_dmamap_t map;
int wantresp;
};
struct iwm_rx_ring {
struct iwm_dma_info desc_dma;
struct iwm_dma_info stat_dma;
struct iwm_dma_info buf_dma;
uint32_t *desc;
struct iwm_rb_status *stat;
struct iwm_rx_data data[IWM_RX_RING_COUNT];
bus_dma_tag_t data_dmat;
int cur;
};
#define IWM_FLAG_USE_ICT 0x01
#define IWM_FLAG_HW_INITED 0x02
#define IWM_FLAG_STOPPED 0x04
#define IWM_FLAG_RFKILL 0x08
#define IWM_FLAG_BUSY 0x10
struct iwm_ucode_status {
uint32_t uc_error_event_table;
uint32_t uc_log_event_table;
int uc_ok;
int uc_intr;
};
#define IWM_CMD_RESP_MAX PAGE_SIZE
#define IWM_OTP_LOW_IMAGE_SIZE 2048
#define IWM_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS 500
#define IWM_MVM_TE_SESSION_PROTECTION_MIN_TIME_MS 400
/*
* Command headers are in iwl-trans.h, which is full of all
* kinds of other junk, so we just replicate the structures here.
* First the software bits:
*/
enum IWM_CMD_MODE {
IWM_CMD_SYNC = 0,
IWM_CMD_ASYNC = (1 << 0),
IWM_CMD_WANT_SKB = (1 << 1),
IWM_CMD_SEND_IN_RFKILL = (1 << 2),
};
enum iwm_hcmd_dataflag {
IWM_HCMD_DFL_NOCOPY = (1 << 0),
IWM_HCMD_DFL_DUP = (1 << 1),
};
/*
* iwlwifi/iwl-phy-db
*/
#define IWM_NUM_PAPD_CH_GROUPS 4
#define IWM_NUM_TXP_CH_GROUPS 9
struct iwm_phy_db_entry {
uint16_t size;
uint8_t *data;
};
struct iwm_phy_db {
struct iwm_phy_db_entry cfg;
struct iwm_phy_db_entry calib_nch;
struct iwm_phy_db_entry calib_ch_group_papd[IWM_NUM_PAPD_CH_GROUPS];
struct iwm_phy_db_entry calib_ch_group_txp[IWM_NUM_TXP_CH_GROUPS];
};
struct iwm_int_sta {
uint32_t sta_id;
uint32_t tfd_queue_msk;
};
struct iwm_mvm_phy_ctxt {
uint16_t id;
uint16_t color;
uint32_t ref;
struct ieee80211_channel *channel;
};
struct iwm_bf_data {
int bf_enabled; /* filtering */
int ba_enabled; /* abort */
int ave_beacon_signal;
int last_cqm_event;
};
struct iwm_vap {
struct ieee80211vap iv_vap;
uint8_t macaddr[IEEE80211_ADDR_LEN];
int is_uploaded;
int (*iv_newstate)(struct ieee80211vap *, enum ieee80211_state, int);
};
#define IWM_VAP(_vap) ((struct iwm_vap *)(_vap))
struct iwm_softc {
struct ifnet *sc_ifp;
device_t sc_dev;
struct ieee80211com *sc_ic;
int sc_newstate_pending;
uint8_t sc_bssid[IEEE80211_ADDR_LEN];
struct intr_config_hook sc_preinit_hook;
struct mtx sc_mtx;
struct callout sc_watchdog_to;
struct task init_task;
struct resource *sc_irq;
struct resource *sc_mem;
bus_space_tag_t sc_st;
bus_space_handle_t sc_sh;
bus_size_t sc_sz;
bus_dma_tag_t sc_dmat;
void *sc_ih;
/* TX scheduler rings. */
struct iwm_dma_info sched_dma;
uint32_t sched_base;
/* TX/RX rings. */
struct iwm_tx_ring txq[IWM_MVM_MAX_QUEUES];
struct iwm_rx_ring rxq;
int qfullmsk;
int sc_sf_state;
/* ICT table. */
struct iwm_dma_info ict_dma;
int ict_cur;
int sc_hw_rev;
int sc_hw_id;
struct iwm_dma_info kw_dma;
struct iwm_dma_info fw_dma;
int sc_fw_chunk_done;
int sc_init_complete;
struct iwm_ucode_status sc_uc;
enum iwm_ucode_type sc_uc_current;
int sc_fwver;
int sc_capaflags;
int sc_capa_max_probe_len;
int sc_intmask;
int sc_flags;
uint32_t sc_debug;
/*
* So why do we need a separate stopped flag and a generation?
* the former protects the device from issueing commands when it's
* stopped (duh). The latter protects against race from a very
* fast stop/unstop cycle where threads waiting for responses do
* not have a chance to run in between. Notably: we want to stop
* the device from interrupt context when it craps out, so we
* don't have the luxury of waiting for quiescense.
*/
int sc_generation;
const char *sc_fwname;
bus_size_t sc_fwdmasegsz;
struct iwm_fw_info sc_fw;
int sc_fw_phy_config;
struct iwm_tlv_calib_ctrl sc_default_calib[IWM_UCODE_TYPE_MAX];
struct iwm_nvm_data sc_nvm;
struct iwm_phy_db sc_phy_db;
struct iwm_bf_data sc_bf;
int sc_tx_timer;
struct iwm_scan_cmd *sc_scan_cmd;
size_t sc_scan_cmd_len;
int sc_scan_last_antenna;
int sc_scanband;
int sc_auth_prot;
int sc_fixed_ridx;
int sc_staid;
int sc_nodecolor;
uint8_t sc_cmd_resp[IWM_CMD_RESP_MAX];
int sc_wantresp;
struct taskqueue *sc_tq;
struct task sc_es_task;
struct iwm_rx_phy_info sc_last_phy_info;
int sc_ampdu_ref;
struct iwm_int_sta sc_aux_sta;
/* phy contexts. we only use the first one */
struct iwm_mvm_phy_ctxt sc_phyctxt[IWM_NUM_PHY_CTX];
struct iwm_notif_statistics sc_stats;
int sc_noise;
int host_interrupt_operation_mode;
caddr_t sc_drvbpf;
union {
struct iwm_rx_radiotap_header th;
uint8_t pad[IEEE80211_RADIOTAP_HDRLEN];
} sc_rxtapu;
#define sc_rxtap sc_rxtapu.th
int sc_rxtap_len;
union {
struct iwm_tx_radiotap_header th;
uint8_t pad[IEEE80211_RADIOTAP_HDRLEN];
} sc_txtapu;
#define sc_txtap sc_txtapu.th
int sc_txtap_len;
int sc_max_rssi;
};
#define IWM_DEFAULT_MACID 0
#define IWM_DEFAULT_COLOR 0
#define IWM_DEFAULT_TSFID 0
struct iwm_node {
struct ieee80211_node in_ni;
struct iwm_mvm_phy_ctxt *in_phyctxt;
/* status "bits" */
int in_assoc;
struct iwm_lq_cmd in_lq;
uint8_t in_ridx[IEEE80211_RATE_MAXSIZE];
};
#define IWM_STATION_ID 0
#define IWM_ICT_SIZE 4096
#define IWM_ICT_COUNT (IWM_ICT_SIZE / sizeof (uint32_t))
#define IWM_ICT_PADDR_SHIFT 12

17
sys/modules/iwm/Makefile Normal file
View File

@ -0,0 +1,17 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../dev/iwm
KMOD= if_iwm
# Main driver
SRCS= if_iwm.c if_iwm_binding.c if_iwm_util.c if_iwm_phy_db.c
SRCS+= if_iwm_mac_ctxt.c if_iwm_phy_ctxt.c if_iwm_time_event.c
SRCS+= if_iwm_power.c if_iwm_scan.c
# bus layer
SRCS+= if_iwm_pcie_trans.c
SRCS+= device_if.h bus_if.h pci_if.h opt_wlan.h
CFLAGS+= -DIWM_DEBUG -I${.CURDIR}/../../dev/iwm
.include <bsd.kmod.mk>

View File

@ -0,0 +1,5 @@
# $FreeBSD$
SUBDIR= iwm3160fw iwm7260fw iwm7265fw
.include <bsd.subdir.mk>

View File

@ -0,0 +1,18 @@
# $FreeBSD$
#
# Common rules for building firmware. Note this gets auto-included
# by the subdir Makefile's as a consequence of included bsd.kmod.mk.
_FIRM= ${IMG}.fw
CLEANFILES+= ${_FIRM}
FIRMWS= ${_FIRM}:${KMOD}
#
# Note that a license ack is not needed for iwn.
#
#FIRMWARE_LICENSE=
${_FIRM}: ${.CURDIR}/${_FIRM}.uu
uudecode -p $? > ${.TARGET}

View File

@ -0,0 +1,6 @@
# $FreeBSD$
KMOD= iwm3160fw
IMG= iwm-3160-9
.include <bsd.kmod.mk>

View File

@ -0,0 +1,6 @@
# $FreeBSD$
KMOD= iwm7260fw
IMG= iwm-7260-9
.include <bsd.kmod.mk>

View File

@ -0,0 +1,6 @@
# $FreeBSD$
KMOD= iwm7265fw
IMG= iwm-7265-9
.include <bsd.kmod.mk>