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

📄 hfa384x.c

📁 uClinux2.6上兼容PRISM2.0芯片组的USB设备驱动程序.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* src/prism2/driver/hfa384x.c** Implements the functions of the Intersil hfa384x MAC** Copyright (C) 1999 AbsoluteValue Systems, Inc.  All Rights Reserved.* --------------------------------------------------------------------** linux-wlan**   The contents of this file are subject to the Mozilla Public*   License Version 1.1 (the "License"); you may not use this file*   except in compliance with the License. You may obtain a copy of*   the License at http://www.mozilla.org/MPL/**   Software distributed under the License is distributed on an "AS*   IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or*   implied. See the License for the specific language governing*   rights and limitations under the License.**   Alternatively, the contents of this file may be used under the*   terms of the GNU Public License version 2 (the "GPL"), in which*   case the provisions of the GPL are applicable instead of the*   above.  If you wish to allow the use of your version of this file*   only under the terms of the GPL and not to allow others to use*   your version of this file under the MPL, indicate your decision*   by deleting the provisions above and replace them with the notice*   and other provisions required by the GPL.  If you do not delete*   the provisions above, a recipient may use your version of this*   file under either the MPL or the GPL.** --------------------------------------------------------------------** Inquiries regarding the linux-wlan Open Source project can be* made directly to:** AbsoluteValue Systems Inc.* info@linux-wlan.com* http://www.linux-wlan.com** --------------------------------------------------------------------** Portions of the development of this software were funded by * Intersil Corporation as part of PRISM(R) chipset product development.** --------------------------------------------------------------------** This file implements functions that correspond to the prism2/hfa384x* 802.11 MAC hardware and firmware host interface.** The functions can be considered to represent several levels of * abstraction.  The lowest level functions are simply C-callable wrappers* around the register accesses.  The next higher level represents C-callable* prism2 API functions that match the Intersil documentation as closely* as is reasonable.  The next higher layer implements common sequences * of invokations of the API layer (e.g. write to bap, followed by cmd).** Common sequences:* hfa384x_drvr_xxx	Highest level abstractions provided by the *			hfa384x code.  They are driver defined wrappers *			for common sequences.  These functions generally*			use the services of the lower levels.** hfa384x_drvr_xxxconfig  An example of the drvr level abstraction. These*			functions are wrappers for the RID get/set *			sequence. They 	call copy_[to|from]_bap() and *			cmd_access().	These functions operate on the *			RIDs and buffers without validation.  The caller*			is responsible for that.** API wrapper functions:* hfa384x_cmd_xxx	functions that provide access to the f/w commands.  *			The function arguments correspond to each command*			argument, even command arguments that get packed*			into single registers.  These functions _just_*			issue the command by setting the cmd/parm regs*			& reading the status/resp regs.  Additional*			activities required to fully use a command*			(read/write from/to bap, get/set int status etc.)*			are implemented separately.  Think of these as*			C-callable prism2 commands.** Lowest Layer Functions:* hfa384x_docmd_xxx	These functions implement the sequence required*			to issue any prism2 command.  Primarily used by the*			hfa384x_cmd_xxx functions.** hfa384x_bap_xxx	BAP read/write access functions.*			Note: we usually use BAP0 for non-interrupt context*			 and BAP1 for interrupt context.** hfa384x_dl_xxx	download related functions.*                 	* Driver State Issues:* Note that there are two pairs of functions that manage the* 'initialized' and 'running' states of the hw/MAC combo.  The four* functions are create(), destroy(), start(), and stop().  create()* sets up the data structures required to support the hfa384x_** functions and destroy() cleans them up.  The start() function gets* the actual hardware running and enables the interrupts.  The stop()* function shuts the hardware down.  The sequence should be:* create()*  .*  .  Self contained test routines can run here, particularly*  .  corereset() and test_hostif().*  .* start()*  .*  .  Do interesting things w/ the hardware*  .* stop()* destroy()** Note that destroy() can be called without calling stop() first.* --------------------------------------------------------------------*//*================================================================*//* System Includes */#define WLAN_DBVAR	prism2_debug#include <wlan/version.h>#include <linux/config.h>#include <linux/version.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/slab.h>#include <linux/wireless.h>#include <linux/netdevice.h>#include <linux/timer.h>#include <asm/semaphore.h>#include <asm/io.h>#include <linux/delay.h>#include <asm/byteorder.h>#include <linux/list.h>#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))#include <linux/tqueue.h>#else#include <linux/workqueue.h>#endif#if (WLAN_HOSTIF == WLAN_PCMCIA)#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) )#include <pcmcia/version.h>#endif#include <pcmcia/cs_types.h>#include <pcmcia/cs.h>#include <pcmcia/cistpl.h>#include <pcmcia/ds.h>#include <pcmcia/cisreg.h>#endif#if ((WLAN_HOSTIF == WLAN_PLX) || (WLAN_HOSTIF == WLAN_PCI))#include <linux/ioport.h>#include <linux/pci.h>#endif#include <wlan/wlan_compat.h>// XXXX #define CMD_IRQ/*================================================================*//* Project Includes */#include <wlan/p80211types.h>#include <wlan/p80211hdr.h>#include <wlan/p80211mgmt.h>#include <wlan/p80211conv.h>#include <wlan/p80211msg.h>#include <wlan/p80211netdev.h>#include <wlan/p80211req.h>#include <wlan/p80211metadef.h>#include <wlan/p80211metastruct.h>#include <prism2/hfa384x.h>#include <prism2/prism2mgmt.h>/*================================================================*//* Local Constants */const UINT16 crc16tab[256] ={	0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,	0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,	0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,	0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,	0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,	0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,	0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,	0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,	0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,	0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,	0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,	0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,	0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,	0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,	0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,	0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,	0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,	0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,	0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,	0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,	0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,	0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,	0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,	0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,	0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,	0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,	0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,	0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,	0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,	0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,	0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,	0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040};/*================================================================*//* Local Macros *//*================================================================*//* Local Types *//*================================================================*//* Local Static Definitions */extern int prism2_debug;/*================================================================*//* Local Function Declarations */static void	hfa384x_int_dtim(wlandevice_t *wlandev);static void	hfa384x_int_infdrop(wlandevice_t *wlandev);static void     hfa384x_bap_tasklet(unsigned long data);static void	hfa384x_int_info(wlandevice_t *wlandev);static void	hfa384x_int_txexc(wlandevice_t *wlandev);static void	hfa384x_int_tx(wlandevice_t *wlandev);static void	hfa384x_int_rx(wlandevice_t *wlandev);#ifdef CMD_IRQstatic void	hfa384x_int_cmd(wlandevice_t *wlandev);#endifstatic void	hfa384x_int_rxmonitor( wlandevice_t *wlandev, 			UINT16 rxfid, hfa384x_rx_frame_t *rxdesc);static void	hfa384x_int_alloc(wlandevice_t *wlandev);static int hfa384x_docmd_wait( hfa384x_t *hw, hfa384x_metacmd_t *cmd);static int hfa384x_dl_docmd_wait( hfa384x_t *hw, hfa384x_metacmd_t *cmd);static UINT16 hfa384x_mkcrc16(UINT8 *p, int len);int hfa384x_copy_to_bap4(hfa384x_t *hw, UINT16 bap, UINT16 id, UINT16 offset,			 void *buf, UINT len, void* buf2, UINT len2,			 void *buf3, UINT len3, void* buf4, UINT len4);/*================================================================*//* Function Definitions */UINT16txfid_queue_empty(hfa384x_t *hw){	return (hw->txfid_head == hw->txfid_tail) ? 1 : 0;}UINT16txfid_queue_remove(hfa384x_t *hw){	UINT16 result= 0;	if (txfid_queue_empty(hw)) {		WLAN_LOG_DEBUG(3,"queue empty.\n");	} else {		result = hw->txfid_queue[hw->txfid_head];		hw->txfid_head = (hw->txfid_head + 1) % hw->txfid_N;	}	return (UINT16)result;}INT16txfid_queue_add(hfa384x_t *hw, UINT16 val){	INT16 result = 0;	if (hw->txfid_head == ((hw->txfid_tail + 1) % hw->txfid_N)) {		result = -1;		WLAN_LOG_DEBUG(3,"queue full.\n");	} else {		hw->txfid_queue[hw->txfid_tail] = val;		result = hw->txfid_tail;		hw->txfid_tail = (hw->txfid_tail + 1) % hw->txfid_N;	}	return result;}/*----------------------------------------------------------------* hfa384x_create** Initializes the hfa384x_t data structure for use.  Note this* does _not_ intialize the actual hardware, just the data structures* we use to keep track of its state.** Arguments:*	hw		device structure*	irq		device irq number*	iobase		[pcmcia] i/o base address for register access*			[pci] zero*			[plx] i/o base address for register access*	membase		[pcmcia] pcmcia_cs "link" pointer*			[pci] memory base address for register access*			[plx] memory base address for card attribute memory** Returns: *	nothing** Side effects:** Call context:*	process thread ----------------------------------------------------------------*/void hfa384x_create( hfa384x_t *hw, UINT irq, UINT32 iobase, UINT8 *membase){	DBFENTER;	memset(hw, 0, sizeof(hfa384x_t));	hw->irq = irq;	hw->iobase = iobase;	hw->membase = membase;	spin_lock_init(&(hw->cmdlock));	/* BAP setup */ 	spin_lock_init(&(hw->baplock));	tasklet_init(&hw->bap_tasklet,		     hfa384x_bap_tasklet,		     (unsigned long) hw);	init_waitqueue_head(&hw->cmdq);	sema_init(&hw->infofid_sem, 1);        hw->txfid_head = 0;        hw->txfid_tail = 0;        hw->txfid_N = HFA384x_DRVR_FIDSTACKLEN_MAX;        memset(hw->txfid_queue, 0, sizeof(hw->txfid_queue));	hw->isram16 = 1;	/* Init the auth queue head */	skb_queue_head_init(&hw->authq);	INIT_WORK(&hw->link_bh, prism2sta_processing_defer, hw);        INIT_WORK(&hw->commsqual_bh, prism2sta_commsqual_defer, hw);	init_timer(&hw->commsqual_timer);	hw->commsqual_timer.data = (unsigned long) hw;	hw->commsqual_timer.function = prism2sta_commsqual_timer;	hw->link_status = HFA384x_LINK_NOTCONNECTED;	hw->state = HFA384x_STATE_INIT;	DBFEXIT;}/*----------------------------------------------------------------* hfa384x_destroy** Partner to hfa384x_create().  This function cleans up the hw* structure so that it can be freed by the caller using a simple* kfree.  Currently, this function is just a placeholder.  If, at some* point in the future, an hw in the 'shutdown' state requires a 'deep'* kfree, this is where it should be done.  Note that if this function* is called on a _running_ hw structure, the drvr_stop() function is* called.** Arguments:*	hw		device structure** Returns: *	nothing, this function is not allowed to fail.** Side effects:** Call context:*	process ----------------------------------------------------------------*/voidhfa384x_destroy( hfa384x_t *hw){	struct sk_buff *skb;	DBFENTER;	if ( hw->state == HFA384x_STATE_RUNNING ) {		hfa384x_drvr_stop(hw);	}	hw->state = HFA384x_STATE_PREINIT;			if (hw->scanresults) {		kfree(hw->scanresults);		hw->scanresults = NULL;	}        /* Now to clean out the auth queue */        while ( (skb = skb_dequeue(&hw->authq)) ) {                dev_kfree_skb(skb);        }	DBFEXIT;	return;}/*----------------------------------------------------------------* hfa384x_drvr_getconfig** Performs the sequence necessary to read a config/info item.** Arguments:*	hw		device structure*	rid		config/info record id (host order)*	buf		host side record buffer.  Upon return it will*			contain the body portion of the record (minus the *			RID and len).*	len		buffer length (in bytes, should match record length)** Returns: *	0		success*	>0		f/w reported error - f/w status code*	<0		driver reported error*	-ENODATA 	length mismatch between argument and retrieved*			record.** Side effects:** Call context:*	process thread ----------------------------------------------------------------*/int hfa384x_drvr_getconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len){	int 		result = 0;	DBFENTER;	result = hfa384x_cmd_access( hw, 0, rid, buf, len);	DBFEXIT;	return result;}/*----------------------------------------------------------------* hfa384x_drvr_setconfig** Performs the sequence necessary to write a config/info item.** Arguments:*	hw		device structure*	rid		config/info record id (in host order)*	buf		host side record buffer*	len		buffer length (in bytes)** Returns: *	0		success*	>0		f/w reported error - f/w status code*	<0		driver reported error** Side effects:** Call context:*	process thread ----------------------------------------------------------------*/int hfa384x_drvr_setconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len){	int		result = 0;	DBFENTER;	result = hfa384x_cmd_access( hw, 1, rid, buf, len);	DBFEXIT;	return result;}/*----------------------------------------------------------------

⌨️ 快捷键说明

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