102cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos/******************************************************************************
202cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
302cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos  Copyright(c) 2005 Intel Corporation. All rights reserved.
402cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
502cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos  This program is free software; you can redistribute it and/or modify it
602cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos  under the terms of version 2 of the GNU General Public License as
702cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos  published by the Free Software Foundation.
802cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
902cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos  This program is distributed in the hope that it will be useful, but WITHOUT
1002cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1102cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
1202cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos  more details.
1302cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
1402cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos  You should have received a copy of the GNU General Public License along with
1502cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos  this program; if not, write to the Free Software Foundation, Inc., 59
1602cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
1702cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
1802cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos  The full GNU General Public License is included in this distribution in the
1902cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos  file called LICENSE.
2002cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
2102cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos  Contact Information:
22c1eb2c82e5ccc9b691f737c3150e746c9af3ffabReinette Chatre  Intel Linux Wireless <ilw@linux.intel.com>
2302cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
2402cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
2502cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos******************************************************************************/
2602cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos#include <linux/compiler.h>
2702cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos#include <linux/errno.h>
2802cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos#include <linux/if_arp.h>
2902cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos#include <linux/in6.h>
3002cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos#include <linux/in.h>
3102cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos#include <linux/ip.h>
3202cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos#include <linux/kernel.h>
3302cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos#include <linux/module.h>
3402cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos#include <linux/netdevice.h>
3502cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos#include <linux/proc_fs.h>
3602cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos#include <linux/skbuff.h>
3702cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos#include <linux/tcp.h>
3802cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos#include <linux/types.h>
3902cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos#include <linux/wireless.h>
4002cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos#include <linux/etherdevice.h>
4102cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos#include <asm/uaccess.h>
4202cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
43b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linville#include "libipw.h"
4402cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
45b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linvilleint libipw_is_valid_channel(struct libipw_device *ieee, u8 channel)
4602cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos{
4702cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos	int i;
4802cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
4902cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos	/* Driver needs to initialize the geography map before using
5002cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos	 * these helper functions */
5107981aa43f6aec32b875f360755ed3d14f9d5139Pete Zaitcev	if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0)
5207981aa43f6aec32b875f360755ed3d14f9d5139Pete Zaitcev		return 0;
5302cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
54b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linville	if (ieee->freq_band & LIBIPW_24GHZ_BAND)
5502cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos		for (i = 0; i < ieee->geo.bg_channels; i++)
5602cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos			/* NOTE: If G mode is currently supported but
5702cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos			 * this is a B only channel, we don't see it
5802cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos			 * as valid. */
5902cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos			if ((ieee->geo.bg[i].channel == channel) &&
60b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linville			    !(ieee->geo.bg[i].flags & LIBIPW_CH_INVALID) &&
6102cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos			    (!(ieee->mode & IEEE_G) ||
62b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linville			     !(ieee->geo.bg[i].flags & LIBIPW_CH_B_ONLY)))
63b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linville				return LIBIPW_24GHZ_BAND;
6402cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
65b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linville	if (ieee->freq_band & LIBIPW_52GHZ_BAND)
6602cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos		for (i = 0; i < ieee->geo.a_channels; i++)
67d128f6c176bff9c4929476e13132804321a6d5c5Zhu Yi			if ((ieee->geo.a[i].channel == channel) &&
68b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linville			    !(ieee->geo.a[i].flags & LIBIPW_CH_INVALID))
69b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linville				return LIBIPW_52GHZ_BAND;
7002cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
7102cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos	return 0;
7202cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos}
7302cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
74b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linvilleint libipw_channel_to_index(struct libipw_device *ieee, u8 channel)
7502cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos{
7602cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos	int i;
7702cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
7802cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos	/* Driver needs to initialize the geography map before using
7902cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos	 * these helper functions */
8007981aa43f6aec32b875f360755ed3d14f9d5139Pete Zaitcev	if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0)
8107981aa43f6aec32b875f360755ed3d14f9d5139Pete Zaitcev		return -1;
8202cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
83b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linville	if (ieee->freq_band & LIBIPW_24GHZ_BAND)
8402cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos		for (i = 0; i < ieee->geo.bg_channels; i++)
8502cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos			if (ieee->geo.bg[i].channel == channel)
8602cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos				return i;
8702cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
88b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linville	if (ieee->freq_band & LIBIPW_52GHZ_BAND)
8902cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos		for (i = 0; i < ieee->geo.a_channels; i++)
9002cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos			if (ieee->geo.a[i].channel == channel)
9102cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos				return i;
9202cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
9302cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos	return -1;
9402cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos}
9502cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
96b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linvilleu32 libipw_channel_to_freq(struct libipw_device * ieee, u8 channel)
97f5cdf30618cf855c2043e5c0c131ebb120929864Larry Finger{
98b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linville	const struct libipw_channel * ch;
99f5cdf30618cf855c2043e5c0c131ebb120929864Larry Finger
100f5cdf30618cf855c2043e5c0c131ebb120929864Larry Finger	/* Driver needs to initialize the geography map before using
101f5cdf30618cf855c2043e5c0c131ebb120929864Larry Finger	 * these helper functions */
102f5cdf30618cf855c2043e5c0c131ebb120929864Larry Finger	if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0)
103f5cdf30618cf855c2043e5c0c131ebb120929864Larry Finger		return 0;
104f5cdf30618cf855c2043e5c0c131ebb120929864Larry Finger
105b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linville	ch = libipw_get_channel(ieee, channel);
106f5cdf30618cf855c2043e5c0c131ebb120929864Larry Finger	if (!ch->channel)
107f5cdf30618cf855c2043e5c0c131ebb120929864Larry Finger		return 0;
108f5cdf30618cf855c2043e5c0c131ebb120929864Larry Finger	return ch->freq;
109f5cdf30618cf855c2043e5c0c131ebb120929864Larry Finger}
110f5cdf30618cf855c2043e5c0c131ebb120929864Larry Finger
111b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linvilleu8 libipw_freq_to_channel(struct libipw_device * ieee, u32 freq)
11202cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos{
11302cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos	int i;
11402cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
11502cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos	/* Driver needs to initialize the geography map before using
11602cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos	 * these helper functions */
11707981aa43f6aec32b875f360755ed3d14f9d5139Pete Zaitcev	if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0)
11807981aa43f6aec32b875f360755ed3d14f9d5139Pete Zaitcev		return 0;
11902cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
12002cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos	freq /= 100000;
12102cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
122b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linville	if (ieee->freq_band & LIBIPW_24GHZ_BAND)
12302cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos		for (i = 0; i < ieee->geo.bg_channels; i++)
12402cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos			if (ieee->geo.bg[i].freq == freq)
12502cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos				return ieee->geo.bg[i].channel;
12602cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
127b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linville	if (ieee->freq_band & LIBIPW_52GHZ_BAND)
12802cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos		for (i = 0; i < ieee->geo.a_channels; i++)
12902cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos			if (ieee->geo.a[i].freq == freq)
13002cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos				return ieee->geo.a[i].channel;
13102cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
13202cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos	return 0;
13302cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos}
13402cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
135b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linvilleint libipw_set_geo(struct libipw_device *ieee,
136b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linville		      const struct libipw_geo *geo)
13702cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos{
13802cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos	memcpy(ieee->geo.name, geo->name, 3);
13902cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos	ieee->geo.name[3] = '\0';
14002cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos	ieee->geo.bg_channels = geo->bg_channels;
14102cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos	ieee->geo.a_channels = geo->a_channels;
14202cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos	memcpy(ieee->geo.bg, geo->bg, geo->bg_channels *
143b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linville	       sizeof(struct libipw_channel));
14402cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos	memcpy(ieee->geo.a, geo->a, ieee->geo.a_channels *
145b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linville	       sizeof(struct libipw_channel));
14602cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos	return 0;
14702cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos}
14802cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
149b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linvilleconst struct libipw_geo *libipw_get_geo(struct libipw_device *ieee)
15002cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos{
15102cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos	return &ieee->geo;
15202cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos}
15302cda6ae01814f58422c45259fb48136fbd7bcc1James Ketrenos
154b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linvilleu8 libipw_get_channel_flags(struct libipw_device * ieee, u8 channel)
155d128f6c176bff9c4929476e13132804321a6d5c5Zhu Yi{
156b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linville	int index = libipw_channel_to_index(ieee, channel);
157d128f6c176bff9c4929476e13132804321a6d5c5Zhu Yi
158d128f6c176bff9c4929476e13132804321a6d5c5Zhu Yi	if (index == -1)
159b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linville		return LIBIPW_CH_INVALID;
160d128f6c176bff9c4929476e13132804321a6d5c5Zhu Yi
161b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linville	if (channel <= LIBIPW_24GHZ_CHANNELS)
162d128f6c176bff9c4929476e13132804321a6d5c5Zhu Yi		return ieee->geo.bg[index].flags;
163d128f6c176bff9c4929476e13132804321a6d5c5Zhu Yi
164d128f6c176bff9c4929476e13132804321a6d5c5Zhu Yi	return ieee->geo.a[index].flags;
165d128f6c176bff9c4929476e13132804321a6d5c5Zhu Yi}
166d128f6c176bff9c4929476e13132804321a6d5c5Zhu Yi
167b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linvillestatic const struct libipw_channel bad_channel = {
168d128f6c176bff9c4929476e13132804321a6d5c5Zhu Yi	.channel = 0,
169b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linville	.flags = LIBIPW_CH_INVALID,
170d128f6c176bff9c4929476e13132804321a6d5c5Zhu Yi	.max_power = 0,
171d128f6c176bff9c4929476e13132804321a6d5c5Zhu Yi};
172d128f6c176bff9c4929476e13132804321a6d5c5Zhu Yi
173b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linvilleconst struct libipw_channel *libipw_get_channel(struct libipw_device
174d128f6c176bff9c4929476e13132804321a6d5c5Zhu Yi						      *ieee, u8 channel)
175d128f6c176bff9c4929476e13132804321a6d5c5Zhu Yi{
176b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linville	int index = libipw_channel_to_index(ieee, channel);
177d128f6c176bff9c4929476e13132804321a6d5c5Zhu Yi
178d128f6c176bff9c4929476e13132804321a6d5c5Zhu Yi	if (index == -1)
179d128f6c176bff9c4929476e13132804321a6d5c5Zhu Yi		return &bad_channel;
180d128f6c176bff9c4929476e13132804321a6d5c5Zhu Yi
181b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. Linville	if (channel <= LIBIPW_24GHZ_CHANNELS)
182d128f6c176bff9c4929476e13132804321a6d5c5Zhu Yi		return &ieee->geo.bg[index];
183d128f6c176bff9c4929476e13132804321a6d5c5Zhu Yi
184d128f6c176bff9c4929476e13132804321a6d5c5Zhu Yi	return &ieee->geo.a[index];
185d128f6c176bff9c4929476e13132804321a6d5c5Zhu Yi}
186d128f6c176bff9c4929476e13132804321a6d5c5Zhu Yi
187b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. LinvilleEXPORT_SYMBOL(libipw_get_channel);
188b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. LinvilleEXPORT_SYMBOL(libipw_get_channel_flags);
189b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. LinvilleEXPORT_SYMBOL(libipw_is_valid_channel);
190b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. LinvilleEXPORT_SYMBOL(libipw_freq_to_channel);
191b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. LinvilleEXPORT_SYMBOL(libipw_channel_to_freq);
192b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. LinvilleEXPORT_SYMBOL(libipw_channel_to_index);
193b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. LinvilleEXPORT_SYMBOL(libipw_set_geo);
194b0a4e7d8a291de63f35b04464de9ab4a83d38a7cJohn W. LinvilleEXPORT_SYMBOL(libipw_get_geo);
195