net80211.c revision 40db2e2b777b79f3dd0d6d9629593a07f86b9c0a
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 2001 Atsushi Onoe
* Copyright (c) 2002-2005 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. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* 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.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* IEEE 802.11 generic handler
*/
#include "net80211_impl.h"
const char *ieee80211_phymode_name[] = {
"auto", /* IEEE80211_MODE_AUTO */
"11a", /* IEEE80211_MODE_11A */
"11b", /* IEEE80211_MODE_11B */
"11g", /* IEEE80211_MODE_11G */
"FH", /* IEEE80211_MODE_FH */
"turboA", /* IEEE80211_MODE_TURBO_A */
"turboG", /* IEEE80211_MODE_TURBO_G */
};
} while (0)
/*
* Print error messages
*/
void
{
}
/*
* Print debug messages
*/
void
{
if (flag & ieee80211_debug)
}
/*
* Alloc memory, and save the size
*/
void *
{
*(int *)p = size;
p = (char *)p + 4;
return (p);
}
void
ieee80211_free(void *p)
{
void *tp = (char *)p - 4;
}
void
{
wifi_data_t wd = { 0 };
/*
* We can send data now; update the fastpath with our
* current associated BSSID and other relevant settings.
*/
}
/*
* ieee80211_event_thread
* open door of wpa, send event to wpad service
*/
static void
ieee80211_event_thread(void *arg)
{
ic->ic_evq_head ++;
ic->ic_evq_head = 0;
/*
* Locate the door used for upcalls
*/
ieee80211_err("ieee80211_event: door_ki_open(%s) failed\n",
ic->ic_wpadoor);
goto out;
}
ieee80211_err("ieee80211_event: door_ki_upcall() failed\n");
}
if (event_door) { /* release our hold (if any) */
}
out:
}
/*
* Notify state transition event message to WPA daemon
*/
void
{
return; /* Not running on WPA mode */
ic->ic_evq_tail ++;
/* async */
}
/*
* Register WPA door
*/
void
{
}
/*
* Default reset method for use with the ioctl support. This
* method is invoked after any state change in the 802.11
* layer that should be propagated to the hardware but not
* require re-initialization of the 802.11 state machine (e.g
* rescanning for an ap). We always return ENETRESET which
* should cause the driver to re-initialize the device. Drivers
* can override this method to implement more optimized support.
*/
/* ARGSUSED */
static int
{
return (ENETRESET);
}
/*
* Convert channel to IEEE channel number.
*/
{
} else if (ch == IEEE80211_CHAN_ANYC) {
return (IEEE80211_CHAN_ANY);
ieee80211_err("invalid channel freq %u flags %x\n",
return (0);
}
return (0);
}
/*
* Convert IEEE channel number to MHz frequency.
* chan IEEE channel number
* flags specify whether the frequency is in the 2GHz ISM
* band or the 5GHz band
*
* 802.11b 2GHz: 14 channels, each 5 MHz wide. Channel 1 is placed
* at 2.412 GHz, channel 2 at 2.417 GHz, and so on up to channel 13
* at 2.472 GHz. Channel 14 was defined especially for operation in
* Japan, and has a center frequency 2.484 GHz.
* 802.11g 2GHz: adopts the frequency plan of 802.11b. Japan only
* allows 802.11g operation in channels 1-13
* 802.11a 5GHz: starting every 5 MHz
* 802.11b/g channels 15-24 (2512-2692) are used by some implementation
* (Atheros etc.)
*/
{
if (chan == 14)
return (2484);
if (chan < 14)
else
} else { /* either, guess */
if (chan == 14)
return (2484);
}
}
/*
* Do late attach work. It must be called by the driver after
* calling ieee80211_attach() and before calling most ieee80211
* functions.
*/
void
{
/*
* Do late attach work that must wait for any subclass
* (i.e. driver) work such as overriding methods.
*/
}
/*
* Start Watchdog timer. After count down timer(s), ic_watchdog
* will be called
*/
void
{
}
}
/*
* Stop watchdog timer.
*/
void
{
if (ic->ic_watchdog_timer != 0) {
ic->ic_watchdog_timer = 0;
}
}
/*
* Called from a driver's xxx_watchdog routine. It is used to
* perform periodic cleanup of state for net80211, as well as
* timeout scans.
*/
void
ieee80211_watchdog(void *arg)
{
int inact_timer = 0;
return;
}
if (nt->nt_inact_timer != 0) {
if (--nt->nt_inact_timer == 0)
}
if (nt->nt_inact_timer != 0) {
if (--nt->nt_inact_timer == 0)
}
}
/*
* Set the current phy mode and recalculate the active channel
* set and supported rates based on the available channels for
* this mode. Also select a new BSS channel if the current one
* is inappropriate for this mode.
* This function is called by net80211, and not intended to be
* called directly.
*/
static int
{
0, /* IEEE80211_MODE_AUTO */
IEEE80211_CHAN_A, /* IEEE80211_MODE_11A */
IEEE80211_CHAN_B, /* IEEE80211_MODE_11B */
IEEE80211_CHAN_PUREG, /* IEEE80211_MODE_11G */
IEEE80211_CHAN_FHSS, /* IEEE80211_MODE_FH */
IEEE80211_CHAN_T, /* IEEE80211_MODE_TURBO_A */
IEEE80211_CHAN_108G, /* IEEE80211_MODE_TURBO_G */
};
struct ieee80211_channel *ch;
int i;
int achannels = 0;
/* validate new mode */
ieee80211_err("ieee80211_setmode(): mode %u not supported"
return (EINVAL);
}
/*
* Verify at least one channel is present in the available
* channel list before committing to the new mode.
* Calculate the active channel set.
*/
for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
continue;
if (mode == IEEE80211_MODE_AUTO) {
/* take anything but pure turbo channels */
achannels++;
}
} else {
achannels++;
}
}
}
if (achannels == 0) {
ieee80211_err("ieee80211_setmode(): "
"no channel found for mode %u\n", mode);
return (EINVAL);
}
/*
* channel is wrong for the mode then pick the first
* available channel from the active list. This is likely
* not the right one.
*/
for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
break;
}
}
}
/*
* If the desired channel is set but no longer valid then reset it.
*/
}
/*
* Do mode-specific rate setup.
*/
/*
* Setup an initial rate set according to the
* when scanning but must exist now so drivers have
* consistent state of ic_bsschan.
*/
return (0);
}
/*
* Return the phy mode for with the specified channel so the
* caller can select a rate set. This is problematic for channels
* where multiple operating modes are possible (e.g. 11g+11b).
* In those cases we defer to the current operating mode when set.
*/
enum ieee80211_phymode
{
if (IEEE80211_IS_CHAN_T(chan)) {
return (IEEE80211_MODE_TURBO_A);
} else if (IEEE80211_IS_CHAN_5GHZ(chan)) {
return (IEEE80211_MODE_11A);
} else if (IEEE80211_IS_CHAN_FHSS(chan)) {
return (IEEE80211_MODE_FH);
/*
* This assumes all 11g channels are also usable
* for 11b, which is currently true.
*/
return (IEEE80211_MODE_TURBO_G);
return (IEEE80211_MODE_11B);
return (IEEE80211_MODE_11G);
} else {
return (IEEE80211_MODE_11B);
}
}
/*
* Return the size of the 802.11 header for a management or data frame.
*/
int
ieee80211_hdrspace(const void *data)
{
int size = sizeof (struct ieee80211_frame);
/* NB: we don't handle control frames */
return (size);
}
/*
* Allocate and setup a management frame of the specified
* size. We return the mblk and a pointer to the start
* of the contiguous data area that's been reserved based
* on the packet length.
*/
mblk_t *
{
int len;
} else {
ieee80211_err("ieee80211_getmgtframe: "
"alloc frame failed, %d\n", len);
}
return (mp);
}
/*
* Send system messages to notify the device has joined a WLAN.
* This is an OS specific function. Solaris marks link status
* as up.
*/
void
{
}
/*
* Send system messages to notify the device has left a WLAN.
* This is an OS specific function. Solaris marks link status
* as down.
*/
void
{
}
/*
* Get 802.11 kstats defined in ieee802.11(5)
*
* Return 0 on success
*/
int
{
switch (stat) {
case WIFI_STAT_TX_FRAGS:
break;
case WIFI_STAT_MCAST_TX:
break;
case WIFI_STAT_TX_FAILED:
break;
case WIFI_STAT_TX_RETRANS:
break;
case WIFI_STAT_RTS_SUCCESS:
break;
case WIFI_STAT_RTS_FAILURE:
break;
case WIFI_STAT_ACK_FAILURE:
break;
case WIFI_STAT_RX_FRAGS:
break;
case WIFI_STAT_MCAST_RX:
break;
case WIFI_STAT_RX_DUPS:
break;
case WIFI_STAT_FCS_ERRORS:
break;
case WIFI_STAT_WEP_ERRORS:
break;
}
return (0);
}
/*
* Attach network interface to the 802.11 support module. This
* function must be called before using any of the ieee80211
* functionss. The parameter "ic" MUST be initialized to tell
* net80211 about interface's capabilities.
*/
void
{
struct ieee80211_impl *im;
struct ieee80211_channel *ch;
int i;
/* Check mandatory callback functions not NULL */
/*
* Fill in 802.11 available channel set, mark
* all available channels as active, and pick
* a default channel if not already specified.
*/
for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
/* Verify driver passed us valid data */
ieee80211_err("bad channel ignored: "
"freq %u flags%x number %u\n",
continue;
}
/* Identify mode capabilities */
if (IEEE80211_IS_CHAN_A(ch))
if (IEEE80211_IS_CHAN_B(ch))
if (IEEE80211_IS_CHAN_PUREG(ch))
if (IEEE80211_IS_CHAN_FHSS(ch))
if (IEEE80211_IS_CHAN_T(ch))
if (IEEE80211_IS_CHAN_108G(ch))
/* arbitrarily pick the first channel */
}
}
}
/* validate ic->ic_curmode */
ic->ic_watchdog_timer = 0;
}
/*
* Free any ieee80211 structures associated with the driver.
*/
void
{
}
static struct modlmisc i_wifi_modlmisc = {
"IEEE80211 Kernel Module v1.3"
};
static struct modlinkage i_wifi_modlinkage = {
};
/*
* modlinkage functions
*/
int
_init(void)
{
return (mod_install(&i_wifi_modlinkage));
}
int
_fini(void)
{
return (mod_remove(&i_wifi_modlinkage));
}
int
{
}