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

📄 wlc_scb.c

📁 wi-fi sources for asus wl138g v2 pci card
💻 C
📖 第 1 页 / 共 2 页
字号:
/** * Common interface to the 802.11 Station Control Block (scb) * structure. * This file aims to encapsulating the scb structure. * Copyright 2005-2006, Broadcom Corporation * All Rights Reserved.                 *                                      * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * * $Id$*/#include <wlc_cfg.h>#include <typedefs.h>#include <bcmdefs.h>#include <osl.h>#include <sbutils.h>#include <bcmendian.h>#include <bcmutils.h>#include <proto/802.11.h>#include <proto/wpa.h>#include <sbconfig.h>#include <pcicfg.h>#include <bcmsrom.h>#include <wlioctl.h>#include <epivers.h>#include <proto/eapol.h>#include <bcmwpa.h>#include <sbhndpio.h>#include <sbhnddma.h>#include <hnddma.h>#include <d11.h>#include <wlc_rate.h>#include <wlc_rate_sel.h>#include <wlc_key.h>#include <wlc_channel.h>#include <wlc_pub.h>#include <wlc_bsscfg.h>#include <wlc_pio.h>#include <wlc.h>#include <wlc_scb.h>#include <wlc_phy.h>#include <wl_export.h>#include <wlc_channel.h>#define SCB_MAX_CUBBY		10	/* max number of cubbies in container *//* structure for storing per-cubby client info */typedef struct cubby_info {	scb_cubby_init_t	fn_init;	/* fn called during scb malloc */	scb_cubby_deinit_t	fn_deinit;	/* fn called during scb free */	scb_cubby_dump_t	fn_dump;	/* fn called during scb dump */	void			*context;	/* context to be passed to all cb fns */} cubby_info_t;/* structure for storing public and private global scb module state */typedef struct scb_module_priv {	scb_module_t	scbpub;				/* public part of scb */	uint16		nscb;				/* total number of allocated scbs */	struct scb 	*scbhash[MAXBANDS][NSCBHASH];	/* station control block hash */	uint		scbtotsize;			/* total scb size including container */	uint 		ncubby;				/* current num of cubbies */	cubby_info_t	cubby_info[SCB_MAX_CUBBY];	/* cubby client info */	wlc_pub_t	*pub;				/* public part of wlc */} scb_module_priv_t;#define SCBSTATE_PRIV(s)	((scb_module_priv_t *)(s))#define SCBSTATE_PUB(s)		(&(s)->scbpub)/* station control block - one per remote MAC address */struct scb_info {	struct scb 	scbpub;		/* public portion of scb */	struct scb_info *hashnext;	/* pointer to next scb under same hash entry */	struct scb_info	*next;		/* pointer to next allocated scb */	struct wlcband	*band;		/* pointer to our associated band */};/* Helper macro for txpath in scb *//* A feature in Tx path goes through following states: * Unregisterd -> Registered [Global state] * Registerd -> Configured -> Active -> Configured [Per-scb state] *//* Is the feature configured? */#define SCB_TXMOD_CONFIGURED(scb, fid) (scb->tx_path[(fid)].configured)/* Set the next feature of given feature */#define SCB_TXMOD_SET(scb, fid, _next_fid) { \	scb->tx_path[fid].next_tx_fn = wlc->txmod_fns[_next_fid].tx_fn; \	scb->tx_path[fid].next_handle = wlc->txmod_fns[_next_fid].ctx; \	}static struct scb *wlc_scbvictim(wlc_info_t *wlc);scb_module_t *BCMINITFN(wlc_scb_attach)(wlc_pub_t *pub){	scb_module_priv_t *scbstate;	if ((scbstate = MALLOC(pub->osh, sizeof(scb_module_priv_t))) == NULL)		return NULL;	bzero((char *)scbstate, sizeof(scb_module_priv_t));	scbstate->pub = pub;	scbstate->scbtotsize = sizeof(struct scb_info);	return SCBSTATE_PUB(scbstate);}voidBCMUNINITFN(wlc_scb_detach)(scb_module_t *scbstate){	if (!scbstate)		return;	ASSERT(SCBSTATE_PRIV(scbstate)->nscb == 0);	MFREE(SCBSTATE_PRIV(scbstate)->pub->osh, scbstate, sizeof(scb_module_priv_t));}/* Methods for iterating along a list of scb *//* Direct access to the next */struct scb *wlc_scb_getnext(struct scb *scb){	if (scb)		return (struct scb *)(((struct scb_info *)scb)->next);	return NULL;}/* Initialize an iterator keeping memory of the next scb as it moves along the list */voidwlc_scb_iterinit(struct scb_iter *scbiter, struct scb *scb){	ASSERT(scbiter);	/* Prefetch next scb, so caller can free an scb before going on to the next */	if (scb)		scbiter->next = (struct scb *)(((struct scb_info *)scb)->next);	else		scbiter->next = NULL;}/* move the iterator */struct scb *wlc_scb_iternext(struct scb_iter *scbiter){	struct scb *scb;	ASSERT(scbiter);	if ((scb = scbiter->next))		scbiter->next = (struct scb *)(((struct scb_info *)scb)->next);	else		scbiter->next = NULL;	return  scb;}/*   * Accessors, nagative values are errors. */intwlc_scb_cubby_reserve(wlc_info_t *wlc, uint size, scb_cubby_init_t fn_init,	scb_cubby_deinit_t fn_deinit, scb_cubby_dump_t fn_dump, void *context){	uint offset;	scb_module_priv_t *scbstate = SCBSTATE_PRIV(wlc->scbstate);	cubby_info_t *cubby_info;	ASSERT(scbstate->nscb == 0);	ASSERT((scbstate->scbtotsize % PTRSZ) == 0);	ASSERT(scbstate->ncubby < SCB_MAX_CUBBY);	if (scbstate->ncubby >= SCB_MAX_CUBBY) {		ASSERT(0);		return -1;	}	cubby_info = &scbstate->cubby_info[scbstate->ncubby++];	cubby_info->fn_init = fn_init;	cubby_info->fn_deinit = fn_deinit;	cubby_info->fn_dump = fn_dump;	cubby_info->context = context;	offset = scbstate->scbtotsize;	/* roundup to pointer boundary */	scbstate->scbtotsize = ROUNDUP(scbstate->scbtotsize + size, PTRSZ);	return offset;}struct wlcband *wlc_scbband(struct scb *scb){	return ((struct scb_info *)scb)->band;}struct scb *wlc_scballoc(wlc_info_t *wlc){	struct scb_info *scbinfo = NULL;	struct scb *scb = NULL;	struct scb *oldscb;	struct rateset *rs;	scb_module_priv_t *scbstate = SCBSTATE_PRIV(wlc->scbstate);	cubby_info_t *cubby_info;	uint i;	if (scbstate->nscb < MAXSCB && (scbinfo = MALLOC(wlc->pub.osh, scbstate->scbtotsize)))		scbstate->nscb++;	if (!scbinfo) {		/* free the oldest entry */		if (!(oldscb = wlc_scbvictim(wlc)))			return NULL;		if (!wlc_scbfree(wlc, oldscb))			return NULL;		ASSERT(scbstate->nscb < MAXSCB);		/* allocate memory for scb */		if (!(scbinfo = MALLOC(wlc->pub.osh, scbstate->scbtotsize)))			return NULL;		scbstate->nscb++;	}	bzero((char*)scbinfo, scbstate->scbtotsize);	scb = (struct scb *)scbinfo;	scb->used = wlc->now;	scbinfo->band = wlc->band;	scb->bsscfg = &wlc->cfg;	for (i = 0; i < scbstate->ncubby; i++) {		cubby_info = &scbstate->cubby_info[i];		if (cubby_info->fn_init)			cubby_info->fn_init(cubby_info->context, scb);	}	/* use current, target, or per-band default rateset? */	if (wlc->pub.up && VALID_CHANNEL(wlc, wlc->target_bss.channel))		if (wlc->pub.associated)			rs = &wlc->pub.current_bss.rateset;		else			rs = &wlc->target_bss.rateset;	else		rs = &wlc->band->defrateset;	/*	 * Initialize the per-scb rateset:	 * - if we are AP, start with only the basic subset of the	 *	network rates.  It will be updated when receive the next	 *	probe request or association request.	 * - if we are IBSS and gmode, special case:	 *	start with B-only subset of network rates and probe for ofdm rates	 * - else start with the network rates.	 *	It will be updated on join attempts.	 */	/* initialize the scb rateset */	if (!wlc->pub.BSS && wlc->band->gmode) {		wlc_rateset_filter(rs, &scb->rateset, FALSE, TRUE, RATE_MASK);		/* if resulting set is empty, then take all network rates instead */		if (scb->rateset.count == 0)			wlc_rateset_filter(rs, &scb->rateset, FALSE, FALSE, RATE_MASK);	} else		wlc_rateset_filter(rs, &scb->rateset, FALSE, FALSE, RATE_MASK);	wlc_scb_rate_init(wlc, scb);	/* update scb link list */	scbinfo->next = (struct scb_info *)SCBSTATE_PUB(scbstate)->scb;	SCBSTATE_PUB(scbstate)->scb = scb;	return scb;}boolwlc_scbfree(wlc_info_t *wlc, struct scb *scbd){	int index;	struct scb_info *remove = (struct scb_info *)scbd;	struct scb_info *scbinfo;	scb_module_priv_t *scbstate = SCBSTATE_PRIV(wlc->scbstate);	cubby_info_t *cubby_info;	uint i;	uint8 prio;	if (scbd->permanent)		return FALSE;	for (i = 0; i < scbstate->ncubby; i++) {		cubby_info = &scbstate->cubby_info[i];		if (cubby_info->fn_deinit)			cubby_info->fn_deinit(cubby_info->context, scbd);	}	/* free the per station key if one exists */	if (scbd->key) {		WL_WSEC(("wl%d: %s: deleting pairwise key for %s\n", wlc->pub.unit,		        __FUNCTION__, bcm_ether_ntoa(&scbd->ea, eabuf)));		ASSERT(!bcmp((char*)&scbd->key->ea, (char*)&scbd->ea, ETHER_ADDR_LEN));		wlc_scb_key_delete(wlc, scbd);	}	/* free any frame reassembly buffer */	for (prio = 0; prio < NUMPRIO; prio++) {		if (scbd->fragbuf[prio]) {			PKTFREE(wlc->pub.osh, scbd->fragbuf[prio], FALSE);			scbd->fragbuf[prio] = NULL;			scbd->fragresid[prio] = 0;		}	}	scbd->state = 0;	index = SCBHASHINDEX(scbd->ea.octet);	/* delete it from the hash */	scbinfo = (struct scb_info *)(scbstate->scbhash[remove->band->bandunit][index]);	/* special case for the first */	if (scbinfo == remove) {		scbstate->scbhash[remove->band->bandunit][index] = (struct scb *)scbinfo->hashnext;	}	else {		for (; scbinfo; scbinfo = scbinfo->hashnext) {			if (scbinfo->hashnext == remove)			{				scbinfo->hashnext = remove->hashnext;				break;			}		}		ASSERT(scbinfo);	}	/* delete it from the link list */	scbinfo = (struct scb_info *)(SCBSTATE_PUB(scbstate)->scb);	if (scbinfo == remove) {		SCBSTATE_PUB(scbstate)->scb = wlc_scb_getnext(scbd);	} else {		while (scbinfo) {			if (scbinfo->next == remove) {				scbinfo->next = remove->next;				break;			}			scbinfo = scbinfo->next;		}		ASSERT(scbinfo);	}	/* free scb memory */	MFREE(wlc->pub.osh, remove, scbstate->scbtotsize);	/* update total allocated scb number */	scbstate->nscb--;	return TRUE;}/* free all scbs, unless permanent. Force indicates reclaim permanent as well */voidwlc_scbclear(struct wlc_info *wlc, bool force){	struct scb_iter scbiter;	struct scb *scb;	if (wlc->scbstate == NULL)		return;	FOREACHSCB(&scbiter, wlc->scbstate->scb, scb) {		if (force)			scb->permanent = FALSE;		wlc_scbfree(wlc, scb);	}	if (force)		ASSERT(SCBSTATE_PRIV(wlc->scbstate)->nscb == 0);}static struct scb *wlc_scbvictim(wlc_info_t *wlc){	uint oldest;	struct scb *scb;	struct scb *oldscb;	uint now, age;	struct scb_iter scbiter;	if (!wlc->scbstate->scb)		return NULL;	/* free the oldest scb */	now = wlc->now;	oldest = 0;	oldscb = NULL;	FOREACHSCB(&scbiter, wlc->scbstate->scb, scb)  {		if (!scb->permanent && ((age = (now - scb->used)) >= oldest)) {			oldest = age;			oldscb = scb;		}	}	/* handle extreme case: all are permanent */	if (oldscb == NULL)		return NULL;	WL_ASSOC(("scb free %s due to aging %d\n", bcm_ether_ntoa(&oldscb->ea, eabuf),		oldest));	return oldscb;}voidwlc_scb_setkey(struct scb *scb, wsec_key_t *key){	scb->key = key;}/* "|" operation. */voidwlc_scb_setstatebit(struct scb *scb, uint8 state){	WL_ASSOC(("set state %x\n", state));	ASSERT(scb);	if (state & AUTHENTICATED)	{		scb->state &= ~PENDING_AUTH;	}	if (state & ASSOCIATED)	{		ASSERT(scb->state & AUTHENTICATED);		scb->state &= ~PENDING_ASSOC;	}	if (state & AUTHORIZED)	{		ASSERT((scb->state & ASSOCIATED));	}	scb->state |= state;	WL_ASSOC(("wlc_scb : state = %x\n", scb->state));}/* "& ~" operation */voidwlc_scb_clearstatebit(struct scb *scb, uint8 state){	ASSERT(scb);	WL_ASSOC(("clear state %x\n", state));	scb->state &= ~state;	WL_ASSOC(("wlc_scb : state = %x\n", scb->state));}/* "|" operation . idx = position of the bsscfg in the wlc array of multi ssids.*/voidwlc_scb_setstatebit_bsscfg(struct scb *scb, uint8 state, int idx){	ASSERT(scb);	WL_ASSOC(("set state : %x   bsscfg idx : %d\n", state, idx));	if (state & ASSOCIATED)	{		ASSERT(SCB_AUTHENTICATED_BSSCFG(scb, idx));		/* clear all bits (idx is set below) */		memset(&scb->auth_bsscfg, 0, SCB_BSSCFG_BITSIZE);		scb->state &= ~PENDING_ASSOC;	}	if (state & AUTHORIZED)	{		ASSERT(SCB_ASSOCIATED_BSSCFG(scb, idx));	}	setbit(&scb->auth_bsscfg, idx);	scb->state |= state;

⌨️ 快捷键说明

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