⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 if_wi.c

📁 一个学习SNMP项目:tmoerlan.
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  Copyright (c) 2003, Tijmen Moerland (moerland@yahoo.com)*//* doxygen comments follow *//*!	\file if_wi.c	\brief Source file of the driver for any wi(4) interface	\bug 'wi_cmd busy bit won't clear' when loading the driver --> takes minutes to load	This is where most additions for the 802.11 MIB implementation have taken place.	The functions that are of interest tot the 802.11 MIB project have been documented.	Please refer to the specific functions for detailed information. Note that the additions for extended cache are all	placed between WICACHE defines and should thus be easily removable by not using the -DWICACHE compile option.*//* for some unknown reason doxygen doesn't read the documentation when placed right before function (body) definition * so, we do it here *//*!	\fn static void wi_rxeof(struct wi_softc *sc)	\brief This function is called after the interface has received a frame	\param sc Pointer to the wi_softc structure of the specific interface	This function processes the received frame according to interface port type, frame type, etc.	In the end, some information about the frame is stored by calling the wi_cache_store function.	There's a similar function for sending frames wi_txeof, but it doesn't provide us with the same information	as this function. See wi_write_data.*//*!	\fn static void wi_txeof(struct wi_softc *sc, int status)	\brief This function is called after a frame has been sent by the interface	\param sc Pointer to the wi_softc structure of the specific interface	\param status Flag information about sent packet	This function might be used to count number of packets sent, and number of errors while trying to send a packet.	We're not doing that right now (see wi_write_data).*//*!	\fn static int wi_write_data(struct wi_softc *sc, int id, int off, caddr_t buf, int len)	\brief This function is called to transmit a frame via the wireless interface. We use it to count packets/bytes.	\note No filters are applied (multicast only / IP only)!!		For every packet to be sent, this function is called twice. If off=0, buf points to a wi_frame structure. From this	structure we can read the destination address and the data length. We do have to add header length, which is variable	in 802.11b, for example dependent on whether or not WEP is used. The dirty hack should work for most cases.		The information is stored in the extended cache, and if the interface is in BSS mode the cache timeout is started.*//*!	\fn static int wi_ioctl(struct ifnet *ifp, u_long command, caddr_t data)	\brief Handles many ioctl calls	Handles calls to SIOCSIFFLAGS, SIOCSIFMEDIA, SIOCGIFMEDIA, SIOCADDMULTI, SIOCDELMULTI, SIOCGWAVELAN, SIOCSWAVELAN,	SIOCSPRISM2DEBUG, SIOCGPRISM2DEBUG, SIOCG80211 and SIOCS80211. SIOCHOSTAP_<FOO> calls are forwarded to wihap_ioctl, in	wi_hostap.c.	The lib80211.c file uses SIOCSIFFLAGS, SIOCGWAVELAN, SIOCSWAVELAN, SIOCG80211, SIOCS80211 and some SIOCHOSTAP_<FOO>.	Under the SIOC<S,G>WAVELAN calls have been added for reading and zeroing the extended cache, reading and writing EWMA constants	for bandwidth and signal, noise, quality average calculation, reading and writing the cache timeout time.*//*!	\fn static void wi_init(void *xsc)	\brief Initializes a wireless interface	At the end the every_second function call is started for the specified interface (if not already done so). Also, the bandwidth	and signal, noise, quality EWMA constants and cache timeout time are set to default if this is the first call.	Note that this function can (and will) be called multiple times during operation.*//*!	\fn static void wi_stop(struct wi_softc *sc)	\brief The inverse of init	The every_second function call is stopped, and the parameter in sc is reset so that on the next init it will be started again.	The parameter that makes sure init only sets some variables to default once (see wi_init) is NOT reset, thus will NOT be set	back to default on next init. This because calls to init/stop pairs are done rather frequent and we don't want to throw away	user settings every time.*//* * Copyright (c) 1997, 1998, 1999 *	Bill Paul <wpaul@ctr.columbia.edu>.  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 *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD * 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. *//* * Lucent WaveLAN/IEEE 802.11 PCMCIA driver for FreeBSD. * * Written by Bill Paul <wpaul@ctr.columbia.edu> * Electrical Engineering Department * Columbia University, New York City *//* * The WaveLAN/IEEE adapter is the second generation of the WaveLAN * from Lucent. Unlike the older cards, the new ones are programmed * entirely via a firmware-driven controller called the Hermes. * Unfortunately, Lucent will not release the Hermes programming manual * without an NDA (if at all). What they do release is an API library * called the HCF (Hardware Control Functions) which is supposed to * do the device-specific operations of a device driver for you. The * publically available version of the HCF library (the 'HCF Light') is  * a) extremely gross, b) lacks certain features, particularly support * for 802.11 frames, and c) is contaminated by the GNU Public License. * * This driver does not use the HCF or HCF Light at all. Instead, it * programs the Hermes controller directly, using information gleaned * from the HCF Light code and corresponding documentation. * * This driver supports the ISA, PCMCIA and PCI versions of the Lucent * WaveLan cards (based on the Hermes chipset), as well as the newer * Prism 2 chipsets with firmware from Intersil and Symbol. */#include <sys/param.h>#include <sys/systm.h>#if __FreeBSD_version >= 500033#include <sys/endian.h>#endif#include <sys/sockio.h>#include <sys/mbuf.h>#include <sys/proc.h>#include <sys/kernel.h>#include <sys/socket.h>#include <sys/module.h>#include <sys/bus.h>#include <sys/random.h>#include <sys/syslog.h>#include <sys/sysctl.h>#include <machine/bus.h>#include <machine/resource.h>#include <machine/clock.h>#include <sys/rman.h>#include <net/if.h>#include <net/if_arp.h>#include <net/ethernet.h>#include <net/if_dl.h>#include <net/if_media.h>#include <net/if_types.h>#include <net/if_ieee80211.h>#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/in_var.h>#include <netinet/ip.h>#include <netinet/if_ether.h>#include <net/bpf.h>#include <dev/wi/if_wavelan_ieee.h>#include <dev/wi/wi_hostap.h>#include <dev/wi/if_wivar.h>#include <dev/wi/if_wireg.h>#if !defined(lint)static const char rcsid[] =  "$FreeBSD: src/sys/dev/wi/if_wi.c,v 1.118 2002/11/14 23:54:55 sam Exp $";#endif#ifdef WICACHEextern void saveAssocTime(struct wi_softc *, char *);extern void saveDisassocTime(struct wi_softc *, char *);void wi_every_second(void *);#endifstatic void wi_intr(void *);static void wi_reset(struct wi_softc *);static int wi_ioctl(struct ifnet *, u_long, caddr_t);static void wi_init(void *);static void wi_start(struct ifnet *);static void wi_stop(struct wi_softc *);static void wi_watchdog(struct ifnet *);static void wi_rxeof(struct wi_softc *);static void wi_txeof(struct wi_softc *, int);static void wi_update_stats(struct wi_softc *);static void wi_setmulti(struct wi_softc *);static int wi_cmd(struct wi_softc *, int, int, int, int);static int wi_read_record(struct wi_softc *, struct wi_ltv_gen *);static int wi_write_record(struct wi_softc *, struct wi_ltv_gen *);static int wi_read_data(struct wi_softc *, int, int, caddr_t, int);static int wi_write_data(struct wi_softc *, int, int, caddr_t, int);static int wi_seek(struct wi_softc *, int, int, int);static int wi_alloc_nicmem(struct wi_softc *, int, int *);static void wi_inquire(void *);static void wi_setdef(struct wi_softc *, struct wi_req *);#ifdef WICACHEstaticvoid wi_cache_store(struct wi_softc *, struct ether_header *,	struct mbuf *, unsigned short);int wi_findCacheEntry(struct wi_softc *, char *);void wi_removeCacheEntry(struct wi_softc *, int);void wi_dumpCache(struct wi_softc *);#endifstatic int wi_get_cur_ssid(struct wi_softc *, char *, int *);static void wi_get_id(struct wi_softc *);static int wi_media_change(struct ifnet *);static void wi_media_status(struct ifnet *, struct ifmediareq *);static int wi_get_debug(struct wi_softc *, struct wi_req *);static int wi_set_debug(struct wi_softc *, struct wi_req *);#if __FreeBSD_version >= 500000/* support to download firmware for symbol CF card */static int wi_symbol_write_firm(struct wi_softc *, const void *, int,		const void *, int);static int wi_symbol_set_hcr(struct wi_softc *, int);#endifdevclass_t wi_devclass;struct wi_card_ident wi_card_ident[] = {	/* CARD_ID			CARD_NAME		FIRM_TYPE */	{ WI_NIC_LUCENT_ID,		WI_NIC_LUCENT_STR,	WI_LUCENT },	{ WI_NIC_SONY_ID,		WI_NIC_SONY_STR,	WI_LUCENT },	{ WI_NIC_LUCENT_EMB_ID,		WI_NIC_LUCENT_EMB_STR,	WI_LUCENT },	{ WI_NIC_EVB2_ID,		WI_NIC_EVB2_STR,	WI_INTERSIL },	{ WI_NIC_HWB3763_ID,		WI_NIC_HWB3763_STR,	WI_INTERSIL },	{ WI_NIC_HWB3163_ID,		WI_NIC_HWB3163_STR,	WI_INTERSIL },	{ WI_NIC_HWB3163B_ID,		WI_NIC_HWB3163B_STR,	WI_INTERSIL },	{ WI_NIC_EVB3_ID,		WI_NIC_EVB3_STR,	WI_INTERSIL },	{ WI_NIC_HWB1153_ID,		WI_NIC_HWB1153_STR,	WI_INTERSIL },	{ WI_NIC_P2_SST_ID,		WI_NIC_P2_SST_STR,	WI_INTERSIL },	{ WI_NIC_EVB2_SST_ID,		WI_NIC_EVB2_SST_STR,	WI_INTERSIL },	{ WI_NIC_3842_EVA_ID,		WI_NIC_3842_EVA_STR,	WI_INTERSIL },	{ WI_NIC_3842_PCMCIA_AMD_ID,	WI_NIC_3842_PCMCIA_STR,	WI_INTERSIL },	{ WI_NIC_3842_PCMCIA_SST_ID,	WI_NIC_3842_PCMCIA_STR,	WI_INTERSIL },	{ WI_NIC_3842_PCMCIA_ATL_ID,	WI_NIC_3842_PCMCIA_STR,	WI_INTERSIL },	{ WI_NIC_3842_PCMCIA_ATS_ID,	WI_NIC_3842_PCMCIA_STR,	WI_INTERSIL },	{ WI_NIC_3842_MINI_AMD_ID,	WI_NIC_3842_MINI_STR,	WI_INTERSIL },	{ WI_NIC_3842_MINI_SST_ID,	WI_NIC_3842_MINI_STR,	WI_INTERSIL },	{ WI_NIC_3842_MINI_ATL_ID,	WI_NIC_3842_MINI_STR,	WI_INTERSIL },	{ WI_NIC_3842_MINI_ATS_ID,	WI_NIC_3842_MINI_STR,	WI_INTERSIL },	{ WI_NIC_3842_PCI_AMD_ID,	WI_NIC_3842_PCI_STR,	WI_INTERSIL },	{ WI_NIC_3842_PCI_SST_ID,	WI_NIC_3842_PCI_STR,	WI_INTERSIL },	{ WI_NIC_3842_PCI_ATS_ID,	WI_NIC_3842_PCI_STR,	WI_INTERSIL },	{ WI_NIC_3842_PCI_ATL_ID,	WI_NIC_3842_PCI_STR,	WI_INTERSIL },	{ WI_NIC_P3_PCMCIA_AMD_ID,	WI_NIC_P3_PCMCIA_STR,	WI_INTERSIL },	{ WI_NIC_P3_PCMCIA_SST_ID,	WI_NIC_P3_PCMCIA_STR,	WI_INTERSIL },	{ WI_NIC_P3_PCMCIA_ATL_ID,	WI_NIC_P3_PCMCIA_STR,	WI_INTERSIL },	{ WI_NIC_P3_PCMCIA_ATS_ID,	WI_NIC_P3_PCMCIA_STR,	WI_INTERSIL },	{ WI_NIC_P3_MINI_AMD_ID,	WI_NIC_P3_MINI_STR,	WI_INTERSIL },	{ WI_NIC_P3_MINI_SST_ID,	WI_NIC_P3_MINI_STR,	WI_INTERSIL },	{ WI_NIC_P3_MINI_ATL_ID,	WI_NIC_P3_MINI_STR,	WI_INTERSIL },	{ WI_NIC_P3_MINI_ATS_ID,	WI_NIC_P3_MINI_STR,	WI_INTERSIL },	{ 0,	NULL,	0 },};#ifdef WICACHE/*!	\fn void wi_every_second(void *xsc)	\brief Is called every second to update all kinds of data	\param xsc A pointer to a wi_softc struct corresponding to a specific wireless interface	This function is called once every second for all wireless interfaces. Three things are done (in this order):	Detection of (Dis-)association in BSS mode	Because no function is called on (dis-)association from HostAP when interface is in BSS (client) mode, we check here.	We request the current BSSID we're connected to, and have remembered the previous one (from the last time this function was called).	No association is represented by a BSSID of 44:44:44:44:44:44. Thus, we can detect (dis-)association, and also association to a different	BSSID. Acting accordingly, we can save (dis-)association time.	Cache deletion at timeout	This being done, we start walking through all the cache items, checking if remove_ctr > 0. If so check if one (1) has been reached.	If so, delete cache item. If not, decrement counter.	A difference is made again between between BSS and HostAP. While HostAP deletes any station, BSS checks to see if it's not the current	BSSID that is about to be removed. We don't want to delete the AP we're associated with, just because it's been a while that we sent/received	a packet to/from it. If we get disassociated, then we'll start our cache timeout. In BSS mode, cache timeout is started for any station just 	after a packet sent/received, and we don't know the current bssid there, so we must check here. An option would be to add bssid to wi_softc.	Updating bandwidth averages	We're still walking through cache items. After checking cache timeout, we start updating bandwidth averages according to the accumulated	information on sent/received packets/bytes. This is accumulated since last call to this function, which should be 1 second ago. EWMA method	is used for this calculation of bandwidth in/out averages and deviations. After this, the sums are zeroed again for the next second.*//* must take a void * argument for calling by timeout func */void wi_every_second(void *xsc) {	struct wi_softc *sc = xsc;	struct wi_sigextcache *p;	int i;	float diff;	struct wi_req wreq;	static int init = 0;	static u_char bssid[10][6];	u_char bssid_undef[6] = {0x44, 0x44, 0x44, 0x44, 0x44, 0x44};	u_char *newbssid;	int s;	if (init == 0) {		memset(bssid, 0x44, 60);		init = 1;	}	WI_LOCK(sc, s);/* extra stuff: check if this device is in BSS mode, and if yes --> check association   to keep track of assoctime, disassoctime*/	if (sc->wi_ptype == WI_PORTTYPE_BSS) {	        wreq.wi_type = WI_RID_CURRENT_BSSID;		wreq.wi_len = WI_MAX_DATALEN;                if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) != 0) {			device_printf(sc->dev, "Could not read current BSSID!!\n");			WI_UNLOCK(sc, s);			return;		}		newbssid = (char *) &wreq.wi_val;		if (bcmp(bssid[sc->wi_unit], newbssid, 6) != 0) {			/* BSSID has changed since last call to this function (mostly 1 sec ago) */			if (bcmp(bssid[sc->wi_unit], bssid_undef, 6) == 0) {				/* formerly, BSSID was the undefined, i.e. interface was unassociated */				if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)					device_printf(sc->dev, "BSS new assoc: %6D\n", newbssid, ":");				saveAssocTime(sc, newbssid);			}			else {				/* we were associated with a BSSID */				if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)					device_printf(sc->dev, "BSS disassoc: %6D\n", bssid[sc->wi_unit], ":");				saveDisassocTime(sc, bssid[sc->wi_unit]);				if (bcmp(newbssid, bssid_undef, 6) != 0) {					/* the new BSSID is not the undefined, so we immediately associated					   from one BSSID to the next one! */					if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)						device_printf(sc->dev, "BSS other assoc: %6D\n", newbssid, ":");					saveAssocTime(sc, newbssid);				}			}			bcopy(newbssid, bssid[sc->wi_unit], 6);		}	}	/* for all the items in cache we update the AvgBandwidth with	 * the number of bytes since last call of this function (1 second ago)	 */	if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)		device_printf(sc->dev, "\tfor wi_unit %d: %d items\n", sc->wi_unit, sc->wi_sigitems);	for (i = 0; i < sc->wi_sigitems; i++) {		p = &sc->wi_sigextcache[i];		if (p->remove_ctr > 1) {			p->remove_ctr--;			/*device_printf(sc->dev, "decrementing counter for slot %d --> %d\n", i, p->remove_ctr);*/		}		if (p->remove_ctr == 1) {			/* if we're in BSS mode, we can also have the timeout since last (IP) pkt received			   however, we do not want to throw away the BSSID, we do this after disassoc + timeout			*/			if (sc->wi_ptype == WI_PORTTYPE_BSS) {				if (bcmp(p->macsrc, bssid[sc->wi_unit], 6) != 0) {					/* it's not the BSSID */					if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)						device_printf(sc->dev, "removing in BSS mode (disassoc (from former BSSID) or last pkt received timeout)\n");					wi_removeCacheEntry(sc, i);				}				else {					/* it's the BSSID !! */					if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)						device_printf(sc->dev, "NOT removing BSSID from cache because of 'last pkt received timeout' in BSS mode!!!\n");					p->remove_ctr = 0;	/* it won't be bothered next time */				}			}			else {	/* ptype == BSS */				if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)					device_printf(sc->dev, "removing because of 'disassociated timeout' in HostAP mode\n");				wi_removeCacheEntry(sc, i);			}			i--;			continue;	/* i.e. do this (new!) item again */		}		if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)			device_printf(sc->dev, "past sec: rcvbytes = %lu\t\tsndbytes = %lu\n", p->temprcvbytes, p->tempsndbytes);		if (p->EWMAInBandwidth == 0) {	/* first time */			p->EWMAInBandwidth = p->temprcvbytes;			p->devOutBandwidth = 0;		}		else {			p->EWMAInBandwidth *= 1 - sc->wi_ewmaconst_bw;			p->EWMAInBandwidth += sc->wi_ewmaconst_bw * p->temprcvbytes;			p->devInBandwidth *= 1 - sc->wi_ewmaconst_bw;			diff = p->temprcvbytes - p->EWMAInBandwidth;			if (diff > 0)				p->devInBandwidth += sc->wi_ewmaconst_bw * diff;			else				p->devInBandwidth -= sc->wi_ewmaconst_bw * diff;		}		p->temprcvbytes = 0;		if (p->EWMAOutBandwidth == 0) {			p->EWMAOutBandwidth = p->tempsndbytes;			p->devOutBandwidth = 0;		}		else {			p->EWMAOutBandwidth *= 1 - sc->wi_ewmaconst_bw;			p->EWMAOutBandwidth += sc->wi_ewmaconst_bw * p->tempsndbytes;			p->devOutBandwidth *= 1 - sc->wi_ewmaconst_bw;			diff = p->tempsndbytes - p->EWMAOutBandwidth;			if (diff > 0)				p->devOutBandwidth += sc->wi_ewmaconst_bw * diff;			else				p->devOutBandwidth -= sc->wi_ewmaconst_bw * diff;		}		p->tempsndbytes = 0;	}	/* bandwidth (in and out) have been updated, and counters (tempsndbytes, temprcvbytes) reset to zero	 * we're ready for the next second, make sure we get called in 1 sec again	 */	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -