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

📄 hfa384x_usb.c

📁 uClinux2.6上兼容PRISM2.0芯片组的USB设备驱动程序.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* 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 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 <asm/bitops.h>#include <linux/list.h>#include <linux/usb.h>#include <wlan/wlan_compat.h>#if (WLAN_HOSTIF != WLAN_USB)#error "This file is specific to USB"#endif#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,69)static voidusb_init_urb(struct urb *urb){	memset(urb, 0, sizeof(*urb));#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) /* tune me! */	urb->count = (atomic_t)ATOMIC_INIT(1);#endif	spin_lock_init(&urb->lock);}#endif#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) /* tune me! */#  define SUBMIT_URB(u,f)  usb_submit_urb(u,f)#else#  define SUBMIT_URB(u,f)  usb_submit_urb(u)#endif/*================================================================*//* 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 */enum cmd_mode{  DOWAIT = 0,  DOASYNC};typedef enum cmd_mode CMD_MODE;#define THROTTLE_JIFFIES	(HZ/8)/*================================================================*//* Local Macros */#define ROUNDUP64(a) (((a)+63)&~63)/*================================================================*//* Local Types *//*================================================================*//* Local Static Definitions */extern int prism2_debug;/*================================================================*//* Local Function Declarations */#ifdef DEBUG_USBstatic void dbprint_urb(struct urb* urb);#endifstatic voidhfa384x_int_rxmonitor( 	wlandevice_t *wlandev, 	hfa384x_usb_rxfrm_t *rxfrm);static voidhfa384x_usb_defer(void *hw);static intsubmit_rx_urb(hfa384x_t *hw, int flags);static intsubmit_tx_urb(hfa384x_t *hw, struct urb *tx_urb, int flags);/*---------------------------------------------------*//* Callbacks */#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))static void hfa384x_usbout_callback(struct urb *urb);static voidhfa384x_ctlxout_callback(struct urb *urb);static void	hfa384x_usbin_callback(struct urb *urb);#elsestatic void hfa384x_usbout_callback(struct urb *urb, struct pt_regs *regs);static voidhfa384x_ctlxout_callback(struct urb *urb, struct pt_regs *regs);static void	hfa384x_usbin_callback(struct urb *urb, struct pt_regs *regs);#endifstatic voidhfa384x_usbin_txcompl(wlandevice_t *wlandev, hfa384x_usbin_t *usbin);static voidhfa384x_usbin_rx(wlandevice_t *wlandev, struct sk_buff *skb);static voidhfa384x_usbin_info(wlandevice_t *wlandev, hfa384x_usbin_t *usbin);static voidhfa384x_usbout_tx(wlandevice_t *wlandev, hfa384x_usbout_t *usbout);static void hfa384x_usbin_ctlx(hfa384x_t *hw, hfa384x_usbin_t *usbin, 			       int urb_status);/*---------------------------------------------------*//* Functions to support the prism2 usb command queue */static void hfa384x_usbctlxq_run(hfa384x_t *hw);static void hfa384x_usbctlx_reqtimerfn(unsigned long data);static void hfa384x_usbctlx_resptimerfn(unsigned long data);static voidhfa384x_usb_throttlefn(unsigned long data);static voidhfa384x_usbctlx_completion_task(unsigned long data);static voidhfa384x_usbctlx_reaper_task(unsigned long data);static inthfa384x_usbctlx_submit(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx);static void unlocked_usbctlx_complete(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx);struct usbctlx_completor{	int (*complete)(struct usbctlx_completor*);};typedef struct usbctlx_completor usbctlx_completor_t;static inthfa384x_usbctlx_complete_sync(hfa384x_t *hw,                              hfa384x_usbctlx_t *ctlx,                              usbctlx_completor_t *completor);static intunlocked_usbctlx_cancel_async(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx);static voidhfa384x_cb_status(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx);static voidhfa384x_cb_rrid(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx);static intusbctlx_get_status(const hfa384x_usb_cmdresp_t *cmdresp,                   hfa384x_cmdresult_t *result);static voidusbctlx_get_rridresult(const hfa384x_usb_rridresp_t *rridresp,                       hfa384x_rridresult_t *result);/*---------------------------------------------------*//* Low level req/resp CTLX formatters and submitters */static inthfa384x_docmd( 	hfa384x_t *hw, 	CMD_MODE mode,	hfa384x_metacmd_t *cmd,	ctlx_cmdcb_t cmdcb,	ctlx_usercb_t usercb,	void	*usercb_data);static inthfa384x_dorrid(	hfa384x_t *hw, 	CMD_MODE mode,	UINT16	rid,	void	*riddata,	UINT	riddatalen,	ctlx_cmdcb_t cmdcb,	ctlx_usercb_t usercb,	void	*usercb_data);static inthfa384x_dowrid(	hfa384x_t *hw, 	CMD_MODE mode,	UINT16	rid,	void	*riddata,	UINT	riddatalen,	ctlx_cmdcb_t cmdcb,	ctlx_usercb_t usercb,	void	*usercb_data);static inthfa384x_dormem(	hfa384x_t *hw, 	CMD_MODE mode,	UINT16	page,	UINT16	offset,	void	*data,	UINT	len,	ctlx_cmdcb_t cmdcb,	ctlx_usercb_t usercb,	void	*usercb_data);static inthfa384x_dowmem(	hfa384x_t *hw, 	CMD_MODE mode,	UINT16	page,	UINT16	offset,	void	*data,	UINT	len,	ctlx_cmdcb_t cmdcb,	ctlx_usercb_t usercb,	void	*usercb_data);static inthfa384x_isgood_pdrcode(UINT16 pdrcode);/*================================================================*//* Function Definitions */static inline const char* ctlxstr(CTLX_STATE s){	static const char* ctlx_str[] = {		"Initial state",		"Complete",		"Request failed",		"Request pending",		"Request packet submitted",		"Request packet completed",		"Response packet completed"	};	return ctlx_str[s];};static inline hfa384x_usbctlx_t*get_active_ctlx(hfa384x_t *hw){	return list_entry(hw->ctlxq.active.next, hfa384x_usbctlx_t, list);}#ifdef DEBUG_USBvoiddbprint_urb(struct urb* urb){	WLAN_LOG_DEBUG(3,"urb->pipe=0x%08x\n", urb->pipe);	WLAN_LOG_DEBUG(3,"urb->status=0x%08x\n", urb->status);	WLAN_LOG_DEBUG(3,"urb->transfer_flags=0x%08x\n", urb->transfer_flags);	WLAN_LOG_DEBUG(3,"urb->transfer_buffer=0x%08x\n", (UINT)urb->transfer_buffer);	WLAN_LOG_DEBUG(3,"urb->transfer_buffer_length=0x%08x\n", urb->transfer_buffer_length);	WLAN_LOG_DEBUG(3,"urb->actual_length=0x%08x\n", urb->actual_length);	WLAN_LOG_DEBUG(3,"urb->bandwidth=0x%08x\n", urb->bandwidth);	WLAN_LOG_DEBUG(3,"urb->setup_packet(ctl)=0x%08x\n", (UINT)urb->setup_packet);	WLAN_LOG_DEBUG(3,"urb->start_frame(iso/irq)=0x%08x\n", urb->start_frame);	WLAN_LOG_DEBUG(3,"urb->interval(irq)=0x%08x\n", urb->interval);	WLAN_LOG_DEBUG(3,"urb->error_count(iso)=0x%08x\n", urb->error_count);	WLAN_LOG_DEBUG(3,"urb->timeout=0x%08x\n", urb->timeout);	WLAN_LOG_DEBUG(3,"urb->context=0x%08x\n", (UINT)urb->context);	WLAN_LOG_DEBUG(3,"urb->complete=0x%08x\n", (UINT)urb->complete);}#endif/*----------------------------------------------------------------* submit_rx_urb** Listen for input data on the BULK-IN pipe. If the pipe has* stalled then schedule it to be reset.** Arguments:*	hw		device struct*	memflags	memory allocation flags** Returns:*	error code from submission** Call context:*	Any----------------------------------------------------------------*/static intsubmit_rx_urb(hfa384x_t *hw, int memflags){	struct sk_buff *skb;	int result;	DBFENTER;		skb = dev_alloc_skb(sizeof(hfa384x_usbin_t));	if (skb == NULL) {		result = -ENOMEM;		goto done;	}		/* Post the IN urb */	usb_fill_bulk_urb(&hw->rx_urb, hw->usb,	              hw->endp_in,	              skb->data, sizeof(hfa384x_usbin_t),	              hfa384x_usbin_callback, hw->wlandev);	hw->rx_urb_skb = skb;	result = -ENOLINK;	if ( !hw->wlandev->hwremoved && !test_bit(WORK_RX_HALT, &hw->usb_flags)) {		result = SUBMIT_URB(&hw->rx_urb, memflags);		/* Check whether we need to reset the RX pipe */		if (result == -EPIPE) {			WLAN_LOG_WARNING("%s rx pipe stalled: requesting reset\n",			                 hw->wlandev->netdev->name);			if ( !test_and_set_bit(WORK_RX_HALT, &hw->usb_flags) )				schedule_work(&hw->usb_work);		}	}	/* Don't leak memory if anything should go wrong */	if (result != 0) {		dev_kfree_skb(skb);		skb = NULL;		hw->rx_urb_skb = NULL;	} done:	DBFEXIT;	return result;}/*----------------------------------------------------------------* submit_tx_urb** Prepares and submits the URB of transmitted data. If the* submission fails then it will schedule the output pipe to* be reset.** Arguments:*	hw		device struct*	tx_urb		URB of data for tranmission*	memflags	memory allocation flags** Returns:*	error code from submission** Call context:*	Any----------------------------------------------------------------*/static intsubmit_tx_urb(hfa384x_t *hw, struct urb *tx_urb, int memflags){	struct net_device *netdev = hw->wlandev->netdev;	int result;

⌨️ 快捷键说明

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