hfa384x_usb.c

来自「Linux的无线局域网方案是一个Linux设备驱动程序和子系统 一揽子方案的用」· C语言 代码 · 共 2,513 行 · 第 1/5 页

C
2,513
字号
/* src/prism2/driver/hfa384x_usb.c** Functions that talk to the USB variantof 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()* start()*  .*  .  Do interesting things w/ the hardware*  .* stop()* destroy()** Note that destroy() can be called without calling stop() first.* --------------------------------------------------------------------*//*================================================================*//* System Includes */#define __NO_VERSION__#include <linux/config.h>#define WLAN_DBVAR	prism2_debug#include <linux/version.h>#include <wlan/wlan_compat.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/slab.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>#if ((WLAN_HOSTIF == WLAN_PCMCIA) || (WLAN_HOSTIF == WLAN_PLX) || (WLAN_HOSTIF == WLAN_PCI))#error "This file is specific to USB"#endif#if (WLAN_HOSTIF == WLAN_USB)#include <linux/usb.h>#endif/*================================================================*//* Project Includes */#include <wlan/version.h>#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 <prism2/hfa384x.h>#include <prism2/prism2mgmt.h>/*================================================================*//* Local Constants */#define	DOWAIT		1#define DOASYNC		0/*================================================================*//* Local Macros */#define ROUNDUP64(a) (((a)%64)?((((a)/64)*64)+64):(a))/*================================================================*//* Local Types *//*================================================================*//* Local Static Definitions */extern int prism2_debug;/*================================================================*//* Local Function Declarations */#if 0static void dbprint_urb(struct urb* urb);#endifstatic int	hfa384x_rx_typedrop( wlandevice_t *wlandev, UINT16 fc);#if 0static voidhfa384x_rxmonitor( 	wlandevice_t *wlandev, 	UINT16 rxfid, 	hfa384x_rx_frame_t *rxdesc);#endif/*---------------------------------------------------*//* BULKOUT Callbacks */static void hfa384x_usbout_callback(struct urb *urb);/*---------------------------------------------------*//* BULKIN Callbacks */static void	hfa384x_usbin_callback(struct urb *urb);static voidhfa384x_usbin_txcompl(wlandevice_t *wlandev, hfa384x_usbin_t *usbin);static voidhfa384x_usbin_rx(wlandevice_t *wlandev, hfa384x_usbin_t *usbin);static voidhfa384x_usbin_info(wlandevice_t *wlandev, hfa384x_usbin_t *usbin);static voidhfa384x_usbout_tx(wlandevice_t *wlandev, hfa384x_usbout_t *usbout);static voidhfa384x_usbin_ctlx(wlandevice_t *wlandev, struct urb *urb);/*---------------------------------------------------*//* Functions to support the prism2 usb command queue */static hfa384x_usbctlx_t*hfa384x_usbctlxq_dequeue(hfa384x_usbctlxq_t *ctlxq);static void hfa384x_usbctlxq_enqueue_run(	hfa384x_usbctlxq_t *ctlxq,	hfa384x_usbctlx_t *ctlx);static void hfa384x_usbctlxq_run(hfa384x_usbctlxq_t *ctlxq);static void hfa384x_usbctlx_reqtimerfn(unsigned long data);static void hfa384x_usbctlx_resptimerfn(unsigned long data);static void hfa384x_usbctlx_submit_wait(	hfa384x_t		*hw, 	hfa384x_usbctlx_t	*ctlx);void hfa384x_usbctlx_submit_async(	hfa384x_t		*hw, 	hfa384x_usbctlx_t	*ctlx,	ctlx_usercb_t		usercb,	void			*usercb_data);static void hfa384x_usbctlx_complete(hfa384x_usbctlx_t *ctlx);static voidhfa384x_cbcmd(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx);static voidhfa384x_cbrrid(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx);static voidhfa384x_cbwrid(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx);static voidhfa384x_cbrmem(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx);static voidhfa384x_cbwmem(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx);/*---------------------------------------------------*//* Low level req/resp CTLX formatters and submitters */static inthfa384x_docmd( 	hfa384x_t *hw, 	UINT	wait,	UINT16	cmd, 	UINT16	parm0, 	UINT16	parm1, 	UINT16	parm2,	ctlx_usercb_t usercb,	void	*usercb_data);static inthfa384x_dorrid(	hfa384x_t *hw, 	UINT	wait,	UINT16	rid,	void	*riddata,	UINT	riddatalen,	ctlx_usercb_t usercb,	void	*usercb_data);static inthfa384x_dowrid(	hfa384x_t *hw, 	UINT	wait,	UINT16	rid,	void	*riddata,	UINT	riddatalen,	ctlx_usercb_t usercb,	void	*usercb_data);static inthfa384x_dormem(	hfa384x_t *hw, 	UINT	wait,	UINT16	page,	UINT16	offset,	void	*data,	UINT	len,	ctlx_usercb_t usercb,	void	*usercb_data);static inthfa384x_dowmem(	hfa384x_t *hw, 	UINT	wait,	UINT16	page,	UINT16	offset,	void	*data,	UINT	len,	ctlx_usercb_t usercb,	void	*usercb_data);static inthfa384x_isgood_pdrcode(UINT16 pdrcode);/*================================================================*//* Function Definitions */#if 0voiddbprint_urb(struct urb* urb){	WLAN_LOG_DEBUG1(3,"urb->pipe=0x%08x\n", urb->pipe);	WLAN_LOG_DEBUG1(3,"urb->status=0x%08x\n", urb->status);	WLAN_LOG_DEBUG1(3,"urb->transfer_flags=0x%08x\n", urb->transfer_flags);	WLAN_LOG_DEBUG1(3,"urb->transfer_buffer=0x%08x\n", (UINT)urb->transfer_buffer);	WLAN_LOG_DEBUG1(3,"urb->transfer_buffer_length=0x%08x\n", urb->transfer_buffer_length);	WLAN_LOG_DEBUG1(3,"urb->actual_length=0x%08x\n", urb->actual_length);	WLAN_LOG_DEBUG1(3,"urb->bandwidth=0x%08x\n", urb->bandwidth);	WLAN_LOG_DEBUG1(3,"urb->setup_packet(ctl)=0x%08x\n", (UINT)urb->setup_packet);	WLAN_LOG_DEBUG1(3,"urb->start_frame(iso/irq)=0x%08x\n", urb->start_frame);	WLAN_LOG_DEBUG1(3,"urb->interval(irq)=0x%08x\n", urb->interval);	WLAN_LOG_DEBUG1(3,"urb->error_count(iso)=0x%08x\n", urb->error_count);	WLAN_LOG_DEBUG1(3,"urb->timeout=0x%08x\n", urb->timeout);	WLAN_LOG_DEBUG1(3,"urb->context=0x%08x\n", (UINT)urb->context);	WLAN_LOG_DEBUG1(3,"urb->complete=0x%08x\n", (UINT)urb->complete);}#endif/*----------------------------------------------------------------* hfa384x_create** Sets up 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		i/o base address for register access*	membase		memory base address for register access** Returns: *	nothing** Side effects:** Call context:*	process ----------------------------------------------------------------*/voidhfa384x_create( hfa384x_t *hw, struct usb_device *usb, void *usbcontext){	DBFENTER;	memset(hw, 0, sizeof(hfa384x_t));	hw->usb = usb;	hw->usbcontext = usbcontext;  /* this is actually a wlandev */	/* Initialize the command queue */	spin_lock_init(&hw->ctlxq.lock);/* We need to make sure everything is set up to do USB transfers after this * function is complete. * Normally, Initialize will be called after this is set up. */		DBFEXIT;	return;}/*----------------------------------------------------------------* 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){	DBFENTER;	if ( hw->state == HFA384x_STATE_RUNNING ) {		hfa384x_drvr_stop(hw);	}	hw->state = HFA384x_STATE_PREINIT;						DBFEXIT;	return;}/*----------------------------------------------------------------* hfa384x_cbcmd** Ctlx_complete handler for async CMD type control exchanges.* mark the hw struct as such.** Note: If the handling is changed here, it should probably be *       changed in docmd as well.** Arguments:*	hw		hw struct*	ctlx		complete CTLX** Returns: *	nothing** Side effects:** Call context:*	interrupt----------------------------------------------------------------*/voidhfa384x_cbcmd(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx){	UINT				result;	hfa384x_async_cmdresult_t	cmdresult;	DBFENTER;	if ( ctlx->usercb != NULL ) {		memset(&cmdresult, 0, sizeof(cmdresult));		result = ctlx->state;		if (ctlx->state == HFA384x_USBCTLX_COMPLETE) {			cmdresult.status = 				hfa384x2host_16(ctlx->inbuf.cmdresp.status);			cmdresult.resp0 = 				hfa384x2host_16(ctlx->inbuf.cmdresp.resp0);			cmdresult.resp1 = 				hfa384x2host_16(ctlx->inbuf.cmdresp.resp1);			cmdresult.resp2 = 				hfa384x2host_16(ctlx->inbuf.cmdresp.resp2);		}			(*ctlx->usercb)(hw, result, &cmdresult, ctlx->usercb_data);	}	kfree(ctlx);	DBFEXIT;	return;}/*----------------------------------------------------------------* hfa384x_cbrrid** CTLX completion handler for async RRID type control exchanges.* * Note: If the handling is changed here, it should probably be *       changed in dowrid as well.** Arguments:*	hw		hw struct*	ctlx		complete CTLX** Returns: *	nothing** Side effects:** Call context:*	interrupt----------------------------------------------------------------*/voidhfa384x_cbrrid(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx){	UINT				result;	hfa384x_async_rridresult_t	rridresult;

⌨️ 快捷键说明

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